aboutsummaryrefslogtreecommitdiffstats
path: root/e-util
diff options
context:
space:
mode:
Diffstat (limited to 'e-util')
-rw-r--r--e-util/Makefile.am24
-rw-r--r--e-util/e-account-utils.c96
-rw-r--r--e-util/e-account-utils.h (renamed from e-util/e-corba-utils.c)36
-rw-r--r--e-util/e-dialog-utils.c26
-rw-r--r--e-util/e-dialog-utils.h2
-rw-r--r--e-util/e-logger.c76
-rw-r--r--e-util/e-logger.h26
-rw-r--r--e-util/e-marshal.list1
-rw-r--r--e-util/e-module.c318
-rw-r--r--e-util/e-module.h81
-rw-r--r--e-util/e-non-intrusive-error-dialog.c1
-rw-r--r--e-util/e-non-intrusive-error-dialog.h2
-rw-r--r--e-util/e-plugin-ui.c438
-rw-r--r--e-util/e-plugin-ui.h9
-rw-r--r--e-util/e-signature-utils.c347
-rw-r--r--e-util/e-signature-utils.h (renamed from e-util/e-corba-utils.h)31
-rw-r--r--e-util/e-unicode.c2052
-rw-r--r--e-util/e-unicode.h113
-rw-r--r--e-util/e-util-labels.c586
-rw-r--r--e-util/e-util-labels.h57
-rw-r--r--e-util/e-util.c45
-rw-r--r--e-util/e-util.h14
-rw-r--r--e-util/gconf-bridge.c6
23 files changed, 3463 insertions, 924 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 367a9c79d7..934c20b593 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -4,7 +4,6 @@ ecpsdir = $(privdatadir)/ecps
ruledir = $(privdatadir)
if OS_WIN32
-WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libemiscwidgets.la
PLATFORM_SOURCES = e-win32-reloc.c
endif
@@ -34,18 +33,18 @@ INCLUDES = \
-DSEARCH_RULE_DIR=\"$(ruledir)\" \
-DG_LOG_DOMAIN=\"e-utils\" \
$(GNOME_PILOT_CFLAGS) \
- $(ICONV_CFLAGS) \
+ $(ICONV_CFLAGS) \
$(E_UTIL_CFLAGS)
privsolib_LTLIBRARIES = libeutil.la libeconduit.la
eutilinclude_HEADERS = \
+ e-account-utils.h \
e-bconf-map.h \
e-binding.h \
e-categories-config.h \
e-config.h \
e-config-listener.h \
- e-corba-utils.h \
e-cursor.h \
e-dialog-utils.h \
e-dialog-widgets.h \
@@ -57,10 +56,11 @@ eutilinclude_HEADERS = \
e-icon-factory.h \
e-import.h \
e-logger.h \
- e-non-intrusive-error-dialog.h \
e-marshal.h \
e-menu.h \
e-mktemp.h \
+ e-module.h \
+ e-non-intrusive-error-dialog.h \
e-print.h \
e-plugin.h \
e-plugin-ui.h \
@@ -69,6 +69,7 @@ eutilinclude_HEADERS = \
e-request.h \
e-signature.h \
e-signature-list.h \
+ e-signature-utils.h \
e-bit-array.h \
e-sorter.h \
e-sorter-array.h \
@@ -76,17 +77,17 @@ eutilinclude_HEADERS = \
e-text-event-processor-types.h \
e-text-event-processor.h \
e-util.h \
- e-util-labels.h \
+ e-unicode.h \
e-xml-utils.h
libeutil_la_SOURCES = \
$(eutilinclude_HEADERS) \
+ e-account-utils.c \
e-bconf-map.c \
e-binding.c \
e-categories-config.c \
- e-config.c \
e-config-listener.c \
- e-corba-utils.c \
+ e-config.c \
e-cursor.c \
e-dialog-utils.c \
e-dialog-widgets.c \
@@ -98,25 +99,27 @@ libeutil_la_SOURCES = \
e-icon-factory.c \
e-import.c \
e-logger.c \
- e-non-intrusive-error-dialog.c \
e-marshal.c \
e-menu.c \
e-mktemp.c \
- e-plugin.c \
+ e-module.c \
+ e-non-intrusive-error-dialog.c \
e-plugin-ui.c \
+ e-plugin.c \
e-popup.c \
e-print.c \
e-profile-event.c \
e-request.c \
e-signature.c \
e-signature-list.c \
+ e-signature-utils.c \
e-bit-array.c \
e-sorter.c \
e-sorter-array.c \
e-text-event-processor-emacs-like.c \
e-text-event-processor.c \
e-util.c \
- e-util-labels.c \
+ e-unicode.c \
e-util-private.h \
e-xml-utils.c \
gconf-bridge.c \
@@ -129,7 +132,6 @@ MARSHAL_GENERATED = e-marshal.c e-marshal.h
libeutil_la_LDFLAGS = $(NO_UNDEFINED)
libeutil_la_LIBADD = \
- $(WIN32_BOOTSTRAP_LIBS) \
$(ICONV_LIBS) \
$(E_UTIL_LIBS) \
$(GNOME_PILOT_LIBS) \
diff --git a/e-util/e-account-utils.c b/e-util/e-account-utils.c
new file mode 100644
index 0000000000..d98a378b48
--- /dev/null
+++ b/e-util/e-account-utils.c
@@ -0,0 +1,96 @@
+/*
+ * 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/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ */
+
+#include "e-account-utils.h"
+
+#include <gconf/gconf-client.h>
+
+static EAccountList *global_account_list;
+
+EAccountList *
+e_get_account_list (void)
+{
+ if (G_UNLIKELY (global_account_list == NULL)) {
+ GConfClient *client;
+
+ client = gconf_client_get_default ();
+ global_account_list = e_account_list_new (client);
+ g_object_unref (client);
+ }
+
+ g_return_val_if_fail (global_account_list != NULL, NULL);
+
+ return global_account_list;
+}
+
+EAccount *
+e_get_default_account (void)
+{
+ EAccountList *account_list;
+ const EAccount *account;
+
+ account_list = e_get_account_list ();
+ account = e_account_list_get_default (account_list);
+
+ /* XXX EAccountList misuses const. */
+ return (EAccount *) account;
+}
+
+void
+e_set_default_account (EAccount *account)
+{
+ EAccountList *account_list;
+
+ g_return_if_fail (E_IS_ACCOUNT (account));
+
+ account_list = e_get_account_list ();
+ e_account_list_set_default (account_list, account);
+}
+
+EAccount *
+e_get_account_by_name (const gchar *name)
+{
+ EAccountList *account_list;
+ const EAccount *account;
+ e_account_find_t find;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ find = E_ACCOUNT_FIND_NAME;
+ account_list = e_get_account_list ();
+ account = e_account_list_find (account_list, find, name);
+
+ /* XXX EAccountList misuses const. */
+ return (EAccount *) account;
+}
+
+EAccount *
+e_get_account_by_uid (const gchar *uid)
+{
+ EAccountList *account_list;
+ const EAccount *account;
+ e_account_find_t find;
+
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ find = E_ACCOUNT_FIND_UID;
+ account_list = e_get_account_list ();
+ account = e_account_list_find (account_list, find, uid);
+
+ /* XXX EAccountList misuses const. */
+ return (EAccount *) account;
+}
diff --git a/e-util/e-corba-utils.c b/e-util/e-account-utils.h
index 0288602a7e..24262349d2 100644
--- a/e-util/e-corba-utils.c
+++ b/e-util/e-account-utils.h
@@ -12,32 +12,24 @@
* 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:
- * Ettore Perazzoli <ettore@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#ifndef E_ACCOUNT_UTILS_H
+#define E_ACCOUNT_UTILS_H
+
+#include <glib.h>
+#include <libedataserver/e-account.h>
+#include <libedataserver/e-account-list.h>
-#include "e-corba-utils.h"
+G_BEGIN_DECLS
-
-const CORBA_char *
-e_safe_corba_string (const char *s)
-{
- if (s == NULL)
- return (CORBA_char *) "";
+EAccountList * e_get_account_list (void);
+EAccount * e_get_default_account (void);
+void e_set_default_account (EAccount *account);
+EAccount * e_get_account_by_name (const gchar *name);
+EAccount * e_get_account_by_uid (const gchar *uid);
- return s;
-}
+G_END_DECLS
-CORBA_char *
-e_safe_corba_string_dup (const char *s)
-{
- return CORBA_string_dup (e_safe_corba_string (s));
-}
+#endif /* E_ACCOUNT_UTILS_H */
diff --git a/e-util/e-dialog-utils.c b/e-util/e-dialog-utils.c
index 0546430512..7d1d4836b6 100644
--- a/e-util/e-dialog-utils.c
+++ b/e-util/e-dialog-utils.c
@@ -344,29 +344,29 @@ e_file_dialog_save_folder (const char *title)
* no signals connected and is not shown.
**/
GtkWidget *
-e_file_get_save_filesel (GtkWidget *parent, const char *title, const char *name, GtkFileChooserAction action)
+e_file_get_save_filesel (GtkWindow *parent, const char *title, const char *name, GtkFileChooserAction action)
{
GtkWidget *filesel;
char *uri;
- filesel = gtk_file_chooser_dialog_new (title,
- NULL,
- action,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- (action == GTK_FILE_CHOOSER_ACTION_OPEN) ? GTK_STOCK_OPEN:GTK_STOCK_SAVE, GTK_RESPONSE_OK,
- NULL);
+ g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
+
+ filesel = gtk_file_chooser_dialog_new (
+ title, parent, action,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ (action == GTK_FILE_CHOOSER_ACTION_OPEN) ?
+ GTK_STOCK_OPEN : GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
gtk_dialog_set_default_response (GTK_DIALOG (filesel), GTK_RESPONSE_OK);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (filesel), FALSE);
- if (parent)
- e_dialog_set_transient_for((GtkWindow *)filesel, parent);
-
- uri = e_file_get_save_path();
+ uri = e_file_get_save_path ();
- gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (filesel), uri);
+ gtk_file_chooser_set_current_folder_uri (
+ GTK_FILE_CHOOSER (filesel), uri);
if (name && name[0])
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filesel), name);
+ gtk_file_chooser_set_current_name (
+ GTK_FILE_CHOOSER (filesel), name);
g_free (uri);
diff --git a/e-util/e-dialog-utils.h b/e-util/e-dialog-utils.h
index 9d594122e2..9e6e7992c1 100644
--- a/e-util/e-dialog-utils.h
+++ b/e-util/e-dialog-utils.h
@@ -43,7 +43,7 @@ char *e_file_dialog_save (const char *title, const char *fname)
char *e_file_dialog_save_folder (const char *title);
-GtkWidget * e_file_get_save_filesel (GtkWidget *parent, const char *title, const char *name, GtkFileChooserAction action);
+GtkWidget * e_file_get_save_filesel (GtkWindow *parent, const char *title, const char *name, GtkFileChooserAction action);
gboolean e_file_can_save(GtkWindow *parent, const char *uri);
gboolean e_file_check_local(const char *name);
diff --git a/e-util/e-logger.c b/e-util/e-logger.c
index 0a458b7444..97d27d03cf 100644
--- a/e-util/e-logger.c
+++ b/e-util/e-logger.c
@@ -43,7 +43,7 @@
((obj), E_TYPE_LOGGER, ELoggerPrivate))
struct _ELoggerPrivate {
- gchar *component;
+ gchar *name;
gchar *logfile;
FILE *fp;
@@ -52,13 +52,13 @@ struct _ELoggerPrivate {
enum {
PROP_0,
- PROP_COMPONENT
+ PROP_NAME
};
static gpointer parent_class;
static gboolean
-flush_logfile (ELogger *logger)
+logger_flush (ELogger *logger)
{
if (logger->priv->fp)
fflush (logger->priv->fp);
@@ -68,16 +68,26 @@ flush_logfile (ELogger *logger)
}
static void
-logger_set_component (ELogger *logger,
- const gchar *component)
+logger_set_dirty (ELogger *logger)
+{
+ if (logger->priv->timer)
+ return;
+
+ logger->priv->timer = g_timeout_add (
+ TIMEOUT_INTERVAL, (GSourceFunc) logger_flush, logger);
+}
+
+static void
+logger_set_name (ELogger *logger,
+ const gchar *name)
{
gchar *temp;
- g_return_if_fail (logger->priv->component == NULL);
+ g_return_if_fail (logger->priv->name == NULL);
- temp = g_strdup_printf ("%s.log.XXXXXX", component);
+ temp = g_strdup_printf ("%s.log.XXXXXX", name);
- logger->priv->component = g_strdup (component);
+ logger->priv->name = g_strdup (name);
logger->priv->logfile = e_mktemp (temp);
logger->priv->fp = g_fopen (logger->priv->logfile, "w");
logger->priv->timer = 0;
@@ -95,8 +105,8 @@ logger_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_COMPONENT:
- logger_set_component (
+ case PROP_NAME:
+ logger_set_name (
E_LOGGER (object),
g_value_get_string (value));
return;
@@ -112,9 +122,9 @@ logger_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_COMPONENT:
+ case PROP_NAME:
g_value_set_string (
- value, e_logger_get_component (
+ value, e_logger_get_name (
E_LOGGER (object)));
return;
}
@@ -129,11 +139,11 @@ logger_finalize (GObject *object)
if (logger->priv->timer)
g_source_remove (logger->priv->timer);
- flush_logfile (logger);
+ logger_flush (logger);
if (logger->priv->fp)
fclose (logger->priv->fp);
- g_free (logger->priv->component);
+ g_free (logger->priv->name);
g_free (logger->priv->logfile);
/* Chain up to parent's finalize() method. */
@@ -155,11 +165,11 @@ logger_class_init (ELoggerClass *class)
g_object_class_install_property (
object_class,
- PROP_COMPONENT,
+ PROP_NAME,
g_param_spec_string (
- "component",
- _("Component"),
- _("Name of the component being logged"),
+ "name",
+ _("Name"),
+ _("Name of the logger"),
"anonymous",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
@@ -198,34 +208,24 @@ e_logger_get_type (void)
}
ELogger *
-e_logger_create (gchar *component)
+e_logger_new (const gchar *name)
{
- g_return_val_if_fail (component != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
- return g_object_new (E_TYPE_LOGGER, "component", component, NULL);
+ return g_object_new (E_TYPE_LOGGER, "name", name, NULL);
}
const gchar *
-e_logger_get_component (ELogger *logger)
+e_logger_get_name (ELogger *logger)
{
g_return_val_if_fail (E_IS_LOGGER (logger), NULL);
- return logger->priv->component;
-}
-
-static void
-set_dirty (ELogger *logger)
-{
- if (logger->priv->timer)
- return;
-
- logger->priv->timer = g_timeout_add_seconds (
- TIMEOUT_INTERVAL, (GSourceFunc) flush_logfile, logger);
+ return logger->priv->name;
}
void
e_logger_log (ELogger *logger,
- gint level,
+ ELogLevel level,
gchar *primary,
gchar *secondary)
{
@@ -240,13 +240,13 @@ e_logger_log (ELogger *logger,
fprintf (logger->priv->fp, "%d:%ld:%s\n", level, t, primary);
fprintf (logger->priv->fp, "%d:%ld:%s\n", level, t, secondary);
- set_dirty (logger);
+ logger_set_dirty (logger);
}
void
e_logger_get_logs (ELogger *logger,
ELogFunction func,
- gpointer data)
+ gpointer user_data)
{
FILE *fp;
gchar buf[250];
@@ -288,11 +288,11 @@ e_logger_get_logs (ELogger *logger,
g_string_append (str, tmp);
}
- func (str->str, data);
+ func (str->str, user_data);
g_string_free (str, TRUE);
} else
- func (tmp, data);
+ func (tmp, user_data);
}
fclose (fp);
diff --git a/e-util/e-logger.h b/e-util/e-logger.h
index f7dfd8017e..ce595d691c 100644
--- a/e-util/e-logger.h
+++ b/e-util/e-logger.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef __E_LOGGER_H__
-#define __E_LOGGER_H__
+#ifndef E_LOGGER_H
+#define E_LOGGER_H
#include <glib-object.h>
@@ -52,34 +52,32 @@ typedef struct _ELoggerPrivate ELoggerPrivate;
typedef void (*ELogFunction) (gchar *line, gpointer data);
-enum e_log_level_t {
+typedef enum {
E_LOG_ERROR,
- E_LOG_WARNINGS,
+ E_LOG_WARNING,
E_LOG_DEBUG
-};
+} ELogLevel;
-/* The object */
struct _ELogger {
GObject parent;
-
- struct _ELoggerPrivate *priv;
+ ELoggerPrivate *priv;
};
struct _ELoggerClass {
- GObjectClass popup_class;
+ GObjectClass parent_class;
};
GType e_logger_get_type (void);
-ELogger * e_logger_create (gchar *component);
-const gchar * e_logger_get_component (ELogger *logger);
+ELogger * e_logger_new (const gchar *name);
+const gchar * e_logger_get_name (ELogger *logger);
void e_logger_log (ELogger *logger,
- gint level,
+ ELogLevel level,
gchar *primary,
gchar *secondary);
void e_logger_get_logs (ELogger *logger,
ELogFunction func,
- gpointer data);
+ gpointer user_data);
G_END_DECLS
-#endif /* __E_LOGGER_H__ */
+#endif /* E_LOGGER_H */
diff --git a/e-util/e-marshal.list b/e-util/e-marshal.list
index 366602491b..b667ca4a84 100644
--- a/e-util/e-marshal.list
+++ b/e-util/e-marshal.list
@@ -66,3 +66,4 @@ NONE:STRING,STRING,STRING
NONE:STRING,STRING,UINT
OBJECT:OBJECT,DOUBLE,DOUBLE,BOOLEAN
POINTER:NONE
+STRING:NONE
diff --git a/e-util/e-module.c b/e-util/e-module.c
new file mode 100644
index 0000000000..51e1e18bd6
--- /dev/null
+++ b/e-util/e-module.c
@@ -0,0 +1,318 @@
+/*
+ * e-module.c
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-module.h"
+
+#include <glib/gi18n.h>
+
+/* This is the symbol we call when loading a module. */
+#define LOAD_SYMBOL "e_module_load"
+
+/* This is the symbol we call when unloading a module. */
+#define UNLOAD_SYMBOL "e_module_unload"
+
+#define E_MODULE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MODULE, EModulePrivate))
+
+struct _EModulePrivate {
+ GModule *module;
+ gchar *filename;
+
+ void (*load) (GTypeModule *type_module);
+ void (*unload) (GTypeModule *type_module);
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME
+};
+
+static gpointer parent_class;
+
+static void
+module_set_filename (EModule *module,
+ const gchar *filename)
+{
+ g_return_if_fail (module->priv->filename == NULL);
+
+ module->priv->filename = g_strdup (filename);
+}
+
+static void
+module_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_FILENAME:
+ module_set_filename (
+ E_MODULE (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+module_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_FILENAME:
+ g_value_set_string (
+ value, e_module_get_filename (
+ E_MODULE (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+module_finalize (GObject *object)
+{
+ EModulePrivate *priv;
+
+ priv = E_MODULE_GET_PRIVATE (object);
+
+ g_free (priv->filename);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+module_load (GTypeModule *type_module)
+{
+ EModulePrivate *priv;
+ gpointer symbol;
+
+ priv = E_MODULE_GET_PRIVATE (type_module);
+
+ g_return_val_if_fail (priv->filename != NULL, FALSE);
+ priv->module = g_module_open (priv->filename, 0);
+
+ if (priv->module == NULL)
+ goto fail;
+
+ if (!g_module_symbol (priv->module, LOAD_SYMBOL, &symbol))
+ goto fail;
+
+ priv->load = symbol;
+
+ if (!g_module_symbol (priv->module, UNLOAD_SYMBOL, &symbol))
+ goto fail;
+
+ priv->unload = symbol;
+
+ priv->load (type_module);
+
+ return TRUE;
+
+fail:
+ g_warning ("%s", g_module_error ());
+
+ if (priv->module != NULL)
+ g_module_close (priv->module);
+
+ return FALSE;
+}
+
+static void
+module_unload (GTypeModule *type_module)
+{
+ EModulePrivate *priv;
+
+ priv = E_MODULE_GET_PRIVATE (type_module);
+
+ priv->unload (type_module);
+
+ g_module_close (priv->module);
+ priv->module = NULL;
+
+ priv->load = NULL;
+ priv->unload = NULL;
+}
+
+static void
+module_class_init (EModuleClass *class)
+{
+ GObjectClass *object_class;
+ GTypeModuleClass *type_module_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EModulePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = module_set_property;
+ object_class->get_property = module_get_property;
+ object_class->finalize = module_finalize;
+
+ type_module_class = G_TYPE_MODULE_CLASS (class);
+ type_module_class->load = module_load;
+ type_module_class->unload = module_unload;
+
+ /**
+ * EModule:filename
+ *
+ * The filename of the module.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FILENAME,
+ g_param_spec_string (
+ "filename",
+ _("Filename"),
+ _("The filename of the module"),
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+module_init (EModule *module)
+{
+ module->priv = E_MODULE_GET_PRIVATE (module);
+}
+
+GType
+e_module_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EModuleClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) module_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EModule),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) module_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_TYPE_MODULE, "EModule", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * e_module_new:
+ * @filename: filename of the shared library module
+ *
+ * Creates a new #EModule that will load the specific shared library
+ * when in use.
+ *
+ * Returns: a new #EModule for @filename
+ **/
+EModule *
+e_module_new (const gchar *filename)
+{
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ return g_object_new (E_TYPE_MODULE, "filename", filename, NULL);
+}
+
+/**
+ * e_module_get_filename:
+ * @module: an #EModule
+ *
+ * Returns the filename of the shared library for @module. The
+ * string is owned by @module and should not be modified or freed.
+ *
+ * Returns: the filename for @module
+ **/
+const gchar *
+e_module_get_filename (EModule *module)
+{
+ g_return_val_if_fail (E_IS_MODULE (module), NULL);
+
+ return module->priv->filename;
+}
+
+/**
+ * e_module_load_all_in_directory:
+ * @dirname: pathname for a directory containing modules to load
+ *
+ * Loads all the modules in the specified directory into memory. If
+ * you want to unload them (enabling on-demand loading) you must call
+ * g_type_module_unuse() on all the modules. Free the returned list
+ * with g_list_free().
+ *
+ * Returns: a list of #EModules loaded from @dirname
+ **/
+GList *
+e_module_load_all_in_directory (const gchar *dirname)
+{
+ GDir *dir;
+ const gchar *basename;
+ GList *loaded_modules = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (dirname != NULL, NULL);
+
+ if (!g_module_supported ())
+ return NULL;
+
+ dir = g_dir_open (dirname, 0, &error);
+ if (dir == NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ while ((basename = g_dir_read_name (dir)) != NULL) {
+ EModule *module;
+ gchar *filename;
+
+ if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX))
+ continue;
+
+ filename = g_build_filename (dirname, basename, NULL);
+
+ module = e_module_new (filename);
+
+ if (!g_type_module_use (G_TYPE_MODULE (module))) {
+ g_printerr ("Failed to load module: %s\n", filename);
+ g_object_unref (module);
+ g_free (filename);
+ continue;
+ }
+
+ g_free (filename);
+
+ loaded_modules = g_list_prepend (loaded_modules, module);
+ }
+
+ g_dir_close (dir);
+
+ return loaded_modules;
+}
diff --git a/e-util/e-module.h b/e-util/e-module.h
new file mode 100644
index 0000000000..022769dc1c
--- /dev/null
+++ b/e-util/e-module.h
@@ -0,0 +1,81 @@
+/*
+ * e-module.h
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/**
+ * SECTION: e-module
+ * @short_description: generic module loader
+ * @include: e-util/e-module.h
+ **/
+
+#ifndef E_MODULE_H
+#define E_MODULE_H
+
+#include <gmodule.h>
+#include <glib-object.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MODULE \
+ (e_module_get_type ())
+#define E_MODULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MODULE, EModule))
+#define E_MODULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MODULE, EModuleClass))
+#define E_IS_MODULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MODULE))
+#define E_IS_MODULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MODULE))
+#define E_MODULE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MODULE, EModuleClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EModule EModule;
+typedef struct _EModuleClass EModuleClass;
+typedef struct _EModulePrivate EModulePrivate;
+
+/**
+ * EModule:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ **/
+struct _EModule {
+ GTypeModule parent;
+ EModulePrivate *priv;
+};
+
+struct _EModuleClass {
+ GTypeModuleClass parent_class;
+};
+
+GType e_module_get_type (void);
+EModule * e_module_new (const gchar *filename);
+const gchar * e_module_get_filename (EModule *module);
+GList * e_module_load_all_in_directory (const gchar *dirname);
+
+G_END_DECLS
+
+#endif /* E_MODULE_H */
diff --git a/e-util/e-non-intrusive-error-dialog.c b/e-util/e-non-intrusive-error-dialog.c
index 070c1e9bef..5fd98cacd2 100644
--- a/e-util/e-non-intrusive-error-dialog.c
+++ b/e-util/e-non-intrusive-error-dialog.c
@@ -305,4 +305,3 @@ eni_show_logger(ELogger *logger, GtkWidget *top,const char *error_timeout_path,
gtk_widget_show_all (window);
}
-
diff --git a/e-util/e-non-intrusive-error-dialog.h b/e-util/e-non-intrusive-error-dialog.h
index e801d47a52..159242c0fa 100644
--- a/e-util/e-non-intrusive-error-dialog.h
+++ b/e-util/e-non-intrusive-error-dialog.h
@@ -38,7 +38,7 @@ struct _log_data {
GdkPixbuf *pbuf;
} ldata [] = {
{ E_LOG_ERROR, N_("Error"), N_("Errors"), GTK_STOCK_DIALOG_ERROR },
- { E_LOG_WARNINGS, N_("Warning"), N_("Warnings and Errors"), GTK_STOCK_DIALOG_WARNING },
+ { E_LOG_WARNING, N_("Warning"), N_("Warnings and Errors"), GTK_STOCK_DIALOG_WARNING },
{ E_LOG_DEBUG, N_("Debug"), N_("Error, Warnings and Debug messages"), GTK_STOCK_DIALOG_INFO }
};
diff --git a/e-util/e-plugin-ui.c b/e-util/e-plugin-ui.c
index c3ee13fe60..099efd0d65 100644
--- a/e-util/e-plugin-ui.c
+++ b/e-util/e-plugin-ui.c
@@ -25,7 +25,6 @@
#define E_PLUGIN_UI_INIT_FUNC "e_plugin_ui_init"
#define E_PLUGIN_UI_HOOK_CLASS_ID "org.gnome.evolution.ui:1.0"
-#define E_PLUGIN_UI_MANAGER_ID_KEY "e-plugin-ui-manager-id"
struct _EPluginUIHookPrivate {
@@ -33,9 +32,11 @@ struct _EPluginUIHookPrivate {
*
* For example:
*
- * <ui-manager id="org.gnome.evolution.sample">
- * ... UI definition ...
- * </ui-manager>
+ * <hook class="org.gnome.evolution.ui:1.0">
+ * <ui-manager id="org.gnome.evolution.sample">
+ * ... UI definition ...
+ * </ui-manager>
+ * </hook>
*
* Results in:
*
@@ -49,197 +50,310 @@ struct _EPluginUIHookPrivate {
* optional.
*/
GHashTable *ui_definitions;
+
+ /* The registry is the heart of EPluginUI. It tracks GtkUIManager
+ * instances, GtkUIManager IDs, and UI merge IDs as a hash table of
+ * hash tables:
+ *
+ * GtkUIManager instance -> GtkUIManager ID -> UI Merge ID
+ *
+ * A GtkUIManager instance and ID form a unique key for looking up
+ * UI merge IDs. The reason both are needed is because the same
+ * GtkUIManager instance and be registered under multiple IDs.
+ *
+ * This is done primarily to support shell views, which share a
+ * common GtkUIManager instance for a particular shell window.
+ * Each shell view registers the same GtkUIManager instance under
+ * a unique ID:
+ *
+ * "org.gnome.evolution.mail" }
+ * "org.gnome.evolution.contacts" } aliases for a common
+ * "org.gnome.evolution.calendar" } GtkUIManager instance
+ * "org.gnome.evolution.memos" }
+ * "org.gnome.evolution.tasks" }
+ *
+ * Note: The shell window also registers the same GtkUIManager
+ * instance as "org.gnome.evolution.shell".
+ *
+ * This way, plugins that extend a shell view's UI will follow the
+ * merging and unmerging of the shell view automatically.
+ *
+ * The presence or absence of GtkUIManager IDs in the registry is
+ * significant. Presence of a (instance, ID) pair indicates that
+ * UI manager is active, absence indicates inactive. Furthermore,
+ * a non-zero merge ID for an active UI manager indicates the
+ * plugin is enabled. Zero indicates disabled.
+ *
+ * Here's a quick scenario to illustrate:
+ *
+ * Suppose we have a plugin that extends the mail shell view UI.
+ * Its EPlugin definition file has this section:
+ *
+ * <hook class="org.gnome.evolution.ui:1.0">
+ * <ui-manager id="org.gnome.evolution.mail">
+ * ... UI definition ...
+ * </ui-manager>
+ * </hook>
+ *
+ * The plugin is enabled and the active shell view is "mail".
+ * Let "ManagerA" denote the common GtkUIManager instance for
+ * this shell window. Here's what happens to the registry as
+ * the user performs various actions;
+ *
+ * - Initial State Merge ID
+ * V
+ * { "ManagerA", { "org.gnome.evolution.mail", 3 } }
+ *
+ * - User Disables the Plugin
+ *
+ * { "ManagerA", { "org.gnome.evolution.mail", 0 } }
+ *
+ * - User Enables the Plugin
+ *
+ * { "ManagerA", { "org.gnome.evolution.mail", 4 } }
+ *
+ * - User Switches to Calendar View
+ *
+ * { "ManagerA", { } }
+ *
+ * - User Disables the Plugin
+ *
+ * { "ManagerA", { } }
+ *
+ * - User Switches to Mail View
+ *
+ * { "ManagerA", { "org.gnome.evolution.mail", 0 } }
+ *
+ * - User Enables the Plugin
+ *
+ * { "ManagerA", { "org.gnome.evolution.mail", 5 } }
+ */
+ GHashTable *registry;
};
-/* The registry is a hash table of hash tables. It maps
- *
- * EPluginUIHook instance --> GtkUIManager instance --> UI merge id
- *
- * GtkUIManager instances are automatically removed when finalized.
- */
-static GHashTable *registry;
static gpointer parent_class;
static void
-plugin_ui_registry_remove (EPluginUIHook *hook,
- GtkUIManager *ui_manager)
+plugin_ui_hook_unregister_manager (EPluginUIHook *hook,
+ GtkUIManager *ui_manager)
{
- GHashTable *hash_table;
+ GHashTable *registry;
/* Note: Manager may already be finalized. */
-
- hash_table = g_hash_table_lookup (registry, hook);
- g_return_if_fail (hash_table != NULL);
-
- g_hash_table_remove (hash_table, ui_manager);
- if (g_hash_table_size (hash_table) == 0)
- g_hash_table_remove (registry, hook);
+ registry = hook->priv->registry;
+ g_hash_table_remove (registry, ui_manager);
}
static void
-plugin_ui_registry_insert (EPluginUIHook *hook,
- GtkUIManager *ui_manager,
- guint merge_id)
+plugin_ui_hook_register_manager (EPluginUIHook *hook,
+ GtkUIManager *ui_manager,
+ gpointer user_data)
{
+ EPlugin *plugin;
+ EPluginUIInitFunc func;
+ GHashTable *registry;
GHashTable *hash_table;
- hash_table = g_hash_table_lookup (registry, hook);
- if (hash_table == NULL) {
- hash_table = g_hash_table_new (g_direct_hash, g_direct_equal);
- g_hash_table_insert (registry, hook, hash_table);
- }
+ plugin = ((EPluginHook *) hook)->plugin;
+ func = e_plugin_get_symbol (plugin, E_PLUGIN_UI_INIT_FUNC);
+
+ /* Pass the manager and user_data to the plugin's e_plugin_ui_init()
+ * function (if it defined one). The plugin should install whatever
+ * GtkActions and GtkActionGroups are neccessary to implement the
+ * action names in its UI definition. */
+ if (func != NULL && !func (ui_manager, user_data))
+ return;
g_object_weak_ref (
G_OBJECT (ui_manager), (GWeakNotify)
- plugin_ui_registry_remove, hook);
+ plugin_ui_hook_unregister_manager, hook);
- g_hash_table_insert (
- hash_table, ui_manager, GUINT_TO_POINTER (merge_id));
+ registry = hook->priv->registry;
+ hash_table = g_hash_table_lookup (registry, ui_manager);
+
+ if (hash_table == NULL) {
+ hash_table = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) NULL);
+ g_hash_table_insert (registry, ui_manager, hash_table);
+ }
}
-/* Helper for plugin_ui_hook_merge_ui() */
-static void
-plugin_ui_hook_merge_foreach (GtkUIManager *ui_manager,
- const gchar *ui_definition,
- GHashTable *hash_table)
+static guint
+plugin_ui_hook_merge_ui (EPluginUIHook *hook,
+ GtkUIManager *ui_manager,
+ const gchar *id)
{
+ GHashTable *hash_table;
+ const gchar *ui_definition;
guint merge_id;
GError *error = NULL;
- /* Merge the UI definition into the manager. */
+ hash_table = hook->priv->ui_definitions;
+ ui_definition = g_hash_table_lookup (hash_table, id);
+ g_return_val_if_fail (ui_definition != NULL, 0);
+
merge_id = gtk_ui_manager_add_ui_from_string (
ui_manager, ui_definition, -1, &error);
- gtk_ui_manager_ensure_update (ui_manager);
+
if (error != NULL) {
g_warning ("%s", error->message);
g_error_free (error);
}
- /* Merge ID will be 0 on error, which is what we want. */
- g_hash_table_insert (
- hash_table, ui_manager, GUINT_TO_POINTER (merge_id));
+ return merge_id;
}
static void
-plugin_ui_hook_merge_ui (EPluginUIHook *hook)
+plugin_ui_enable_manager (EPluginUIHook *hook,
+ GtkUIManager *ui_manager,
+ const gchar *id)
{
- GHashTable *old_merge_ids;
- GHashTable *new_merge_ids;
- GHashTable *intermediate;
+ GHashTable *hash_table;
+ GHashTable *ui_definitions;
GList *keys;
- old_merge_ids = g_hash_table_lookup (registry, hook);
- if (old_merge_ids == NULL)
- return;
+ hash_table = hook->priv->registry;
+ hash_table = g_hash_table_lookup (hash_table, ui_manager);
- /* The GtkUIManager instances and UI definitions live in separate
- * tables, so we need to build an intermediate table that we can
- * easily iterate over. */
- keys = g_hash_table_get_keys (old_merge_ids);
- intermediate = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (hash_table == NULL)
+ return;
- while (keys != NULL) {
- GtkUIManager *ui_manager = keys->data;
- gchar *ui_definition;
+ if (id != NULL)
+ keys = g_list_prepend (NULL, (gpointer) id);
+ else
+ keys = g_hash_table_get_keys (hash_table);
- ui_definition = g_hash_table_lookup (
- hook->priv->ui_definitions,
- e_plugin_ui_get_manager_id (ui_manager));
+ ui_definitions = hook->priv->ui_definitions;
- g_hash_table_insert (intermediate, ui_manager, ui_definition);
+ while (keys != NULL) {
+ guint merge_id;
+ gpointer data;
+ id = keys->data;
keys = g_list_delete_link (keys, keys);
- }
- new_merge_ids = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (g_hash_table_lookup (ui_definitions, id) == NULL)
+ continue;
+
+ data = g_hash_table_lookup (hash_table, id);
+ merge_id = GPOINTER_TO_UINT (data);
- g_hash_table_foreach (
- intermediate, (GHFunc)
- plugin_ui_hook_merge_foreach, new_merge_ids);
+ if (merge_id > 0)
+ continue;
- g_hash_table_insert (registry, hook, new_merge_ids);
+ if (((EPluginHook *) hook)->plugin->enabled)
+ merge_id = plugin_ui_hook_merge_ui (
+ hook, ui_manager, id);
- g_hash_table_destroy (intermediate);
+ /* Merge ID will be 0 on error, which is what we want. */
+ data = GUINT_TO_POINTER (merge_id);
+ g_hash_table_insert (hash_table, g_strdup (id), data);
+ }
}
-/* Helper for plugin_ui_hook_unmerge_ui() */
static void
-plugin_ui_hook_unmerge_foreach (GtkUIManager *ui_manager,
- gpointer value,
- GHashTable *hash_table)
+plugin_ui_disable_manager (EPluginUIHook *hook,
+ GtkUIManager *ui_manager,
+ const gchar *id,
+ gboolean remove)
{
- guint merge_id;
+ GHashTable *hash_table;
+ GHashTable *ui_definitions;
+ GList *keys;
+
+ hash_table = hook->priv->registry;
+ hash_table = g_hash_table_lookup (hash_table, ui_manager);
+
+ if (hash_table == NULL)
+ return;
+
+ if (id != NULL)
+ keys = g_list_prepend (NULL, (gpointer) id);
+ else
+ keys = g_hash_table_get_keys (hash_table);
+
+ ui_definitions = hook->priv->ui_definitions;
+
+ while (keys != NULL) {
+ guint merge_id;
+ gpointer data;
- merge_id = GPOINTER_TO_UINT (value);
- gtk_ui_manager_remove_ui (ui_manager, merge_id);
+ id = keys->data;
+ keys = g_list_delete_link (keys, keys);
+
+ if (g_hash_table_lookup (ui_definitions, id) == NULL)
+ continue;
- g_hash_table_insert (hash_table, ui_manager, GUINT_TO_POINTER (0));
+ data = g_hash_table_lookup (hash_table, id);
+ merge_id = GPOINTER_TO_UINT (data);
+
+ /* Merge ID could be 0 if the plugin is disabled. */
+ if (merge_id > 0)
+ gtk_ui_manager_remove_ui (ui_manager, merge_id);
+
+ if (remove)
+ g_hash_table_remove (hash_table, id);
+ else
+ g_hash_table_insert (hash_table, g_strdup (id), NULL);
+ }
}
static void
-plugin_ui_hook_unmerge_ui (EPluginUIHook *hook)
+plugin_ui_enable_hook (EPluginUIHook *hook)
{
- GHashTable *old_merge_ids;
- GHashTable *new_merge_ids;
-
- old_merge_ids = g_hash_table_lookup (registry, hook);
- if (old_merge_ids == NULL)
- return;
+ GHashTable *hash_table;
+ GHashTableIter iter;
+ gpointer key;
- new_merge_ids = g_hash_table_new (g_direct_hash, g_direct_equal);
+ /* Enable all GtkUIManagers for this hook. */
- g_hash_table_foreach (
- old_merge_ids, (GHFunc)
- plugin_ui_hook_unmerge_foreach, new_merge_ids);
+ hash_table = hook->priv->registry;
+ g_hash_table_iter_init (&iter, hash_table);
- g_hash_table_insert (registry, hook, new_merge_ids);
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ GtkUIManager *ui_manager = key;
+ plugin_ui_enable_manager (hook, ui_manager, NULL);
+ }
}
static void
-plugin_ui_hook_register_manager (EPluginUIHook *hook,
- GtkUIManager *ui_manager,
- const gchar *ui_definition,
- gpointer user_data)
+plugin_ui_disable_hook (EPluginUIHook *hook)
{
- EPlugin *plugin;
- EPluginUIInitFunc func;
- guint merge_id = 0;
+ GHashTable *hash_table;
+ GHashTableIter iter;
+ gpointer key;
- plugin = ((EPluginHook *) hook)->plugin;
- func = e_plugin_get_symbol (plugin, E_PLUGIN_UI_INIT_FUNC);
+ /* Disable all GtkUIManagers for this hook. */
- /* Pass the manager and user_data to the plugin's e_plugin_ui_init()
- * function (if it defined one). The plugin should install whatever
- * GtkActions and GtkActionGroups are neccessary to implement the
- * action names in its UI definition. */
- if (func != NULL && !func (ui_manager, user_data))
- return;
+ hash_table = hook->priv->registry;
+ g_hash_table_iter_init (&iter, hash_table);
- if (plugin->enabled) {
- GError *error = NULL;
-
- /* Merge the UI definition into the manager. */
- merge_id = gtk_ui_manager_add_ui_from_string (
- ui_manager, ui_definition, -1, &error);
- gtk_ui_manager_ensure_update (ui_manager);
- if (error != NULL) {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ GtkUIManager *ui_manager = key;
+ plugin_ui_disable_manager (hook, ui_manager, NULL, FALSE);
}
-
- /* Save merge ID's for later use. */
- plugin_ui_registry_insert (hook, ui_manager, merge_id);
}
static void
plugin_ui_hook_finalize (GObject *object)
{
EPluginUIHookPrivate *priv;
+ GHashTableIter iter;
+ gpointer ui_manager;
priv = E_PLUGIN_UI_HOOK_GET_PRIVATE (object);
+ /* Remove weak reference callbacks to GtkUIManagers. */
+ g_hash_table_iter_init (&iter, priv->registry);
+ while (g_hash_table_iter_next (&iter, &ui_manager, NULL))
+ g_object_weak_unref (
+ G_OBJECT (ui_manager), (GWeakNotify)
+ plugin_ui_hook_unregister_manager, object);
+
g_hash_table_destroy (priv->ui_definitions);
+ g_hash_table_destroy (priv->registry);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -300,9 +414,9 @@ plugin_ui_hook_enable (EPluginHook *hook,
gint state)
{
if (state)
- plugin_ui_hook_merge_ui (E_PLUGIN_UI_HOOK (hook));
+ plugin_ui_enable_hook (E_PLUGIN_UI_HOOK (hook));
else
- plugin_ui_hook_unmerge_ui (E_PLUGIN_UI_HOOK (hook));
+ plugin_ui_disable_hook (E_PLUGIN_UI_HOOK (hook));
}
static void
@@ -321,25 +435,24 @@ plugin_ui_hook_class_init (EPluginUIHookClass *class)
plugin_hook_class->id = E_PLUGIN_UI_HOOK_CLASS_ID;
plugin_hook_class->construct = plugin_ui_hook_construct;
plugin_hook_class->enable = plugin_ui_hook_enable;
-
- registry = g_hash_table_new_full (
- g_direct_hash, g_direct_equal,
- (GDestroyNotify) NULL,
- (GDestroyNotify) g_hash_table_destroy);
}
static void
plugin_ui_hook_init (EPluginUIHook *hook)
{
GHashTable *ui_definitions;
+ GHashTable *registry;
ui_definitions = g_hash_table_new_full (
g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_free);
+ registry = g_hash_table_new (g_direct_hash, g_direct_equal);
+
hook->priv = E_PLUGIN_UI_HOOK_GET_PRIVATE (hook);
hook->priv->ui_definitions = ui_definitions;
+ hook->priv->registry = registry;
}
GType
@@ -369,17 +482,14 @@ e_plugin_ui_hook_get_type (void)
}
void
-e_plugin_ui_register_manager (const gchar *id,
- GtkUIManager *ui_manager,
+e_plugin_ui_register_manager (GtkUIManager *ui_manager,
+ const gchar *id,
gpointer user_data)
{
- const gchar *key = E_PLUGIN_UI_MANAGER_ID_KEY;
GSList *plugin_list;
- g_return_if_fail (id != NULL);
g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
-
- g_object_set_data (G_OBJECT (ui_manager), key, (gpointer) id);
+ g_return_if_fail (id != NULL);
/* Loop over all installed plugins. */
plugin_list = e_plugin_list_plugins ();
@@ -387,36 +497,84 @@ e_plugin_ui_register_manager (const gchar *id,
EPlugin *plugin = plugin_list->data;
GSList *iter;
+ plugin_list = g_slist_next (plugin_list);
+
/* Look for hooks of type EPluginUIHook. */
for (iter = plugin->hooks; iter != NULL; iter = iter->next) {
EPluginUIHook *hook = iter->data;
- const gchar *ui_definition;
+ GHashTable *hash_table;
if (!E_IS_PLUGIN_UI_HOOK (hook))
continue;
+ hash_table = hook->priv->ui_definitions;
+
/* Check if the hook has a UI definition
* for the GtkUIManager being registered. */
- ui_definition = g_hash_table_lookup (
- hook->priv->ui_definitions, id);
- if (ui_definition == NULL)
+ if (g_hash_table_lookup (hash_table, id) == NULL)
continue;
/* Register the manager with the hook. */
plugin_ui_hook_register_manager (
- hook, ui_manager, ui_definition, user_data);
+ hook, ui_manager, user_data);
}
+ }
+}
+
+void
+e_plugin_ui_enable_manager (GtkUIManager *ui_manager,
+ const gchar *id)
+{
+ GSList *plugin_list;
+
+ g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
+ g_return_if_fail (id != NULL);
+
+ /* Loop over all installed plugins. */
+ plugin_list = e_plugin_list_plugins ();
+ while (plugin_list != NULL) {
+ EPlugin *plugin = plugin_list->data;
+ GSList *iter;
plugin_list = g_slist_next (plugin_list);
+
+ /* Look for hooks of type EPluginUIHook. */
+ for (iter = plugin->hooks; iter != NULL; iter = iter->next) {
+ EPluginUIHook *hook = iter->data;
+
+ if (!E_IS_PLUGIN_UI_HOOK (hook))
+ continue;
+
+ plugin_ui_enable_manager (hook, ui_manager, id);
+ }
}
}
-const gchar *
-e_plugin_ui_get_manager_id (GtkUIManager *ui_manager)
+void
+e_plugin_ui_disable_manager (GtkUIManager *ui_manager,
+ const gchar *id)
{
- const gchar *key = E_PLUGIN_UI_MANAGER_ID_KEY;
+ GSList *plugin_list;
+
+ g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
+ g_return_if_fail (id != NULL);
+
+ /* Loop over all installed plugins. */
+ plugin_list = e_plugin_list_plugins ();
+ while (plugin_list != NULL) {
+ EPlugin *plugin = plugin_list->data;
+ GSList *iter;
- g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
+ plugin_list = g_slist_next (plugin_list);
+
+ /* Look for hooks of type EPluginUIHook. */
+ for (iter = plugin->hooks; iter != NULL; iter = iter->next) {
+ EPluginUIHook *hook = iter->data;
- return g_object_get_data (G_OBJECT (ui_manager), key);
+ if (!E_IS_PLUGIN_UI_HOOK (hook))
+ continue;
+
+ plugin_ui_disable_manager (hook, ui_manager, id, TRUE);
+ }
+ }
}
diff --git a/e-util/e-plugin-ui.h b/e-util/e-plugin-ui.h
index b8e795c4c4..74d5bdc092 100644
--- a/e-util/e-plugin-ui.h
+++ b/e-util/e-plugin-ui.h
@@ -62,10 +62,13 @@ typedef gboolean (*EPluginUIInitFunc) (GtkUIManager *ui_manager,
GType e_plugin_ui_hook_get_type (void);
-void e_plugin_ui_register_manager (const gchar *id,
- GtkUIManager *ui_manager,
+void e_plugin_ui_register_manager (GtkUIManager *ui_manager,
+ const gchar *id,
gpointer user_data);
-const gchar * e_plugin_ui_get_manager_id (GtkUIManager *ui_manager);
+void e_plugin_ui_enable_manager (GtkUIManager *ui_manager,
+ const gchar *id);
+void e_plugin_ui_disable_manager (GtkUIManager *ui_manager,
+ const gchar *id);
G_END_DECLS
diff --git a/e-util/e-signature-utils.c b/e-util/e-signature-utils.c
new file mode 100644
index 0000000000..0114ce6e06
--- /dev/null
+++ b/e-util/e-signature-utils.c
@@ -0,0 +1,347 @@
+/*
+ * e-signature-utils.c
+ *
+ * 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/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ */
+
+#include "e-signature-utils.h"
+
+#include <errno.h>
+#include <glib/gstdio.h>
+#include <gconf/gconf-client.h>
+#include <camel/camel-stream.h>
+#include <camel/camel-stream-fs.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-stream-filter.h>
+#include <camel/camel-mime-filter-charset.h>
+#include <camel/camel-mime-filter-tohtml.h>
+
+#ifndef G_OS_WIN32
+#include <sys/wait.h>
+#endif
+
+#include "e-util/e-util.h"
+
+static ESignatureList *global_signature_list;
+
+ESignatureList *
+e_get_signature_list (void)
+{
+ if (G_UNLIKELY (global_signature_list == NULL)) {
+ GConfClient *client;
+
+ client = gconf_client_get_default ();
+ global_signature_list = e_signature_list_new (client);
+ g_object_unref (client);
+ }
+
+ g_return_val_if_fail (global_signature_list != NULL, NULL);
+
+ return global_signature_list;
+}
+
+ESignature *
+e_get_signature_by_name (const gchar *name)
+{
+ ESignatureList *signature_list;
+ const ESignature *signature;
+ e_signature_find_t find;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ find = E_SIGNATURE_FIND_NAME;
+ signature_list = e_get_signature_list ();
+ signature = e_signature_list_find (signature_list, find, name);
+
+ /* XXX ESignatureList misuses const. */
+ return (ESignature *) signature;
+}
+
+ESignature *
+e_get_signature_by_uid (const gchar *uid)
+{
+ ESignatureList *signature_list;
+ const ESignature *signature;
+ e_signature_find_t find;
+
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ find = E_SIGNATURE_FIND_UID;
+ signature_list = e_get_signature_list ();
+ signature = e_signature_list_find (signature_list, find, uid);
+
+ /* XXX ESignatureList misuses const. */
+ return (ESignature *) signature;
+}
+
+gchar *
+e_create_signature_file (GError **error)
+{
+ const gchar *data_dir;
+ gchar basename[32];
+ gchar *filename;
+ gchar *pathname;
+ gint32 ii;
+
+ data_dir = e_get_user_data_dir ();
+ pathname = g_build_filename (data_dir, "signatures", NULL);
+ filename = NULL;
+
+ if (g_mkdir_with_parents (pathname, 0700) < 0) {
+ g_set_error (
+ error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "%s: %s", pathname, g_strerror (errno));
+ g_free (pathname);
+ return NULL;
+ }
+
+ for (ii = 0; ii < G_MAXINT32; ii++) {
+
+ g_snprintf (
+ basename, sizeof (basename),
+ "signature-%" G_GINT32_FORMAT, ii);
+
+ g_free (filename);
+ filename = g_build_filename (pathname, basename, NULL);
+
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
+ gint fd;
+
+ fd = g_creat (filename, 0600);
+ if (fd >= 0) {
+ close (fd);
+ break;
+ }
+
+ /* If we failed once we're probably going
+ * to continue failing, so just give up. */
+ g_set_error (
+ error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "%s: %s", filename, g_strerror (errno));
+ g_free (filename);
+ filename = NULL;
+ break;
+ }
+ }
+
+ /* If there are actually G_MAXINT32 signature files, the
+ * most recent signature file we be overwritten. Sorry. */
+
+ return filename;
+}
+
+gchar *
+e_read_signature_file (ESignature *signature,
+ gboolean convert_to_html,
+ GError **error)
+{
+ CamelStream *input_stream;
+ CamelStream *output_stream;
+ GByteArray *buffer;
+ gchar *content;
+ gsize length;
+ gint fd;
+
+ g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL);
+
+ fd = g_open (signature->filename, O_RDONLY, 0);
+ if (fd < 0) {
+ g_set_error (
+ error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "%s: %s", signature->filename,
+ g_strerror (errno));
+ return NULL;
+ }
+
+ input_stream = camel_stream_fs_new_with_fd (fd);
+
+ if (!signature->html && convert_to_html) {
+ CamelStreamFilter *filtered_stream;
+ CamelMimeFilter *filter;
+ gint32 flags;
+
+ filtered_stream =
+ camel_stream_filter_new_with_stream (input_stream);
+ camel_object_unref (input_stream);
+
+ flags =
+ CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
+ filter = camel_mime_filter_tohtml_new (flags, 0);
+ camel_stream_filter_add (filtered_stream, filter);
+ camel_object_unref (filter);
+
+ input_stream = (CamelStream *) filtered_stream;
+ }
+
+ buffer = g_byte_array_new ();
+ output_stream = camel_stream_mem_new ();
+ camel_stream_mem_set_byte_array (
+ CAMEL_STREAM_MEM (output_stream), buffer);
+ camel_stream_write_to_stream (input_stream, output_stream);
+ camel_object_unref (output_stream);
+ camel_object_unref (input_stream);
+
+ /* Make sure the buffer is nul-terminated. */
+ length = (gsize) buffer->len;
+ g_byte_array_append (buffer, (guint8 *) "", 1);
+ content = (gchar *) g_byte_array_free (buffer, FALSE);
+
+ /* Signatures are saved as UTF-8, but we still need to check that
+ * the signature is valid UTF-8 because the user may be opening
+ * a signature file that is in his/her locale character set. If
+ * it's not in UTF-8 then try converting from the current locale. */
+ if (!g_utf8_validate (content, length, NULL)) {
+ gchar *utf8;
+
+ utf8 = g_locale_to_utf8 (content, length, NULL, NULL, error);
+ g_free (content);
+ content = utf8;
+ }
+
+ return content;
+}
+
+gchar *
+e_run_signature_script (const gchar *filename)
+{
+ /* FIXME Make this cross-platform, prefer GLib functions over
+ * POSIX, and report errors via GError instead of dumping
+ * messages to the terminal where users won't see them. */
+
+#ifndef G_OS_WIN32
+ gint in_fds[2];
+ pid_t pid;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ if (pipe (in_fds) == -1) {
+ g_warning (
+ "Failed to create pipe to '%s': %s",
+ filename, g_strerror (errno));
+ return NULL;
+ }
+
+ pid = fork ();
+
+ /* Child Process */
+ if (pid == 0) {
+ gint maxfd, ii;
+
+ close (in_fds[0]);
+ if (dup2 (in_fds[1], STDOUT_FILENO) < 0)
+ _exit (255);
+ close (in_fds[1]);
+
+ setsid ();
+
+ maxfd = sysconf (_SC_OPEN_MAX);
+ for (ii = 3; ii < maxfd; ii++) {
+ if (ii == STDIN_FILENO)
+ continue;
+ if (ii == STDOUT_FILENO)
+ continue;
+ if (ii == STDERR_FILENO)
+ continue;
+ fcntl (ii, F_SETFD, FD_CLOEXEC);
+ }
+
+ execlp ("/bin/sh", "/bin/sh", "-c", filename, NULL);
+
+ g_warning (
+ "Could not execute '%s': %s",
+ filename, g_strerror (errno));
+
+ _exit (255);
+
+ /* Parent Process */
+ } else if (pid > 0) {
+ CamelStream *output_stream;
+ CamelStream *input_stream;
+ GByteArray *buffer;
+ gchar *content;
+ gsize length;
+ gint result;
+ gint status;
+
+ close (in_fds[1]);
+
+ buffer = g_byte_array_new ();
+ output_stream = camel_stream_mem_new ();
+ camel_stream_mem_set_byte_array (
+ CAMEL_STREAM_MEM (output_stream), buffer);
+
+ input_stream = camel_stream_fs_new_with_fd (in_fds[0]);
+ camel_stream_write_to_stream (input_stream, output_stream);
+ camel_object_unref (input_stream);
+
+ camel_object_unref (output_stream);
+
+ /* Make sure the buffer is nul-terminated. */
+ length = (gsize) buffer->len;
+ g_byte_array_append (buffer, (guchar *) "", 1);
+ content = (gchar *) g_byte_array_free (buffer, FALSE);
+
+ /* Signature scripts are supposed to generate UTF-8 content,
+ * but because users are known to never read the manual, we
+ * try to do our best if the content isn't valid UTF-8 by
+ * assuming that the content is in the user's locale
+ * character set. */
+ if (!g_utf8_validate (content, length, NULL)) {
+ gchar *utf8;
+
+ /* XXX Should pass a GError here. */
+ utf8 = g_locale_to_utf8 (
+ content, length, NULL, NULL, NULL);
+ g_free (content);
+ content = utf8;
+ }
+
+ /* Wait for the script process to terminate. */
+ result = waitpid (pid, &status, 0);
+
+ if (result == -1 && errno == EINTR) {
+ /* Child process is hanging... */
+ kill (pid, SIGTERM);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ if (result == 0) {
+ /* ...still hanging, set phasers to KILL. */
+ kill (pid, SIGKILL);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ }
+ }
+
+ return content;
+
+ /* Forking Failed */
+ } else {
+ g_warning (
+ "Failed to create child process '%s': %s",
+ filename, g_strerror (errno));
+ close (in_fds[0]);
+ close (in_fds[1]);
+ }
+#endif
+
+ return NULL;
+}
diff --git a/e-util/e-corba-utils.h b/e-util/e-signature-utils.h
index 979237929d..41472f45d0 100644
--- a/e-util/e-corba-utils.h
+++ b/e-util/e-signature-utils.h
@@ -1,4 +1,6 @@
/*
+ * e-signature-utils.h
+ *
* 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
@@ -12,20 +14,27 @@
* 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:
- * Ettore Perazzoli <ettore@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
-#ifndef E_CORBA_UTILS_H
-#define E_CORBA_UTILS_H
+#ifndef E_SIGNATURE_UTILS_H
+#define E_SIGNATURE_UTILS_H
+
+#include <gtk/gtk.h>
+#include <e-util/e-signature.h>
+#include <e-util/e-signature-list.h>
+
+G_BEGIN_DECLS
-#include <orbit/orbit.h>
+ESignatureList *e_get_signature_list (void);
+ESignature * e_get_signature_by_name (const gchar *name);
+ESignature * e_get_signature_by_uid (const gchar *uid);
+gchar * e_create_signature_file (GError **error);
+gchar * e_read_signature_file (ESignature *signature,
+ gboolean convert_to_html,
+ GError **error);
+gchar * e_run_signature_script (const gchar *filename);
-const CORBA_char *e_safe_corba_string (const char *s);
-CORBA_char *e_safe_corba_string_dup (const char *s);
+G_END_DECLS
-#endif
+#endif /* E_SIGNATURE_UTILS_H */
diff --git a/e-util/e-unicode.c b/e-util/e-unicode.c
new file mode 100644
index 0000000000..9d660b6600
--- /dev/null
+++ b/e-util/e-unicode.c
@@ -0,0 +1,2052 @@
+/*
+ * e-unicode.c - utf-8 support functions for gal
+ *
+ * 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:
+ * Lauris Kaplinski <lauris@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/*
+ * TODO: Break simple ligatures in e_utf8_strstrcasedecomp
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <iconv.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <libxml/xmlmemory.h>
+
+#include <camel/camel-iconv.h>
+
+#include <glib/gi18n.h>
+#include "e-unicode.h"
+
+#define d(x)
+
+#define FONT_TESTING
+#define MAX_DECOMP 8
+
+static gint e_canonical_decomposition (gunichar ch, gunichar * buf);
+static gunichar e_stripped_char (gunichar ch);
+
+/* FIXME: this has not been ported fully yet - non ASCII people beware. */
+
+/*
+ * This my favourite
+ *
+ * strstr doing case insensitive, decomposing search
+ *
+ * Lauris
+ */
+
+const gchar *
+e_utf8_strstrcasedecomp (const gchar *haystack, const gchar *needle)
+{
+ gunichar *nuni;
+ gunichar unival;
+ gint nlen;
+ const gchar *o, *p;
+
+ if (haystack == NULL) return NULL;
+ if (needle == NULL) return NULL;
+ if (strlen (needle) == 0) return haystack;
+ if (strlen (haystack) == 0) return NULL;
+
+ nuni = alloca (sizeof (gunichar) * strlen (needle));
+
+ nlen = 0;
+ for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
+ gint sc;
+ sc = e_stripped_char (unival);
+ if (sc) {
+ nuni[nlen++] = sc;
+ }
+ }
+ /* NULL means there was illegal utf-8 sequence */
+ if (!p) return NULL;
+ /* If everything is correct, we have decomposed, lowercase, stripped needle */
+ if (nlen < 1) return haystack;
+
+ o = haystack;
+ for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
+ gint sc;
+ sc = e_stripped_char (unival);
+ if (sc) {
+ /* We have valid stripped char */
+ if (sc == nuni[0]) {
+ const gchar *q = p;
+ gint npos = 1;
+ while (npos < nlen) {
+ q = e_unicode_get_utf8 (q, &unival);
+ if (!q || !unival) return NULL;
+ sc = e_stripped_char (unival);
+ if ((!sc) || (sc != nuni[npos])) break;
+ npos++;
+ }
+ if (npos == nlen) {
+ return o;
+ }
+ }
+ }
+ o = p;
+ }
+
+ return NULL;
+}
+
+const gchar *
+e_utf8_strstrcase (const gchar *haystack, const gchar *needle)
+{
+ gunichar *nuni;
+ gunichar unival;
+ gint nlen;
+ const gchar *o, *p;
+
+ if (haystack == NULL) return NULL;
+ if (needle == NULL) return NULL;
+ if (strlen (needle) == 0) return haystack;
+ if (strlen (haystack) == 0) return NULL;
+
+ nuni = alloca (sizeof (gunichar) * strlen (needle));
+
+ nlen = 0;
+ for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
+ nuni[nlen++] = g_unichar_tolower (unival);
+ }
+ /* NULL means there was illegal utf-8 sequence */
+ if (!p) return NULL;
+
+ o = haystack;
+ for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) {
+ gint sc;
+ sc = g_unichar_tolower (unival);
+ /* We have valid stripped char */
+ if (sc == nuni[0]) {
+ const gchar *q = p;
+ gint npos = 1;
+ while (npos < nlen) {
+ q = e_unicode_get_utf8 (q, &unival);
+ if (!q || !unival) return NULL;
+ sc = g_unichar_tolower (unival);
+ if (sc != nuni[npos]) break;
+ npos++;
+ }
+ if (npos == nlen) {
+ return o;
+ }
+ }
+ o = p;
+ }
+
+ return NULL;
+}
+
+#if 0
+const gchar *
+e_utf8_strstrcase (const gchar *haystack, const gchar *needle)
+{
+ gchar *p;
+ gunichar *huni, *nuni;
+ gunichar unival;
+ gint hlen, nlen, hp, np;
+
+ if (haystack == NULL) return NULL;
+ if (needle == NULL) return NULL;
+ if (strlen (needle) == 0) return haystack;
+
+ huni = alloca (sizeof (gunichar) * strlen (haystack));
+
+ for (hlen = 0, p = e_unicode_get_utf8 (haystack, &unival); p && unival; hlen++, p = e_unicode_get_utf8 (p, &unival)) {
+ huni[hlen] = g_unichar_tolower (unival);
+ }
+
+ if (!p) return NULL;
+ if (hlen == 0) return NULL;
+
+ nuni = alloca (sizeof (gunichar) * strlen (needle));
+
+ for (nlen = 0, p = e_unicode_get_utf8 (needle, &unival); p && unival; nlen++, p = e_unicode_get_utf8 (p, &unival)) {
+ nuni[nlen] = g_unichar_tolower (unival);
+ }
+
+ if (!p) return NULL;
+ if (nlen == 0) return NULL;
+
+ if (hlen < nlen) return NULL;
+
+ for (hp = 0; hp <= hlen - nlen; hp++) {
+ for (np = 0; np < nlen; np++) {
+ if (huni[hp + np] != nuni[np]) break;
+ }
+ if (np == nlen) return haystack + unicode_offset_to_index (haystack, hp);
+ }
+
+ return NULL;
+}
+#endif
+
+gchar *
+e_utf8_from_gtk_event_key (GtkWidget *widget, guint keyval, const gchar *string)
+{
+ gint unival;
+ gchar *utf;
+ gint unilen;
+
+ if (keyval == GDK_VoidSymbol) {
+ utf = e_utf8_from_locale_string (string);
+ } else {
+ unival = gdk_keyval_to_unicode (keyval);
+
+ if (unival < ' ') return NULL;
+
+ utf = g_new (gchar, 7);
+
+ unilen = e_unichar_to_utf8 (unival, utf);
+
+ utf[unilen] = '\0';
+ }
+
+ return utf;
+}
+
+gchar *
+e_utf8_from_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes)
+{
+ char *new, *ob;
+ const char *ib;
+ size_t ibl, obl;
+
+ if (!string) return NULL;
+
+ if (ic == (iconv_t) -1) {
+ gint i;
+ /* iso-8859-1 */
+ ib = (char *) string;
+ new = ob = (char *)g_new (unsigned char, bytes * 2 + 1);
+ for (i = 0; i < (bytes); i ++) {
+ ob += e_unichar_to_utf8 (ib[i], ob);
+ }
+ *ob = '\0';
+ return new;
+ }
+
+ ib = string;
+ ibl = bytes;
+ new = ob = g_new (gchar, ibl * 6 + 1);
+ obl = ibl * 6;
+
+ while (ibl > 0) {
+ camel_iconv (ic, &ib, &ibl, &ob, &obl);
+ if (ibl > 0) {
+ gint len;
+ if ((*ib & 0x80) == 0x00) len = 1;
+ else if ((*ib &0xe0) == 0xc0) len = 2;
+ else if ((*ib &0xf0) == 0xe0) len = 3;
+ else if ((*ib &0xf8) == 0xf0) len = 4;
+ else {
+ g_warning ("Invalid UTF-8 sequence");
+ break;
+ }
+ ib += len;
+ ibl = bytes - (ib - string);
+ if (ibl > bytes) ibl = 0;
+ *ob++ = '_';
+ obl--;
+ }
+ }
+
+ *ob = '\0';
+
+ return new;
+}
+
+gchar *
+e_utf8_from_iconv_string (iconv_t ic, const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_from_iconv_string_sized (ic, string, strlen (string));
+}
+
+gchar *
+e_utf8_to_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes)
+{
+ char *new, *ob;
+ const char *ib;
+ size_t ibl, obl;
+
+ if (!string) return NULL;
+
+ if (ic == (iconv_t) -1) {
+ gint len;
+ const gchar *u;
+ gunichar uc;
+
+ new = (char *)g_new (unsigned char, bytes * 4 + 1);
+ u = string;
+ len = 0;
+
+ while ((u) && (u - string < bytes)) {
+ u = e_unicode_get_utf8 (u, &uc);
+ new[len++] = uc & 0xff;
+ }
+ new[len] = '\0';
+ return new;
+ }
+
+ ib = string;
+ ibl = bytes;
+ new = ob = g_new (char, ibl * 4 + 4);
+ obl = ibl * 4;
+
+ while (ibl > 0) {
+ camel_iconv (ic, &ib, &ibl, &ob, &obl);
+ if (ibl > 0) {
+ gint len;
+ if ((*ib & 0x80) == 0x00) len = 1;
+ else if ((*ib &0xe0) == 0xc0) len = 2;
+ else if ((*ib &0xf0) == 0xe0) len = 3;
+ else if ((*ib &0xf8) == 0xf0) len = 4;
+ else {
+ g_warning ("Invalid UTF-8 sequence");
+ break;
+ }
+ ib += len;
+ ibl = bytes - (ib - string);
+ if (ibl > bytes) ibl = 0;
+
+ /* FIXME: this is wrong... what if the destination charset is 16 or 32 bit? */
+ *ob++ = '_';
+ obl--;
+ }
+ }
+
+ /* Make sure to terminate with plenty of padding */
+ memset (ob, 0, 4);
+
+ return new;
+}
+
+gchar *
+e_utf8_to_iconv_string (iconv_t ic, const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_to_iconv_string_sized (ic, string, strlen (string));
+}
+
+gchar *
+e_utf8_from_charset_string_sized (const gchar *charset, const gchar *string, gint bytes)
+{
+ iconv_t ic;
+ char *ret;
+
+ if (!string) return NULL;
+
+ ic = camel_iconv_open("utf-8", charset);
+ ret = e_utf8_from_iconv_string_sized (ic, string, bytes);
+ camel_iconv_close(ic);
+
+ return ret;
+}
+
+gchar *
+e_utf8_from_charset_string (const gchar *charset, const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_from_charset_string_sized (charset, string, strlen (string));
+}
+
+gchar *
+e_utf8_to_charset_string_sized (const gchar *charset, const gchar *string, gint bytes)
+{
+ iconv_t ic;
+ char *ret;
+
+ if (!string) return NULL;
+
+ ic = camel_iconv_open(charset, "utf-8");
+ ret = e_utf8_to_iconv_string_sized (ic, string, bytes);
+ camel_iconv_close(ic);
+
+ return ret;
+}
+
+gchar *
+e_utf8_to_charset_string (const gchar *charset, const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_to_charset_string_sized (charset, string, strlen (string));
+}
+
+gchar *
+e_utf8_from_locale_string_sized (const gchar *string, gint bytes)
+{
+ iconv_t ic;
+ char *ret;
+
+ if (!string) return NULL;
+
+ ic = camel_iconv_open("utf-8", camel_iconv_locale_charset());
+ ret = e_utf8_from_iconv_string_sized (ic, string, bytes);
+ camel_iconv_close(ic);
+
+ return ret;
+}
+
+gchar *
+e_utf8_from_locale_string (const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_from_locale_string_sized (string, strlen (string));
+}
+
+gchar *
+e_utf8_to_locale_string_sized (const gchar *string, gint bytes)
+{
+ iconv_t ic;
+ char *ret;
+
+ if (!string) return NULL;
+
+ ic = camel_iconv_open(camel_iconv_locale_charset(), "utf-8");
+ ret = e_utf8_to_iconv_string_sized (ic, string, bytes);
+ camel_iconv_close(ic);
+
+ return ret;
+}
+
+gchar *
+e_utf8_to_locale_string (const gchar *string)
+{
+ if (!string) return NULL;
+ return e_utf8_to_locale_string_sized (string, strlen (string));
+}
+
+gboolean
+e_utf8_is_ascii (const gchar *string)
+{
+ char c;
+
+ g_return_val_if_fail (string != NULL, FALSE);
+
+ for (; (c = *string); string++) {
+ if (c & 0x80)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gchar *
+e_utf8_gtk_entry_get_text (GtkEntry *entry)
+{
+ return g_strdup (gtk_entry_get_text (entry));
+}
+
+gchar *
+e_utf8_gtk_editable_get_text (GtkEditable *editable)
+{
+ return gtk_editable_get_chars (editable, 0, -1);
+}
+
+gchar *
+e_utf8_gtk_editable_get_chars (GtkEditable *editable, gint start, gint end)
+{
+ return gtk_editable_get_chars (editable, start, end);
+}
+
+void
+e_utf8_gtk_editable_insert_text (GtkEditable *editable, const gchar *text, gint length, gint *position)
+{
+ gtk_editable_insert_text (editable, text, length, position);
+}
+
+void
+e_utf8_gtk_editable_set_text (GtkEditable *editable, const gchar *text)
+{
+ int position;
+
+ gtk_editable_delete_text(editable, 0, -1);
+ gtk_editable_insert_text (editable, text, strlen (text), &position);
+}
+
+void
+e_utf8_gtk_entry_set_text (GtkEntry *entry, const gchar *text)
+{
+ if (!text)
+ gtk_entry_set_text(entry, "");
+ else
+ gtk_entry_set_text (entry, text);
+}
+
+/*
+ * Translate \U+XXXX\ sequences to utf8 chars
+ */
+
+gchar *
+e_utf8_xml1_decode (const gchar *text)
+{
+ const guchar *c;
+ gchar *u, *d;
+ int len, s;
+
+ g_return_val_if_fail (text != NULL, NULL);
+
+ len = strlen (text)+1;
+ /* len * 2 is absolute maximum */
+ u = d = g_malloc (len * 2);
+
+ c = (guchar *)text;
+ s = 0;
+ while (s < len) {
+ if ((s <= (len - 8)) &&
+ (c[s ] == '\\') &&
+ (c[s + 1] == 'U' ) &&
+ (c[s + 2] == '+' ) &&
+ isxdigit (c[s + 3]) &&
+ isxdigit (c[s + 4]) &&
+ isxdigit (c[s + 5]) &&
+ isxdigit (c[s + 6]) &&
+ (c[s + 7] == '\\')) {
+ /* Valid \U+XXXX\ sequence */
+ int unival;
+ unival = strtol ((char *)(c + s + 3), NULL, 16);
+ d += e_unichar_to_utf8 (unival, d);
+ s += 8;
+ } else if (c[s] > 127) {
+ /* fixme: We assume iso-8859-1 currently */
+ d += e_unichar_to_utf8 (c[s], d);
+ s += 1;
+ } else {
+ *d++ = c[s++];
+ }
+ }
+ *d++ = '\0';
+ u = g_realloc (u, (d - u));
+
+ return u;
+}
+
+gchar *
+e_utf8_xml1_encode (const gchar *text)
+{
+ gchar *u, *d, *c;
+ unsigned int unival;
+ int len;
+
+ g_return_val_if_fail (text != NULL, NULL);
+
+ len = 0;
+ for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) {
+ if ((unival >= 0x80) || (unival == '\\')) {
+ len += 8;
+ } else {
+ len += 1;
+ }
+ }
+ d = c = (char *)g_new (guchar, len + 1);
+
+ for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) {
+ if ((unival >= 0x80) || (unival == '\\')) {
+ *c++ = '\\';
+ *c++ = 'U';
+ *c++ = '+';
+ c += sprintf (c, "%04x", unival);
+ *c++ = '\\';
+ } else {
+ *c++ = unival;
+ }
+ }
+ *c = '\0';
+
+ return d;
+}
+
+/**
+ * e_unichar_to_utf8:
+ * @c: a ISO10646 character code
+ * @outbuf: output buffer, must have at least 6 bytes of space.
+ * If %NULL, the length will be computed and returned
+ * and nothing will be written to @out.
+ *
+ * Convert a single character to utf8
+ *
+ * Return value: number of bytes written
+ **/
+
+gint
+e_unichar_to_utf8 (gint c, gchar *outbuf)
+{
+ size_t len = 0;
+ int first;
+ int i;
+
+ if (c < 0x80)
+ {
+ first = 0;
+ len = 1;
+ }
+ else if (c < 0x800)
+ {
+ first = 0xc0;
+ len = 2;
+ }
+ else if (c < 0x10000)
+ {
+ first = 0xe0;
+ len = 3;
+ }
+ else if (c < 0x200000)
+ {
+ first = 0xf0;
+ len = 4;
+ }
+ else if (c < 0x4000000)
+ {
+ first = 0xf8;
+ len = 5;
+ }
+ else
+ {
+ first = 0xfc;
+ len = 6;
+ }
+
+ if (outbuf)
+ {
+ for (i = len - 1; i > 0; --i)
+ {
+ outbuf[i] = (c & 0x3f) | 0x80;
+ c >>= 6;
+ }
+ outbuf[0] = c | first;
+ }
+
+ return len;
+}
+
+gchar *
+e_unicode_get_utf8 (const gchar *text, gunichar *out)
+{
+ *out = g_utf8_get_char (text);
+ return (*out == (gunichar)-1) ? NULL : g_utf8_next_char (text);
+}
+
+/*
+ * Canonical decomposition
+ *
+ * It is copied here from libunicode, because we do not want malloc
+ *
+ */
+
+typedef struct
+{
+ unsigned short ch;
+ char *expansion;
+} e_decomposition;
+
+static e_decomposition e_decomp_table[] =
+{
+ { 0x00c0, "\x00\x41\x03\x00\0" },
+ { 0x00c1, "\x00\x41\x03\x01\0" },
+ { 0x00c2, "\x00\x41\x03\x02\0" },
+ { 0x00c3, "\x00\x41\x03\x03\0" },
+ { 0x00c4, "\x00\x41\x03\x08\0" },
+ { 0x00c5, "\x00\x41\x03\x0a\0" },
+ { 0x00c7, "\x00\x43\x03\x27\0" },
+ { 0x00c8, "\x00\x45\x03\x00\0" },
+ { 0x00c9, "\x00\x45\x03\x01\0" },
+ { 0x00ca, "\x00\x45\x03\x02\0" },
+ { 0x00cb, "\x00\x45\x03\x08\0" },
+ { 0x00cc, "\x00\x49\x03\x00\0" },
+ { 0x00cd, "\x00\x49\x03\x01\0" },
+ { 0x00ce, "\x00\x49\x03\x02\0" },
+ { 0x00cf, "\x00\x49\x03\x08\0" },
+ { 0x00d1, "\x00\x4e\x03\x03\0" },
+ { 0x00d2, "\x00\x4f\x03\x00\0" },
+ { 0x00d3, "\x00\x4f\x03\x01\0" },
+ { 0x00d4, "\x00\x4f\x03\x02\0" },
+ { 0x00d5, "\x00\x4f\x03\x03\0" },
+ { 0x00d6, "\x00\x4f\x03\x08\0" },
+ { 0x00d9, "\x00\x55\x03\x00\0" },
+ { 0x00da, "\x00\x55\x03\x01\0" },
+ { 0x00db, "\x00\x55\x03\x02\0" },
+ { 0x00dc, "\x00\x55\x03\x08\0" },
+ { 0x00dd, "\x00\x59\x03\x01\0" },
+ { 0x00e0, "\x00\x61\x03\x00\0" },
+ { 0x00e1, "\x00\x61\x03\x01\0" },
+ { 0x00e2, "\x00\x61\x03\x02\0" },
+ { 0x00e3, "\x00\x61\x03\x03\0" },
+ { 0x00e4, "\x00\x61\x03\x08\0" },
+ { 0x00e5, "\x00\x61\x03\x0a\0" },
+ { 0x00e7, "\x00\x63\x03\x27\0" },
+ { 0x00e8, "\x00\x65\x03\x00\0" },
+ { 0x00e9, "\x00\x65\x03\x01\0" },
+ { 0x00ea, "\x00\x65\x03\x02\0" },
+ { 0x00eb, "\x00\x65\x03\x08\0" },
+ { 0x00ec, "\x00\x69\x03\x00\0" },
+ { 0x00ed, "\x00\x69\x03\x01\0" },
+ { 0x00ee, "\x00\x69\x03\x02\0" },
+ { 0x00ef, "\x00\x69\x03\x08\0" },
+ { 0x00f1, "\x00\x6e\x03\x03\0" },
+ { 0x00f2, "\x00\x6f\x03\x00\0" },
+ { 0x00f3, "\x00\x6f\x03\x01\0" },
+ { 0x00f4, "\x00\x6f\x03\x02\0" },
+ { 0x00f5, "\x00\x6f\x03\x03\0" },
+ { 0x00f6, "\x00\x6f\x03\x08\0" },
+ { 0x00f9, "\x00\x75\x03\x00\0" },
+ { 0x00fa, "\x00\x75\x03\x01\0" },
+ { 0x00fb, "\x00\x75\x03\x02\0" },
+ { 0x00fc, "\x00\x75\x03\x08\0" },
+ { 0x00fd, "\x00\x79\x03\x01\0" },
+ { 0x00ff, "\x00\x79\x03\x08\0" },
+ { 0x0100, "\x00\x41\x03\x04\0" },
+ { 0x0101, "\x00\x61\x03\x04\0" },
+ { 0x0102, "\x00\x41\x03\x06\0" },
+ { 0x0103, "\x00\x61\x03\x06\0" },
+ { 0x0104, "\x00\x41\x03\x28\0" },
+ { 0x0105, "\x00\x61\x03\x28\0" },
+ { 0x0106, "\x00\x43\x03\x01\0" },
+ { 0x0107, "\x00\x63\x03\x01\0" },
+ { 0x0108, "\x00\x43\x03\x02\0" },
+ { 0x0109, "\x00\x63\x03\x02\0" },
+ { 0x010a, "\x00\x43\x03\x07\0" },
+ { 0x010b, "\x00\x63\x03\x07\0" },
+ { 0x010c, "\x00\x43\x03\x0c\0" },
+ { 0x010d, "\x00\x63\x03\x0c\0" },
+ { 0x010e, "\x00\x44\x03\x0c\0" },
+ { 0x010f, "\x00\x64\x03\x0c\0" },
+ { 0x0112, "\x00\x45\x03\x04\0" },
+ { 0x0113, "\x00\x65\x03\x04\0" },
+ { 0x0114, "\x00\x45\x03\x06\0" },
+ { 0x0115, "\x00\x65\x03\x06\0" },
+ { 0x0116, "\x00\x45\x03\x07\0" },
+ { 0x0117, "\x00\x65\x03\x07\0" },
+ { 0x0118, "\x00\x45\x03\x28\0" },
+ { 0x0119, "\x00\x65\x03\x28\0" },
+ { 0x011a, "\x00\x45\x03\x0c\0" },
+ { 0x011b, "\x00\x65\x03\x0c\0" },
+ { 0x011c, "\x00\x47\x03\x02\0" },
+ { 0x011d, "\x00\x67\x03\x02\0" },
+ { 0x011e, "\x00\x47\x03\x06\0" },
+ { 0x011f, "\x00\x67\x03\x06\0" },
+ { 0x0120, "\x00\x47\x03\x07\0" },
+ { 0x0121, "\x00\x67\x03\x07\0" },
+ { 0x0122, "\x00\x47\x03\x27\0" },
+ { 0x0123, "\x00\x67\x03\x27\0" },
+ { 0x0124, "\x00\x48\x03\x02\0" },
+ { 0x0125, "\x00\x68\x03\x02\0" },
+ { 0x0128, "\x00\x49\x03\x03\0" },
+ { 0x0129, "\x00\x69\x03\x03\0" },
+ { 0x012a, "\x00\x49\x03\x04\0" },
+ { 0x012b, "\x00\x69\x03\x04\0" },
+ { 0x012c, "\x00\x49\x03\x06\0" },
+ { 0x012d, "\x00\x69\x03\x06\0" },
+ { 0x012e, "\x00\x49\x03\x28\0" },
+ { 0x012f, "\x00\x69\x03\x28\0" },
+ { 0x0130, "\x00\x49\x03\x07\0" },
+ { 0x0134, "\x00\x4a\x03\x02\0" },
+ { 0x0135, "\x00\x6a\x03\x02\0" },
+ { 0x0136, "\x00\x4b\x03\x27\0" },
+ { 0x0137, "\x00\x6b\x03\x27\0" },
+ { 0x0139, "\x00\x4c\x03\x01\0" },
+ { 0x013a, "\x00\x6c\x03\x01\0" },
+ { 0x013b, "\x00\x4c\x03\x27\0" },
+ { 0x013c, "\x00\x6c\x03\x27\0" },
+ { 0x013d, "\x00\x4c\x03\x0c\0" },
+ { 0x013e, "\x00\x6c\x03\x0c\0" },
+ { 0x0143, "\x00\x4e\x03\x01\0" },
+ { 0x0144, "\x00\x6e\x03\x01\0" },
+ { 0x0145, "\x00\x4e\x03\x27\0" },
+ { 0x0146, "\x00\x6e\x03\x27\0" },
+ { 0x0147, "\x00\x4e\x03\x0c\0" },
+ { 0x0148, "\x00\x6e\x03\x0c\0" },
+ { 0x014c, "\x00\x4f\x03\x04\0" },
+ { 0x014d, "\x00\x6f\x03\x04\0" },
+ { 0x014e, "\x00\x4f\x03\x06\0" },
+ { 0x014f, "\x00\x6f\x03\x06\0" },
+ { 0x0150, "\x00\x4f\x03\x0b\0" },
+ { 0x0151, "\x00\x6f\x03\x0b\0" },
+ { 0x0154, "\x00\x52\x03\x01\0" },
+ { 0x0155, "\x00\x72\x03\x01\0" },
+ { 0x0156, "\x00\x52\x03\x27\0" },
+ { 0x0157, "\x00\x72\x03\x27\0" },
+ { 0x0158, "\x00\x52\x03\x0c\0" },
+ { 0x0159, "\x00\x72\x03\x0c\0" },
+ { 0x015a, "\x00\x53\x03\x01\0" },
+ { 0x015b, "\x00\x73\x03\x01\0" },
+ { 0x015c, "\x00\x53\x03\x02\0" },
+ { 0x015d, "\x00\x73\x03\x02\0" },
+ { 0x015e, "\x00\x53\x03\x27\0" },
+ { 0x015f, "\x00\x73\x03\x27\0" },
+ { 0x0160, "\x00\x53\x03\x0c\0" },
+ { 0x0161, "\x00\x73\x03\x0c\0" },
+ { 0x0162, "\x00\x54\x03\x27\0" },
+ { 0x0163, "\x00\x74\x03\x27\0" },
+ { 0x0164, "\x00\x54\x03\x0c\0" },
+ { 0x0165, "\x00\x74\x03\x0c\0" },
+ { 0x0168, "\x00\x55\x03\x03\0" },
+ { 0x0169, "\x00\x75\x03\x03\0" },
+ { 0x016a, "\x00\x55\x03\x04\0" },
+ { 0x016b, "\x00\x75\x03\x04\0" },
+ { 0x016c, "\x00\x55\x03\x06\0" },
+ { 0x016d, "\x00\x75\x03\x06\0" },
+ { 0x016e, "\x00\x55\x03\x0a\0" },
+ { 0x016f, "\x00\x75\x03\x0a\0" },
+ { 0x0170, "\x00\x55\x03\x0b\0" },
+ { 0x0171, "\x00\x75\x03\x0b\0" },
+ { 0x0172, "\x00\x55\x03\x28\0" },
+ { 0x0173, "\x00\x75\x03\x28\0" },
+ { 0x0174, "\x00\x57\x03\x02\0" },
+ { 0x0175, "\x00\x77\x03\x02\0" },
+ { 0x0176, "\x00\x59\x03\x02\0" },
+ { 0x0177, "\x00\x79\x03\x02\0" },
+ { 0x0178, "\x00\x59\x03\x08\0" },
+ { 0x0179, "\x00\x5a\x03\x01\0" },
+ { 0x017a, "\x00\x7a\x03\x01\0" },
+ { 0x017b, "\x00\x5a\x03\x07\0" },
+ { 0x017c, "\x00\x7a\x03\x07\0" },
+ { 0x017d, "\x00\x5a\x03\x0c\0" },
+ { 0x017e, "\x00\x7a\x03\x0c\0" },
+ { 0x01a0, "\x00\x4f\x03\x1b\0" },
+ { 0x01a1, "\x00\x6f\x03\x1b\0" },
+ { 0x01af, "\x00\x55\x03\x1b\0" },
+ { 0x01b0, "\x00\x75\x03\x1b\0" },
+ { 0x01cd, "\x00\x41\x03\x0c\0" },
+ { 0x01ce, "\x00\x61\x03\x0c\0" },
+ { 0x01cf, "\x00\x49\x03\x0c\0" },
+ { 0x01d0, "\x00\x69\x03\x0c\0" },
+ { 0x01d1, "\x00\x4f\x03\x0c\0" },
+ { 0x01d2, "\x00\x6f\x03\x0c\0" },
+ { 0x01d3, "\x00\x55\x03\x0c\0" },
+ { 0x01d4, "\x00\x75\x03\x0c\0" },
+ { 0x01d5, "\x00\x55\x03\x08\x03\x04\0" },
+ { 0x01d6, "\x00\x75\x03\x08\x03\x04\0" },
+ { 0x01d7, "\x00\x55\x03\x08\x03\x01\0" },
+ { 0x01d8, "\x00\x75\x03\x08\x03\x01\0" },
+ { 0x01d9, "\x00\x55\x03\x08\x03\x0c\0" },
+ { 0x01da, "\x00\x75\x03\x08\x03\x0c\0" },
+ { 0x01db, "\x00\x55\x03\x08\x03\x00\0" },
+ { 0x01dc, "\x00\x75\x03\x08\x03\x00\0" },
+ { 0x01de, "\x00\x41\x03\x08\x03\x04\0" },
+ { 0x01df, "\x00\x61\x03\x08\x03\x04\0" },
+ { 0x01e0, "\x00\x41\x03\x07\x03\x04\0" },
+ { 0x01e1, "\x00\x61\x03\x07\x03\x04\0" },
+ { 0x01e2, "\x00\xc6\x03\x04\0" },
+ { 0x01e3, "\x00\xe6\x03\x04\0" },
+ { 0x01e6, "\x00\x47\x03\x0c\0" },
+ { 0x01e7, "\x00\x67\x03\x0c\0" },
+ { 0x01e8, "\x00\x4b\x03\x0c\0" },
+ { 0x01e9, "\x00\x6b\x03\x0c\0" },
+ { 0x01ea, "\x00\x4f\x03\x28\0" },
+ { 0x01eb, "\x00\x6f\x03\x28\0" },
+ { 0x01ec, "\x00\x4f\x03\x28\x03\x04\0" },
+ { 0x01ed, "\x00\x6f\x03\x28\x03\x04\0" },
+ { 0x01ee, "\x01\xb7\x03\x0c\0" },
+ { 0x01ef, "\x02\x92\x03\x0c\0" },
+ { 0x01f0, "\x00\x6a\x03\x0c\0" },
+ { 0x01f4, "\x00\x47\x03\x01\0" },
+ { 0x01f5, "\x00\x67\x03\x01\0" },
+ { 0x01fa, "\x00\x41\x03\x0a\x03\x01\0" },
+ { 0x01fb, "\x00\x61\x03\x0a\x03\x01\0" },
+ { 0x01fc, "\x00\xc6\x03\x01\0" },
+ { 0x01fd, "\x00\xe6\x03\x01\0" },
+ { 0x01fe, "\x00\xd8\x03\x01\0" },
+ { 0x01ff, "\x00\xf8\x03\x01\0" },
+ { 0x0200, "\x00\x41\x03\x0f\0" },
+ { 0x0201, "\x00\x61\x03\x0f\0" },
+ { 0x0202, "\x00\x41\x03\x11\0" },
+ { 0x0203, "\x00\x61\x03\x11\0" },
+ { 0x0204, "\x00\x45\x03\x0f\0" },
+ { 0x0205, "\x00\x65\x03\x0f\0" },
+ { 0x0206, "\x00\x45\x03\x11\0" },
+ { 0x0207, "\x00\x65\x03\x11\0" },
+ { 0x0208, "\x00\x49\x03\x0f\0" },
+ { 0x0209, "\x00\x69\x03\x0f\0" },
+ { 0x020a, "\x00\x49\x03\x11\0" },
+ { 0x020b, "\x00\x69\x03\x11\0" },
+ { 0x020c, "\x00\x4f\x03\x0f\0" },
+ { 0x020d, "\x00\x6f\x03\x0f\0" },
+ { 0x020e, "\x00\x4f\x03\x11\0" },
+ { 0x020f, "\x00\x6f\x03\x11\0" },
+ { 0x0210, "\x00\x52\x03\x0f\0" },
+ { 0x0211, "\x00\x72\x03\x0f\0" },
+ { 0x0212, "\x00\x52\x03\x11\0" },
+ { 0x0213, "\x00\x72\x03\x11\0" },
+ { 0x0214, "\x00\x55\x03\x0f\0" },
+ { 0x0215, "\x00\x75\x03\x0f\0" },
+ { 0x0216, "\x00\x55\x03\x11\0" },
+ { 0x0217, "\x00\x75\x03\x11\0" },
+ { 0x0340, "\x03\x00\0" },
+ { 0x0341, "\x03\x01\0" },
+ { 0x0343, "\x03\x13\0" },
+ { 0x0344, "\x03\x08\x03\x01\0" },
+ { 0x0374, "\x02\xb9\0" },
+ { 0x037e, "\x00\x3b\0" },
+ { 0x0385, "\x00\xa8\x03\x01\0" },
+ { 0x0386, "\x03\x91\x03\x01\0" },
+ { 0x0387, "\x00\xb7\0" },
+ { 0x0388, "\x03\x95\x03\x01\0" },
+ { 0x0389, "\x03\x97\x03\x01\0" },
+ { 0x038a, "\x03\x99\x03\x01\0" },
+ { 0x038c, "\x03\x9f\x03\x01\0" },
+ { 0x038e, "\x03\xa5\x03\x01\0" },
+ { 0x038f, "\x03\xa9\x03\x01\0" },
+ { 0x0390, "\x03\xb9\x03\x08\x03\x01\0" },
+ { 0x03aa, "\x03\x99\x03\x08\0" },
+ { 0x03ab, "\x03\xa5\x03\x08\0" },
+ { 0x03ac, "\x03\xb1\x03\x01\0" },
+ { 0x03ad, "\x03\xb5\x03\x01\0" },
+ { 0x03ae, "\x03\xb7\x03\x01\0" },
+ { 0x03af, "\x03\xb9\x03\x01\0" },
+ { 0x03b0, "\x03\xc5\x03\x08\x03\x01\0" },
+ { 0x03ca, "\x03\xb9\x03\x08\0" },
+ { 0x03cb, "\x03\xc5\x03\x08\0" },
+ { 0x03cc, "\x03\xbf\x03\x01\0" },
+ { 0x03cd, "\x03\xc5\x03\x01\0" },
+ { 0x03ce, "\x03\xc9\x03\x01\0" },
+ { 0x03d3, "\x03\xd2\x03\x01\0" },
+ { 0x03d4, "\x03\xd2\x03\x08\0" },
+ { 0x0401, "\x04\x15\x03\x08\0" },
+ { 0x0403, "\x04\x13\x03\x01\0" },
+ { 0x0407, "\x04\x06\x03\x08\0" },
+ { 0x040c, "\x04\x1a\x03\x01\0" },
+ { 0x040e, "\x04\x23\x03\x06\0" },
+ { 0x0419, "\x04\x18\x03\x06\0" },
+ { 0x0439, "\x04\x38\x03\x06\0" },
+ { 0x0451, "\x04\x35\x03\x08\0" },
+ { 0x0453, "\x04\x33\x03\x01\0" },
+ { 0x0457, "\x04\x56\x03\x08\0" },
+ { 0x045c, "\x04\x3a\x03\x01\0" },
+ { 0x045e, "\x04\x43\x03\x06\0" },
+ { 0x0476, "\x04\x74\x03\x0f\0" },
+ { 0x0477, "\x04\x75\x03\x0f\0" },
+ { 0x04c1, "\x04\x16\x03\x06\0" },
+ { 0x04c2, "\x04\x36\x03\x06\0" },
+ { 0x04d0, "\x04\x10\x03\x06\0" },
+ { 0x04d1, "\x04\x30\x03\x06\0" },
+ { 0x04d2, "\x04\x10\x03\x08\0" },
+ { 0x04d3, "\x04\x30\x03\x08\0" },
+ { 0x04d6, "\x04\x15\x03\x06\0" },
+ { 0x04d7, "\x04\x35\x03\x06\0" },
+ { 0x04da, "\x04\xd8\x03\x08\0" },
+ { 0x04db, "\x04\xd9\x03\x08\0" },
+ { 0x04dc, "\x04\x16\x03\x08\0" },
+ { 0x04dd, "\x04\x36\x03\x08\0" },
+ { 0x04de, "\x04\x17\x03\x08\0" },
+ { 0x04df, "\x04\x37\x03\x08\0" },
+ { 0x04e2, "\x04\x18\x03\x04\0" },
+ { 0x04e3, "\x04\x38\x03\x04\0" },
+ { 0x04e4, "\x04\x18\x03\x08\0" },
+ { 0x04e5, "\x04\x38\x03\x08\0" },
+ { 0x04e6, "\x04\x1e\x03\x08\0" },
+ { 0x04e7, "\x04\x3e\x03\x08\0" },
+ { 0x04ea, "\x04\xe8\x03\x08\0" },
+ { 0x04eb, "\x04\xe9\x03\x08\0" },
+ { 0x04ee, "\x04\x23\x03\x04\0" },
+ { 0x04ef, "\x04\x43\x03\x04\0" },
+ { 0x04f0, "\x04\x23\x03\x08\0" },
+ { 0x04f1, "\x04\x43\x03\x08\0" },
+ { 0x04f2, "\x04\x23\x03\x0b\0" },
+ { 0x04f3, "\x04\x43\x03\x0b\0" },
+ { 0x04f4, "\x04\x27\x03\x08\0" },
+ { 0x04f5, "\x04\x47\x03\x08\0" },
+ { 0x04f8, "\x04\x2b\x03\x08\0" },
+ { 0x04f9, "\x04\x4b\x03\x08\0" },
+ { 0x0929, "\x09\x28\x09\x3c\0" },
+ { 0x0931, "\x09\x30\x09\x3c\0" },
+ { 0x0934, "\x09\x33\x09\x3c\0" },
+ { 0x0958, "\x09\x15\x09\x3c\0" },
+ { 0x0959, "\x09\x16\x09\x3c\0" },
+ { 0x095a, "\x09\x17\x09\x3c\0" },
+ { 0x095b, "\x09\x1c\x09\x3c\0" },
+ { 0x095c, "\x09\x21\x09\x3c\0" },
+ { 0x095d, "\x09\x22\x09\x3c\0" },
+ { 0x095e, "\x09\x2b\x09\x3c\0" },
+ { 0x095f, "\x09\x2f\x09\x3c\0" },
+ { 0x09b0, "\x09\xac\x09\xbc\0" },
+ { 0x09cb, "\x09\xc7\x09\xbe\0" },
+ { 0x09cc, "\x09\xc7\x09\xd7\0" },
+ { 0x09dc, "\x09\xa1\x09\xbc\0" },
+ { 0x09dd, "\x09\xa2\x09\xbc\0" },
+ { 0x09df, "\x09\xaf\x09\xbc\0" },
+ { 0x0a59, "\x0a\x16\x0a\x3c\0" },
+ { 0x0a5a, "\x0a\x17\x0a\x3c\0" },
+ { 0x0a5b, "\x0a\x1c\x0a\x3c\0" },
+ { 0x0a5c, "\x0a\x21\x0a\x3c\0" },
+ { 0x0a5e, "\x0a\x2b\x0a\x3c\0" },
+ { 0x0b48, "\x0b\x47\x0b\x56\0" },
+ { 0x0b4b, "\x0b\x47\x0b\x3e\0" },
+ { 0x0b4c, "\x0b\x47\x0b\x57\0" },
+ { 0x0b5c, "\x0b\x21\x0b\x3c\0" },
+ { 0x0b5d, "\x0b\x22\x0b\x3c\0" },
+ { 0x0b5f, "\x0b\x2f\x0b\x3c\0" },
+ { 0x0b94, "\x0b\x92\x0b\xd7\0" },
+ { 0x0bca, "\x0b\xc6\x0b\xbe\0" },
+ { 0x0bcb, "\x0b\xc7\x0b\xbe\0" },
+ { 0x0bcc, "\x0b\xc6\x0b\xd7\0" },
+ { 0x0c48, "\x0c\x46\x0c\x56\0" },
+ { 0x0cc0, "\x0c\xbf\x0c\xd5\0" },
+ { 0x0cc7, "\x0c\xc6\x0c\xd5\0" },
+ { 0x0cc8, "\x0c\xc6\x0c\xd6\0" },
+ { 0x0cca, "\x0c\xc6\x0c\xc2\0" },
+ { 0x0ccb, "\x0c\xc6\x0c\xc2\x0c\xd5\0" },
+ { 0x0d4a, "\x0d\x46\x0d\x3e\0" },
+ { 0x0d4b, "\x0d\x47\x0d\x3e\0" },
+ { 0x0d4c, "\x0d\x46\x0d\x57\0" },
+ { 0x0e33, "\x0e\x4d\x0e\x32\0" },
+ { 0x0eb3, "\x0e\xcd\x0e\xb2\0" },
+ { 0x0f43, "\x0f\x42\x0f\xb7\0" },
+ { 0x0f4d, "\x0f\x4c\x0f\xb7\0" },
+ { 0x0f52, "\x0f\x51\x0f\xb7\0" },
+ { 0x0f57, "\x0f\x56\x0f\xb7\0" },
+ { 0x0f5c, "\x0f\x5b\x0f\xb7\0" },
+ { 0x0f69, "\x0f\x40\x0f\xb5\0" },
+ { 0x0f73, "\x0f\x71\x0f\x72\0" },
+ { 0x0f75, "\x0f\x71\x0f\x74\0" },
+ { 0x0f76, "\x0f\xb2\x0f\x80\0" },
+ { 0x0f78, "\x0f\xb3\x0f\x80\0" },
+ { 0x0f81, "\x0f\x71\x0f\x80\0" },
+ { 0x0f93, "\x0f\x92\x0f\xb7\0" },
+ { 0x0f9d, "\x0f\x9c\x0f\xb7\0" },
+ { 0x0fa2, "\x0f\xa1\x0f\xb7\0" },
+ { 0x0fa7, "\x0f\xa6\x0f\xb7\0" },
+ { 0x0fac, "\x0f\xab\x0f\xb7\0" },
+ { 0x0fb9, "\x0f\x90\x0f\xb5\0" },
+ { 0x1e00, "\x00\x41\x03\x25\0" },
+ { 0x1e01, "\x00\x61\x03\x25\0" },
+ { 0x1e02, "\x00\x42\x03\x07\0" },
+ { 0x1e03, "\x00\x62\x03\x07\0" },
+ { 0x1e04, "\x00\x42\x03\x23\0" },
+ { 0x1e05, "\x00\x62\x03\x23\0" },
+ { 0x1e06, "\x00\x42\x03\x31\0" },
+ { 0x1e07, "\x00\x62\x03\x31\0" },
+ { 0x1e08, "\x00\x43\x03\x27\x03\x01\0" },
+ { 0x1e09, "\x00\x63\x03\x27\x03\x01\0" },
+ { 0x1e0a, "\x00\x44\x03\x07\0" },
+ { 0x1e0b, "\x00\x64\x03\x07\0" },
+ { 0x1e0c, "\x00\x44\x03\x23\0" },
+ { 0x1e0d, "\x00\x64\x03\x23\0" },
+ { 0x1e0e, "\x00\x44\x03\x31\0" },
+ { 0x1e0f, "\x00\x64\x03\x31\0" },
+ { 0x1e10, "\x00\x44\x03\x27\0" },
+ { 0x1e11, "\x00\x64\x03\x27\0" },
+ { 0x1e12, "\x00\x44\x03\x2d\0" },
+ { 0x1e13, "\x00\x64\x03\x2d\0" },
+ { 0x1e14, "\x00\x45\x03\x04\x03\x00\0" },
+ { 0x1e15, "\x00\x65\x03\x04\x03\x00\0" },
+ { 0x1e16, "\x00\x45\x03\x04\x03\x01\0" },
+ { 0x1e17, "\x00\x65\x03\x04\x03\x01\0" },
+ { 0x1e18, "\x00\x45\x03\x2d\0" },
+ { 0x1e19, "\x00\x65\x03\x2d\0" },
+ { 0x1e1a, "\x00\x45\x03\x30\0" },
+ { 0x1e1b, "\x00\x65\x03\x30\0" },
+ { 0x1e1c, "\x00\x45\x03\x27\x03\x06\0" },
+ { 0x1e1d, "\x00\x65\x03\x27\x03\x06\0" },
+ { 0x1e1e, "\x00\x46\x03\x07\0" },
+ { 0x1e1f, "\x00\x66\x03\x07\0" },
+ { 0x1e20, "\x00\x47\x03\x04\0" },
+ { 0x1e21, "\x00\x67\x03\x04\0" },
+ { 0x1e22, "\x00\x48\x03\x07\0" },
+ { 0x1e23, "\x00\x68\x03\x07\0" },
+ { 0x1e24, "\x00\x48\x03\x23\0" },
+ { 0x1e25, "\x00\x68\x03\x23\0" },
+ { 0x1e26, "\x00\x48\x03\x08\0" },
+ { 0x1e27, "\x00\x68\x03\x08\0" },
+ { 0x1e28, "\x00\x48\x03\x27\0" },
+ { 0x1e29, "\x00\x68\x03\x27\0" },
+ { 0x1e2a, "\x00\x48\x03\x2e\0" },
+ { 0x1e2b, "\x00\x68\x03\x2e\0" },
+ { 0x1e2c, "\x00\x49\x03\x30\0" },
+ { 0x1e2d, "\x00\x69\x03\x30\0" },
+ { 0x1e2e, "\x00\x49\x03\x08\x03\x01\0" },
+ { 0x1e2f, "\x00\x69\x03\x08\x03\x01\0" },
+ { 0x1e30, "\x00\x4b\x03\x01\0" },
+ { 0x1e31, "\x00\x6b\x03\x01\0" },
+ { 0x1e32, "\x00\x4b\x03\x23\0" },
+ { 0x1e33, "\x00\x6b\x03\x23\0" },
+ { 0x1e34, "\x00\x4b\x03\x31\0" },
+ { 0x1e35, "\x00\x6b\x03\x31\0" },
+ { 0x1e36, "\x00\x4c\x03\x23\0" },
+ { 0x1e37, "\x00\x6c\x03\x23\0" },
+ { 0x1e38, "\x00\x4c\x03\x23\x03\x04\0" },
+ { 0x1e39, "\x00\x6c\x03\x23\x03\x04\0" },
+ { 0x1e3a, "\x00\x4c\x03\x31\0" },
+ { 0x1e3b, "\x00\x6c\x03\x31\0" },
+ { 0x1e3c, "\x00\x4c\x03\x2d\0" },
+ { 0x1e3d, "\x00\x6c\x03\x2d\0" },
+ { 0x1e3e, "\x00\x4d\x03\x01\0" },
+ { 0x1e3f, "\x00\x6d\x03\x01\0" },
+ { 0x1e40, "\x00\x4d\x03\x07\0" },
+ { 0x1e41, "\x00\x6d\x03\x07\0" },
+ { 0x1e42, "\x00\x4d\x03\x23\0" },
+ { 0x1e43, "\x00\x6d\x03\x23\0" },
+ { 0x1e44, "\x00\x4e\x03\x07\0" },
+ { 0x1e45, "\x00\x6e\x03\x07\0" },
+ { 0x1e46, "\x00\x4e\x03\x23\0" },
+ { 0x1e47, "\x00\x6e\x03\x23\0" },
+ { 0x1e48, "\x00\x4e\x03\x31\0" },
+ { 0x1e49, "\x00\x6e\x03\x31\0" },
+ { 0x1e4a, "\x00\x4e\x03\x2d\0" },
+ { 0x1e4b, "\x00\x6e\x03\x2d\0" },
+ { 0x1e4c, "\x00\x4f\x03\x03\x03\x01\0" },
+ { 0x1e4d, "\x00\x6f\x03\x03\x03\x01\0" },
+ { 0x1e4e, "\x00\x4f\x03\x03\x03\x08\0" },
+ { 0x1e4f, "\x00\x6f\x03\x03\x03\x08\0" },
+ { 0x1e50, "\x00\x4f\x03\x04\x03\x00\0" },
+ { 0x1e51, "\x00\x6f\x03\x04\x03\x00\0" },
+ { 0x1e52, "\x00\x4f\x03\x04\x03\x01\0" },
+ { 0x1e53, "\x00\x6f\x03\x04\x03\x01\0" },
+ { 0x1e54, "\x00\x50\x03\x01\0" },
+ { 0x1e55, "\x00\x70\x03\x01\0" },
+ { 0x1e56, "\x00\x50\x03\x07\0" },
+ { 0x1e57, "\x00\x70\x03\x07\0" },
+ { 0x1e58, "\x00\x52\x03\x07\0" },
+ { 0x1e59, "\x00\x72\x03\x07\0" },
+ { 0x1e5a, "\x00\x52\x03\x23\0" },
+ { 0x1e5b, "\x00\x72\x03\x23\0" },
+ { 0x1e5c, "\x00\x52\x03\x23\x03\x04\0" },
+ { 0x1e5d, "\x00\x72\x03\x23\x03\x04\0" },
+ { 0x1e5e, "\x00\x52\x03\x31\0" },
+ { 0x1e5f, "\x00\x72\x03\x31\0" },
+ { 0x1e60, "\x00\x53\x03\x07\0" },
+ { 0x1e61, "\x00\x73\x03\x07\0" },
+ { 0x1e62, "\x00\x53\x03\x23\0" },
+ { 0x1e63, "\x00\x73\x03\x23\0" },
+ { 0x1e64, "\x00\x53\x03\x01\x03\x07\0" },
+ { 0x1e65, "\x00\x73\x03\x01\x03\x07\0" },
+ { 0x1e66, "\x00\x53\x03\x0c\x03\x07\0" },
+ { 0x1e67, "\x00\x73\x03\x0c\x03\x07\0" },
+ { 0x1e68, "\x00\x53\x03\x23\x03\x07\0" },
+ { 0x1e69, "\x00\x73\x03\x23\x03\x07\0" },
+ { 0x1e6a, "\x00\x54\x03\x07\0" },
+ { 0x1e6b, "\x00\x74\x03\x07\0" },
+ { 0x1e6c, "\x00\x54\x03\x23\0" },
+ { 0x1e6d, "\x00\x74\x03\x23\0" },
+ { 0x1e6e, "\x00\x54\x03\x31\0" },
+ { 0x1e6f, "\x00\x74\x03\x31\0" },
+ { 0x1e70, "\x00\x54\x03\x2d\0" },
+ { 0x1e71, "\x00\x74\x03\x2d\0" },
+ { 0x1e72, "\x00\x55\x03\x24\0" },
+ { 0x1e73, "\x00\x75\x03\x24\0" },
+ { 0x1e74, "\x00\x55\x03\x30\0" },
+ { 0x1e75, "\x00\x75\x03\x30\0" },
+ { 0x1e76, "\x00\x55\x03\x2d\0" },
+ { 0x1e77, "\x00\x75\x03\x2d\0" },
+ { 0x1e78, "\x00\x55\x03\x03\x03\x01\0" },
+ { 0x1e79, "\x00\x75\x03\x03\x03\x01\0" },
+ { 0x1e7a, "\x00\x55\x03\x04\x03\x08\0" },
+ { 0x1e7b, "\x00\x75\x03\x04\x03\x08\0" },
+ { 0x1e7c, "\x00\x56\x03\x03\0" },
+ { 0x1e7d, "\x00\x76\x03\x03\0" },
+ { 0x1e7e, "\x00\x56\x03\x23\0" },
+ { 0x1e7f, "\x00\x76\x03\x23\0" },
+ { 0x1e80, "\x00\x57\x03\x00\0" },
+ { 0x1e81, "\x00\x77\x03\x00\0" },
+ { 0x1e82, "\x00\x57\x03\x01\0" },
+ { 0x1e83, "\x00\x77\x03\x01\0" },
+ { 0x1e84, "\x00\x57\x03\x08\0" },
+ { 0x1e85, "\x00\x77\x03\x08\0" },
+ { 0x1e86, "\x00\x57\x03\x07\0" },
+ { 0x1e87, "\x00\x77\x03\x07\0" },
+ { 0x1e88, "\x00\x57\x03\x23\0" },
+ { 0x1e89, "\x00\x77\x03\x23\0" },
+ { 0x1e8a, "\x00\x58\x03\x07\0" },
+ { 0x1e8b, "\x00\x78\x03\x07\0" },
+ { 0x1e8c, "\x00\x58\x03\x08\0" },
+ { 0x1e8d, "\x00\x78\x03\x08\0" },
+ { 0x1e8e, "\x00\x59\x03\x07\0" },
+ { 0x1e8f, "\x00\x79\x03\x07\0" },
+ { 0x1e90, "\x00\x5a\x03\x02\0" },
+ { 0x1e91, "\x00\x7a\x03\x02\0" },
+ { 0x1e92, "\x00\x5a\x03\x23\0" },
+ { 0x1e93, "\x00\x7a\x03\x23\0" },
+ { 0x1e94, "\x00\x5a\x03\x31\0" },
+ { 0x1e95, "\x00\x7a\x03\x31\0" },
+ { 0x1e96, "\x00\x68\x03\x31\0" },
+ { 0x1e97, "\x00\x74\x03\x08\0" },
+ { 0x1e98, "\x00\x77\x03\x0a\0" },
+ { 0x1e99, "\x00\x79\x03\x0a\0" },
+ { 0x1e9b, "\x01\x7f\x03\x07\0" },
+ { 0x1ea0, "\x00\x41\x03\x23\0" },
+ { 0x1ea1, "\x00\x61\x03\x23\0" },
+ { 0x1ea2, "\x00\x41\x03\x09\0" },
+ { 0x1ea3, "\x00\x61\x03\x09\0" },
+ { 0x1ea4, "\x00\x41\x03\x02\x03\x01\0" },
+ { 0x1ea5, "\x00\x61\x03\x02\x03\x01\0" },
+ { 0x1ea6, "\x00\x41\x03\x02\x03\x00\0" },
+ { 0x1ea7, "\x00\x61\x03\x02\x03\x00\0" },
+ { 0x1ea8, "\x00\x41\x03\x02\x03\x09\0" },
+ { 0x1ea9, "\x00\x61\x03\x02\x03\x09\0" },
+ { 0x1eaa, "\x00\x41\x03\x02\x03\x03\0" },
+ { 0x1eab, "\x00\x61\x03\x02\x03\x03\0" },
+ { 0x1eac, "\x00\x41\x03\x23\x03\x02\0" },
+ { 0x1ead, "\x00\x61\x03\x23\x03\x02\0" },
+ { 0x1eae, "\x00\x41\x03\x06\x03\x01\0" },
+ { 0x1eaf, "\x00\x61\x03\x06\x03\x01\0" },
+ { 0x1eb0, "\x00\x41\x03\x06\x03\x00\0" },
+ { 0x1eb1, "\x00\x61\x03\x06\x03\x00\0" },
+ { 0x1eb2, "\x00\x41\x03\x06\x03\x09\0" },
+ { 0x1eb3, "\x00\x61\x03\x06\x03\x09\0" },
+ { 0x1eb4, "\x00\x41\x03\x06\x03\x03\0" },
+ { 0x1eb5, "\x00\x61\x03\x06\x03\x03\0" },
+ { 0x1eb6, "\x00\x41\x03\x23\x03\x06\0" },
+ { 0x1eb7, "\x00\x61\x03\x23\x03\x06\0" },
+ { 0x1eb8, "\x00\x45\x03\x23\0" },
+ { 0x1eb9, "\x00\x65\x03\x23\0" },
+ { 0x1eba, "\x00\x45\x03\x09\0" },
+ { 0x1ebb, "\x00\x65\x03\x09\0" },
+ { 0x1ebc, "\x00\x45\x03\x03\0" },
+ { 0x1ebd, "\x00\x65\x03\x03\0" },
+ { 0x1ebe, "\x00\x45\x03\x02\x03\x01\0" },
+ { 0x1ebf, "\x00\x65\x03\x02\x03\x01\0" },
+ { 0x1ec0, "\x00\x45\x03\x02\x03\x00\0" },
+ { 0x1ec1, "\x00\x65\x03\x02\x03\x00\0" },
+ { 0x1ec2, "\x00\x45\x03\x02\x03\x09\0" },
+ { 0x1ec3, "\x00\x65\x03\x02\x03\x09\0" },
+ { 0x1ec4, "\x00\x45\x03\x02\x03\x03\0" },
+ { 0x1ec5, "\x00\x65\x03\x02\x03\x03\0" },
+ { 0x1ec6, "\x00\x45\x03\x23\x03\x02\0" },
+ { 0x1ec7, "\x00\x65\x03\x23\x03\x02\0" },
+ { 0x1ec8, "\x00\x49\x03\x09\0" },
+ { 0x1ec9, "\x00\x69\x03\x09\0" },
+ { 0x1eca, "\x00\x49\x03\x23\0" },
+ { 0x1ecb, "\x00\x69\x03\x23\0" },
+ { 0x1ecc, "\x00\x4f\x03\x23\0" },
+ { 0x1ecd, "\x00\x6f\x03\x23\0" },
+ { 0x1ece, "\x00\x4f\x03\x09\0" },
+ { 0x1ecf, "\x00\x6f\x03\x09\0" },
+ { 0x1ed0, "\x00\x4f\x03\x02\x03\x01\0" },
+ { 0x1ed1, "\x00\x6f\x03\x02\x03\x01\0" },
+ { 0x1ed2, "\x00\x4f\x03\x02\x03\x00\0" },
+ { 0x1ed3, "\x00\x6f\x03\x02\x03\x00\0" },
+ { 0x1ed4, "\x00\x4f\x03\x02\x03\x09\0" },
+ { 0x1ed5, "\x00\x6f\x03\x02\x03\x09\0" },
+ { 0x1ed6, "\x00\x4f\x03\x02\x03\x03\0" },
+ { 0x1ed7, "\x00\x6f\x03\x02\x03\x03\0" },
+ { 0x1ed8, "\x00\x4f\x03\x23\x03\x02\0" },
+ { 0x1ed9, "\x00\x6f\x03\x23\x03\x02\0" },
+ { 0x1eda, "\x00\x4f\x03\x1b\x03\x01\0" },
+ { 0x1edb, "\x00\x6f\x03\x1b\x03\x01\0" },
+ { 0x1edc, "\x00\x4f\x03\x1b\x03\x00\0" },
+ { 0x1edd, "\x00\x6f\x03\x1b\x03\x00\0" },
+ { 0x1ede, "\x00\x4f\x03\x1b\x03\x09\0" },
+ { 0x1edf, "\x00\x6f\x03\x1b\x03\x09\0" },
+ { 0x1ee0, "\x00\x4f\x03\x1b\x03\x03\0" },
+ { 0x1ee1, "\x00\x6f\x03\x1b\x03\x03\0" },
+ { 0x1ee2, "\x00\x4f\x03\x1b\x03\x23\0" },
+ { 0x1ee3, "\x00\x6f\x03\x1b\x03\x23\0" },
+ { 0x1ee4, "\x00\x55\x03\x23\0" },
+ { 0x1ee5, "\x00\x75\x03\x23\0" },
+ { 0x1ee6, "\x00\x55\x03\x09\0" },
+ { 0x1ee7, "\x00\x75\x03\x09\0" },
+ { 0x1ee8, "\x00\x55\x03\x1b\x03\x01\0" },
+ { 0x1ee9, "\x00\x75\x03\x1b\x03\x01\0" },
+ { 0x1eea, "\x00\x55\x03\x1b\x03\x00\0" },
+ { 0x1eeb, "\x00\x75\x03\x1b\x03\x00\0" },
+ { 0x1eec, "\x00\x55\x03\x1b\x03\x09\0" },
+ { 0x1eed, "\x00\x75\x03\x1b\x03\x09\0" },
+ { 0x1eee, "\x00\x55\x03\x1b\x03\x03\0" },
+ { 0x1eef, "\x00\x75\x03\x1b\x03\x03\0" },
+ { 0x1ef0, "\x00\x55\x03\x1b\x03\x23\0" },
+ { 0x1ef1, "\x00\x75\x03\x1b\x03\x23\0" },
+ { 0x1ef2, "\x00\x59\x03\x00\0" },
+ { 0x1ef3, "\x00\x79\x03\x00\0" },
+ { 0x1ef4, "\x00\x59\x03\x23\0" },
+ { 0x1ef5, "\x00\x79\x03\x23\0" },
+ { 0x1ef6, "\x00\x59\x03\x09\0" },
+ { 0x1ef7, "\x00\x79\x03\x09\0" },
+ { 0x1ef8, "\x00\x59\x03\x03\0" },
+ { 0x1ef9, "\x00\x79\x03\x03\0" },
+ { 0x1f00, "\x03\xb1\x03\x13\0" },
+ { 0x1f01, "\x03\xb1\x03\x14\0" },
+ { 0x1f02, "\x03\xb1\x03\x13\x03\x00\0" },
+ { 0x1f03, "\x03\xb1\x03\x14\x03\x00\0" },
+ { 0x1f04, "\x03\xb1\x03\x13\x03\x01\0" },
+ { 0x1f05, "\x03\xb1\x03\x14\x03\x01\0" },
+ { 0x1f06, "\x03\xb1\x03\x13\x03\x42\0" },
+ { 0x1f07, "\x03\xb1\x03\x14\x03\x42\0" },
+ { 0x1f08, "\x03\x91\x03\x13\0" },
+ { 0x1f09, "\x03\x91\x03\x14\0" },
+ { 0x1f0a, "\x03\x91\x03\x13\x03\x00\0" },
+ { 0x1f0b, "\x03\x91\x03\x14\x03\x00\0" },
+ { 0x1f0c, "\x03\x91\x03\x13\x03\x01\0" },
+ { 0x1f0d, "\x03\x91\x03\x14\x03\x01\0" },
+ { 0x1f0e, "\x03\x91\x03\x13\x03\x42\0" },
+ { 0x1f0f, "\x03\x91\x03\x14\x03\x42\0" },
+ { 0x1f10, "\x03\xb5\x03\x13\0" },
+ { 0x1f11, "\x03\xb5\x03\x14\0" },
+ { 0x1f12, "\x03\xb5\x03\x13\x03\x00\0" },
+ { 0x1f13, "\x03\xb5\x03\x14\x03\x00\0" },
+ { 0x1f14, "\x03\xb5\x03\x13\x03\x01\0" },
+ { 0x1f15, "\x03\xb5\x03\x14\x03\x01\0" },
+ { 0x1f18, "\x03\x95\x03\x13\0" },
+ { 0x1f19, "\x03\x95\x03\x14\0" },
+ { 0x1f1a, "\x03\x95\x03\x13\x03\x00\0" },
+ { 0x1f1b, "\x03\x95\x03\x14\x03\x00\0" },
+ { 0x1f1c, "\x03\x95\x03\x13\x03\x01\0" },
+ { 0x1f1d, "\x03\x95\x03\x14\x03\x01\0" },
+ { 0x1f20, "\x03\xb7\x03\x13\0" },
+ { 0x1f21, "\x03\xb7\x03\x14\0" },
+ { 0x1f22, "\x03\xb7\x03\x13\x03\x00\0" },
+ { 0x1f23, "\x03\xb7\x03\x14\x03\x00\0" },
+ { 0x1f24, "\x03\xb7\x03\x13\x03\x01\0" },
+ { 0x1f25, "\x03\xb7\x03\x14\x03\x01\0" },
+ { 0x1f26, "\x03\xb7\x03\x13\x03\x42\0" },
+ { 0x1f27, "\x03\xb7\x03\x14\x03\x42\0" },
+ { 0x1f28, "\x03\x97\x03\x13\0" },
+ { 0x1f29, "\x03\x97\x03\x14\0" },
+ { 0x1f2a, "\x03\x97\x03\x13\x03\x00\0" },
+ { 0x1f2b, "\x03\x97\x03\x14\x03\x00\0" },
+ { 0x1f2c, "\x03\x97\x03\x13\x03\x01\0" },
+ { 0x1f2d, "\x03\x97\x03\x14\x03\x01\0" },
+ { 0x1f2e, "\x03\x97\x03\x13\x03\x42\0" },
+ { 0x1f2f, "\x03\x97\x03\x14\x03\x42\0" },
+ { 0x1f30, "\x03\xb9\x03\x13\0" },
+ { 0x1f31, "\x03\xb9\x03\x14\0" },
+ { 0x1f32, "\x03\xb9\x03\x13\x03\x00\0" },
+ { 0x1f33, "\x03\xb9\x03\x14\x03\x00\0" },
+ { 0x1f34, "\x03\xb9\x03\x13\x03\x01\0" },
+ { 0x1f35, "\x03\xb9\x03\x14\x03\x01\0" },
+ { 0x1f36, "\x03\xb9\x03\x13\x03\x42\0" },
+ { 0x1f37, "\x03\xb9\x03\x14\x03\x42\0" },
+ { 0x1f38, "\x03\x99\x03\x13\0" },
+ { 0x1f39, "\x03\x99\x03\x14\0" },
+ { 0x1f3a, "\x03\x99\x03\x13\x03\x00\0" },
+ { 0x1f3b, "\x03\x99\x03\x14\x03\x00\0" },
+ { 0x1f3c, "\x03\x99\x03\x13\x03\x01\0" },
+ { 0x1f3d, "\x03\x99\x03\x14\x03\x01\0" },
+ { 0x1f3e, "\x03\x99\x03\x13\x03\x42\0" },
+ { 0x1f3f, "\x03\x99\x03\x14\x03\x42\0" },
+ { 0x1f40, "\x03\xbf\x03\x13\0" },
+ { 0x1f41, "\x03\xbf\x03\x14\0" },
+ { 0x1f42, "\x03\xbf\x03\x13\x03\x00\0" },
+ { 0x1f43, "\x03\xbf\x03\x14\x03\x00\0" },
+ { 0x1f44, "\x03\xbf\x03\x13\x03\x01\0" },
+ { 0x1f45, "\x03\xbf\x03\x14\x03\x01\0" },
+ { 0x1f48, "\x03\x9f\x03\x13\0" },
+ { 0x1f49, "\x03\x9f\x03\x14\0" },
+ { 0x1f4a, "\x03\x9f\x03\x13\x03\x00\0" },
+ { 0x1f4b, "\x03\x9f\x03\x14\x03\x00\0" },
+ { 0x1f4c, "\x03\x9f\x03\x13\x03\x01\0" },
+ { 0x1f4d, "\x03\x9f\x03\x14\x03\x01\0" },
+ { 0x1f50, "\x03\xc5\x03\x13\0" },
+ { 0x1f51, "\x03\xc5\x03\x14\0" },
+ { 0x1f52, "\x03\xc5\x03\x13\x03\x00\0" },
+ { 0x1f53, "\x03\xc5\x03\x14\x03\x00\0" },
+ { 0x1f54, "\x03\xc5\x03\x13\x03\x01\0" },
+ { 0x1f55, "\x03\xc5\x03\x14\x03\x01\0" },
+ { 0x1f56, "\x03\xc5\x03\x13\x03\x42\0" },
+ { 0x1f57, "\x03\xc5\x03\x14\x03\x42\0" },
+ { 0x1f59, "\x03\xa5\x03\x14\0" },
+ { 0x1f5b, "\x03\xa5\x03\x14\x03\x00\0" },
+ { 0x1f5d, "\x03\xa5\x03\x14\x03\x01\0" },
+ { 0x1f5f, "\x03\xa5\x03\x14\x03\x42\0" },
+ { 0x1f60, "\x03\xc9\x03\x13\0" },
+ { 0x1f61, "\x03\xc9\x03\x14\0" },
+ { 0x1f62, "\x03\xc9\x03\x13\x03\x00\0" },
+ { 0x1f63, "\x03\xc9\x03\x14\x03\x00\0" },
+ { 0x1f64, "\x03\xc9\x03\x13\x03\x01\0" },
+ { 0x1f65, "\x03\xc9\x03\x14\x03\x01\0" },
+ { 0x1f66, "\x03\xc9\x03\x13\x03\x42\0" },
+ { 0x1f67, "\x03\xc9\x03\x14\x03\x42\0" },
+ { 0x1f68, "\x03\xa9\x03\x13\0" },
+ { 0x1f69, "\x03\xa9\x03\x14\0" },
+ { 0x1f6a, "\x03\xa9\x03\x13\x03\x00\0" },
+ { 0x1f6b, "\x03\xa9\x03\x14\x03\x00\0" },
+ { 0x1f6c, "\x03\xa9\x03\x13\x03\x01\0" },
+ { 0x1f6d, "\x03\xa9\x03\x14\x03\x01\0" },
+ { 0x1f6e, "\x03\xa9\x03\x13\x03\x42\0" },
+ { 0x1f6f, "\x03\xa9\x03\x14\x03\x42\0" },
+ { 0x1f70, "\x03\xb1\x03\x00\0" },
+ { 0x1f71, "\x03\xb1\x03\x01\0" },
+ { 0x1f72, "\x03\xb5\x03\x00\0" },
+ { 0x1f73, "\x03\xb5\x03\x01\0" },
+ { 0x1f74, "\x03\xb7\x03\x00\0" },
+ { 0x1f75, "\x03\xb7\x03\x01\0" },
+ { 0x1f76, "\x03\xb9\x03\x00\0" },
+ { 0x1f77, "\x03\xb9\x03\x01\0" },
+ { 0x1f78, "\x03\xbf\x03\x00\0" },
+ { 0x1f79, "\x03\xbf\x03\x01\0" },
+ { 0x1f7a, "\x03\xc5\x03\x00\0" },
+ { 0x1f7b, "\x03\xc5\x03\x01\0" },
+ { 0x1f7c, "\x03\xc9\x03\x00\0" },
+ { 0x1f7d, "\x03\xc9\x03\x01\0" },
+ { 0x1f80, "\x03\xb1\x03\x13\x03\x45\0" },
+ { 0x1f81, "\x03\xb1\x03\x14\x03\x45\0" },
+ { 0x1f82, "\x03\xb1\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1f83, "\x03\xb1\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1f84, "\x03\xb1\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1f85, "\x03\xb1\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1f86, "\x03\xb1\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1f87, "\x03\xb1\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1f88, "\x03\x91\x03\x13\x03\x45\0" },
+ { 0x1f89, "\x03\x91\x03\x14\x03\x45\0" },
+ { 0x1f8a, "\x03\x91\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1f8b, "\x03\x91\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1f8c, "\x03\x91\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1f8d, "\x03\x91\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1f8e, "\x03\x91\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1f8f, "\x03\x91\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1f90, "\x03\xb7\x03\x13\x03\x45\0" },
+ { 0x1f91, "\x03\xb7\x03\x14\x03\x45\0" },
+ { 0x1f92, "\x03\xb7\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1f93, "\x03\xb7\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1f94, "\x03\xb7\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1f95, "\x03\xb7\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1f96, "\x03\xb7\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1f97, "\x03\xb7\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1f98, "\x03\x97\x03\x13\x03\x45\0" },
+ { 0x1f99, "\x03\x97\x03\x14\x03\x45\0" },
+ { 0x1f9a, "\x03\x97\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1f9b, "\x03\x97\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1f9c, "\x03\x97\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1f9d, "\x03\x97\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1f9e, "\x03\x97\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1f9f, "\x03\x97\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1fa0, "\x03\xc9\x03\x13\x03\x45\0" },
+ { 0x1fa1, "\x03\xc9\x03\x14\x03\x45\0" },
+ { 0x1fa2, "\x03\xc9\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1fa3, "\x03\xc9\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1fa4, "\x03\xc9\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1fa5, "\x03\xc9\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1fa6, "\x03\xc9\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1fa7, "\x03\xc9\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1fa8, "\x03\xa9\x03\x13\x03\x45\0" },
+ { 0x1fa9, "\x03\xa9\x03\x14\x03\x45\0" },
+ { 0x1faa, "\x03\xa9\x03\x13\x03\x00\x03\x45\0" },
+ { 0x1fab, "\x03\xa9\x03\x14\x03\x00\x03\x45\0" },
+ { 0x1fac, "\x03\xa9\x03\x13\x03\x01\x03\x45\0" },
+ { 0x1fad, "\x03\xa9\x03\x14\x03\x01\x03\x45\0" },
+ { 0x1fae, "\x03\xa9\x03\x13\x03\x42\x03\x45\0" },
+ { 0x1faf, "\x03\xa9\x03\x14\x03\x42\x03\x45\0" },
+ { 0x1fb0, "\x03\xb1\x03\x06\0" },
+ { 0x1fb1, "\x03\xb1\x03\x04\0" },
+ { 0x1fb2, "\x03\xb1\x03\x00\x03\x45\0" },
+ { 0x1fb3, "\x03\xb1\x03\x45\0" },
+ { 0x1fb4, "\x03\xb1\x03\x01\x03\x45\0" },
+ { 0x1fb6, "\x03\xb1\x03\x42\0" },
+ { 0x1fb7, "\x03\xb1\x03\x42\x03\x45\0" },
+ { 0x1fb8, "\x03\x91\x03\x06\0" },
+ { 0x1fb9, "\x03\x91\x03\x04\0" },
+ { 0x1fba, "\x03\x91\x03\x00\0" },
+ { 0x1fbb, "\x03\x91\x03\x01\0" },
+ { 0x1fbc, "\x03\x91\x03\x45\0" },
+ { 0x1fbe, "\x03\xb9\0" },
+ { 0x1fc1, "\x00\xa8\x03\x42\0" },
+ { 0x1fc2, "\x03\xb7\x03\x00\x03\x45\0" },
+ { 0x1fc3, "\x03\xb7\x03\x45\0" },
+ { 0x1fc4, "\x03\xb7\x03\x01\x03\x45\0" },
+ { 0x1fc6, "\x03\xb7\x03\x42\0" },
+ { 0x1fc7, "\x03\xb7\x03\x42\x03\x45\0" },
+ { 0x1fc8, "\x03\x95\x03\x00\0" },
+ { 0x1fc9, "\x03\x95\x03\x01\0" },
+ { 0x1fca, "\x03\x97\x03\x00\0" },
+ { 0x1fcb, "\x03\x97\x03\x01\0" },
+ { 0x1fcc, "\x03\x97\x03\x45\0" },
+ { 0x1fcd, "\x1f\xbf\x03\x00\0" },
+ { 0x1fce, "\x1f\xbf\x03\x01\0" },
+ { 0x1fcf, "\x1f\xbf\x03\x42\0" },
+ { 0x1fd0, "\x03\xb9\x03\x06\0" },
+ { 0x1fd1, "\x03\xb9\x03\x04\0" },
+ { 0x1fd2, "\x03\xb9\x03\x08\x03\x00\0" },
+ { 0x1fd3, "\x03\xb9\x03\x08\x03\x01\0" },
+ { 0x1fd6, "\x03\xb9\x03\x42\0" },
+ { 0x1fd7, "\x03\xb9\x03\x08\x03\x42\0" },
+ { 0x1fd8, "\x03\x99\x03\x06\0" },
+ { 0x1fd9, "\x03\x99\x03\x04\0" },
+ { 0x1fda, "\x03\x99\x03\x00\0" },
+ { 0x1fdb, "\x03\x99\x03\x01\0" },
+ { 0x1fdd, "\x1f\xfe\x03\x00\0" },
+ { 0x1fde, "\x1f\xfe\x03\x01\0" },
+ { 0x1fdf, "\x1f\xfe\x03\x42\0" },
+ { 0x1fe0, "\x03\xc5\x03\x06\0" },
+ { 0x1fe1, "\x03\xc5\x03\x04\0" },
+ { 0x1fe2, "\x03\xc5\x03\x08\x03\x00\0" },
+ { 0x1fe3, "\x03\xc5\x03\x08\x03\x01\0" },
+ { 0x1fe4, "\x03\xc1\x03\x13\0" },
+ { 0x1fe5, "\x03\xc1\x03\x14\0" },
+ { 0x1fe6, "\x03\xc5\x03\x42\0" },
+ { 0x1fe7, "\x03\xc5\x03\x08\x03\x42\0" },
+ { 0x1fe8, "\x03\xa5\x03\x06\0" },
+ { 0x1fe9, "\x03\xa5\x03\x04\0" },
+ { 0x1fea, "\x03\xa5\x03\x00\0" },
+ { 0x1feb, "\x03\xa5\x03\x01\0" },
+ { 0x1fec, "\x03\xa1\x03\x14\0" },
+ { 0x1fed, "\x00\xa8\x03\x00\0" },
+ { 0x1fee, "\x00\xa8\x03\x01\0" },
+ { 0x1fef, "\x00\x60\0" },
+ { 0x1ff2, "\x03\xc9\x03\x00\x03\x45\0" },
+ { 0x1ff3, "\x03\xc9\x03\x45\0" },
+ { 0x1ff4, "\x03\xc9\x03\x01\x03\x45\0" },
+ { 0x1ff6, "\x03\xc9\x03\x42\0" },
+ { 0x1ff7, "\x03\xc9\x03\x42\x03\x45\0" },
+ { 0x1ff8, "\x03\x9f\x03\x00\0" },
+ { 0x1ff9, "\x03\x9f\x03\x01\0" },
+ { 0x1ffa, "\x03\xa9\x03\x00\0" },
+ { 0x1ffb, "\x03\xa9\x03\x01\0" },
+ { 0x1ffc, "\x03\xa9\x03\x45\0" },
+ { 0x1ffd, "\x00\xb4\0" },
+ { 0x2000, "\x20\x02\0" },
+ { 0x2001, "\x20\x03\0" },
+ { 0x2126, "\x03\xa9\0" },
+ { 0x212a, "\x00\x4b\0" },
+ { 0x212b, "\x00\x41\x03\x0a\0" },
+ { 0x2204, "\x22\x03\x03\x38\0" },
+ { 0x2209, "\x22\x08\x03\x38\0" },
+ { 0x220c, "\x22\x0b\x03\x38\0" },
+ { 0x2224, "\x22\x23\x03\x38\0" },
+ { 0x2226, "\x22\x25\x03\x38\0" },
+ { 0x2241, "\x00\x7e\x03\x38\0" },
+ { 0x2244, "\x22\x43\x03\x38\0" },
+ { 0x2247, "\x22\x45\x03\x38\0" },
+ { 0x2249, "\x22\x48\x03\x38\0" },
+ { 0x2260, "\x00\x3d\x03\x38\0" },
+ { 0x2262, "\x22\x61\x03\x38\0" },
+ { 0x226d, "\x22\x4d\x03\x38\0" },
+ { 0x226e, "\x00\x3c\x03\x38\0" },
+ { 0x226f, "\x00\x3e\x03\x38\0" },
+ { 0x2270, "\x22\x64\x03\x38\0" },
+ { 0x2271, "\x22\x65\x03\x38\0" },
+ { 0x2274, "\x22\x72\x03\x38\0" },
+ { 0x2275, "\x22\x73\x03\x38\0" },
+ { 0x2278, "\x22\x76\x03\x38\0" },
+ { 0x2279, "\x22\x77\x03\x38\0" },
+ { 0x2280, "\x22\x7a\x03\x38\0" },
+ { 0x2281, "\x22\x7b\x03\x38\0" },
+ { 0x2284, "\x22\x82\x03\x38\0" },
+ { 0x2285, "\x22\x83\x03\x38\0" },
+ { 0x2288, "\x22\x86\x03\x38\0" },
+ { 0x2289, "\x22\x87\x03\x38\0" },
+ { 0x22ac, "\x22\xa2\x03\x38\0" },
+ { 0x22ad, "\x22\xa8\x03\x38\0" },
+ { 0x22ae, "\x22\xa9\x03\x38\0" },
+ { 0x22af, "\x22\xab\x03\x38\0" },
+ { 0x22e0, "\x22\x7c\x03\x38\0" },
+ { 0x22e1, "\x22\x7d\x03\x38\0" },
+ { 0x22e2, "\x22\x91\x03\x38\0" },
+ { 0x22e3, "\x22\x92\x03\x38\0" },
+ { 0x22ea, "\x22\xb2\x03\x38\0" },
+ { 0x22eb, "\x22\xb3\x03\x38\0" },
+ { 0x22ec, "\x22\xb4\x03\x38\0" },
+ { 0x22ed, "\x22\xb5\x03\x38\0" },
+ { 0x2329, "\x30\x08\0" },
+ { 0x232a, "\x30\x09\0" },
+ { 0x304c, "\x30\x4b\x30\x99\0" },
+ { 0x304e, "\x30\x4d\x30\x99\0" },
+ { 0x3050, "\x30\x4f\x30\x99\0" },
+ { 0x3052, "\x30\x51\x30\x99\0" },
+ { 0x3054, "\x30\x53\x30\x99\0" },
+ { 0x3056, "\x30\x55\x30\x99\0" },
+ { 0x3058, "\x30\x57\x30\x99\0" },
+ { 0x305a, "\x30\x59\x30\x99\0" },
+ { 0x305c, "\x30\x5b\x30\x99\0" },
+ { 0x305e, "\x30\x5d\x30\x99\0" },
+ { 0x3060, "\x30\x5f\x30\x99\0" },
+ { 0x3062, "\x30\x61\x30\x99\0" },
+ { 0x3065, "\x30\x64\x30\x99\0" },
+ { 0x3067, "\x30\x66\x30\x99\0" },
+ { 0x3069, "\x30\x68\x30\x99\0" },
+ { 0x3070, "\x30\x6f\x30\x99\0" },
+ { 0x3071, "\x30\x6f\x30\x9a\0" },
+ { 0x3073, "\x30\x72\x30\x99\0" },
+ { 0x3074, "\x30\x72\x30\x9a\0" },
+ { 0x3076, "\x30\x75\x30\x99\0" },
+ { 0x3077, "\x30\x75\x30\x9a\0" },
+ { 0x3079, "\x30\x78\x30\x99\0" },
+ { 0x307a, "\x30\x78\x30\x9a\0" },
+ { 0x307c, "\x30\x7b\x30\x99\0" },
+ { 0x307d, "\x30\x7b\x30\x9a\0" },
+ { 0x3094, "\x30\x46\x30\x99\0" },
+ { 0x309e, "\x30\x9d\x30\x99\0" },
+ { 0x30ac, "\x30\xab\x30\x99\0" },
+ { 0x30ae, "\x30\xad\x30\x99\0" },
+ { 0x30b0, "\x30\xaf\x30\x99\0" },
+ { 0x30b2, "\x30\xb1\x30\x99\0" },
+ { 0x30b4, "\x30\xb3\x30\x99\0" },
+ { 0x30b6, "\x30\xb5\x30\x99\0" },
+ { 0x30b8, "\x30\xb7\x30\x99\0" },
+ { 0x30ba, "\x30\xb9\x30\x99\0" },
+ { 0x30bc, "\x30\xbb\x30\x99\0" },
+ { 0x30be, "\x30\xbd\x30\x99\0" },
+ { 0x30c0, "\x30\xbf\x30\x99\0" },
+ { 0x30c2, "\x30\xc1\x30\x99\0" },
+ { 0x30c5, "\x30\xc4\x30\x99\0" },
+ { 0x30c7, "\x30\xc6\x30\x99\0" },
+ { 0x30c9, "\x30\xc8\x30\x99\0" },
+ { 0x30d0, "\x30\xcf\x30\x99\0" },
+ { 0x30d1, "\x30\xcf\x30\x9a\0" },
+ { 0x30d3, "\x30\xd2\x30\x99\0" },
+ { 0x30d4, "\x30\xd2\x30\x9a\0" },
+ { 0x30d6, "\x30\xd5\x30\x99\0" },
+ { 0x30d7, "\x30\xd5\x30\x9a\0" },
+ { 0x30d9, "\x30\xd8\x30\x99\0" },
+ { 0x30da, "\x30\xd8\x30\x9a\0" },
+ { 0x30dc, "\x30\xdb\x30\x99\0" },
+ { 0x30dd, "\x30\xdb\x30\x9a\0" },
+ { 0x30f4, "\x30\xa6\x30\x99\0" },
+ { 0x30f7, "\x30\xef\x30\x99\0" },
+ { 0x30f8, "\x30\xf0\x30\x99\0" },
+ { 0x30f9, "\x30\xf1\x30\x99\0" },
+ { 0x30fa, "\x30\xf2\x30\x99\0" },
+ { 0x30fe, "\x30\xfd\x30\x99\0" },
+ { 0xf900, "\x8c\x48\0" },
+ { 0xf901, "\x66\xf4\0" },
+ { 0xf902, "\x8e\xca\0" },
+ { 0xf903, "\x8c\xc8\0" },
+ { 0xf904, "\x6e\xd1\0" },
+ { 0xf905, "\x4e\x32\0" },
+ { 0xf906, "\x53\xe5\0" },
+ { 0xf907, "\x9f\x9c\0" },
+ { 0xf908, "\x9f\x9c\0" },
+ { 0xf909, "\x59\x51\0" },
+ { 0xf90a, "\x91\xd1\0" },
+ { 0xf90b, "\x55\x87\0" },
+ { 0xf90c, "\x59\x48\0" },
+ { 0xf90d, "\x61\xf6\0" },
+ { 0xf90e, "\x76\x69\0" },
+ { 0xf90f, "\x7f\x85\0" },
+ { 0xf910, "\x86\x3f\0" },
+ { 0xf911, "\x87\xba\0" },
+ { 0xf912, "\x88\xf8\0" },
+ { 0xf913, "\x90\x8f\0" },
+ { 0xf914, "\x6a\x02\0" },
+ { 0xf915, "\x6d\x1b\0" },
+ { 0xf916, "\x70\xd9\0" },
+ { 0xf917, "\x73\xde\0" },
+ { 0xf918, "\x84\x3d\0" },
+ { 0xf919, "\x91\x6a\0" },
+ { 0xf91a, "\x99\xf1\0" },
+ { 0xf91b, "\x4e\x82\0" },
+ { 0xf91c, "\x53\x75\0" },
+ { 0xf91d, "\x6b\x04\0" },
+ { 0xf91e, "\x72\x1b\0" },
+ { 0xf91f, "\x86\x2d\0" },
+ { 0xf920, "\x9e\x1e\0" },
+ { 0xf921, "\x5d\x50\0" },
+ { 0xf922, "\x6f\xeb\0" },
+ { 0xf923, "\x85\xcd\0" },
+ { 0xf924, "\x89\x64\0" },
+ { 0xf925, "\x62\xc9\0" },
+ { 0xf926, "\x81\xd8\0" },
+ { 0xf927, "\x88\x1f\0" },
+ { 0xf928, "\x5e\xca\0" },
+ { 0xf929, "\x67\x17\0" },
+ { 0xf92a, "\x6d\x6a\0" },
+ { 0xf92b, "\x72\xfc\0" },
+ { 0xf92c, "\x90\xce\0" },
+ { 0xf92d, "\x4f\x86\0" },
+ { 0xf92e, "\x51\xb7\0" },
+ { 0xf92f, "\x52\xde\0" },
+ { 0xf930, "\x64\xc4\0" },
+ { 0xf931, "\x6a\xd3\0" },
+ { 0xf932, "\x72\x10\0" },
+ { 0xf933, "\x76\xe7\0" },
+ { 0xf934, "\x80\x01\0" },
+ { 0xf935, "\x86\x06\0" },
+ { 0xf936, "\x86\x5c\0" },
+ { 0xf937, "\x8d\xef\0" },
+ { 0xf938, "\x97\x32\0" },
+ { 0xf939, "\x9b\x6f\0" },
+ { 0xf93a, "\x9d\xfa\0" },
+ { 0xf93b, "\x78\x8c\0" },
+ { 0xf93c, "\x79\x7f\0" },
+ { 0xf93d, "\x7d\xa0\0" },
+ { 0xf93e, "\x83\xc9\0" },
+ { 0xf93f, "\x93\x04\0" },
+ { 0xf940, "\x9e\x7f\0" },
+ { 0xf941, "\x8a\xd6\0" },
+ { 0xf942, "\x58\xdf\0" },
+ { 0xf943, "\x5f\x04\0" },
+ { 0xf944, "\x7c\x60\0" },
+ { 0xf945, "\x80\x7e\0" },
+ { 0xf946, "\x72\x62\0" },
+ { 0xf947, "\x78\xca\0" },
+ { 0xf948, "\x8c\xc2\0" },
+ { 0xf949, "\x96\xf7\0" },
+ { 0xf94a, "\x58\xd8\0" },
+ { 0xf94b, "\x5c\x62\0" },
+ { 0xf94c, "\x6a\x13\0" },
+ { 0xf94d, "\x6d\xda\0" },
+ { 0xf94e, "\x6f\x0f\0" },
+ { 0xf94f, "\x7d\x2f\0" },
+ { 0xf950, "\x7e\x37\0" },
+ { 0xf951, "\x96\xfb\0" },
+ { 0xf952, "\x52\xd2\0" },
+ { 0xf953, "\x80\x8b\0" },
+ { 0xf954, "\x51\xdc\0" },
+ { 0xf955, "\x51\xcc\0" },
+ { 0xf956, "\x7a\x1c\0" },
+ { 0xf957, "\x7d\xbe\0" },
+ { 0xf958, "\x83\xf1\0" },
+ { 0xf959, "\x96\x75\0" },
+ { 0xf95a, "\x8b\x80\0" },
+ { 0xf95b, "\x62\xcf\0" },
+ { 0xf95c, "\x6a\x02\0" },
+ { 0xf95d, "\x8a\xfe\0" },
+ { 0xf95e, "\x4e\x39\0" },
+ { 0xf95f, "\x5b\xe7\0" },
+ { 0xf960, "\x60\x12\0" },
+ { 0xf961, "\x73\x87\0" },
+ { 0xf962, "\x75\x70\0" },
+ { 0xf963, "\x53\x17\0" },
+ { 0xf964, "\x78\xfb\0" },
+ { 0xf965, "\x4f\xbf\0" },
+ { 0xf966, "\x5f\xa9\0" },
+ { 0xf967, "\x4e\x0d\0" },
+ { 0xf968, "\x6c\xcc\0" },
+ { 0xf969, "\x65\x78\0" },
+ { 0xf96a, "\x7d\x22\0" },
+ { 0xf96b, "\x53\xc3\0" },
+ { 0xf96c, "\x58\x5e\0" },
+ { 0xf96d, "\x77\x01\0" },
+ { 0xf96e, "\x84\x49\0" },
+ { 0xf96f, "\x8a\xaa\0" },
+ { 0xf970, "\x6b\xba\0" },
+ { 0xf971, "\x8f\xb0\0" },
+ { 0xf972, "\x6c\x88\0" },
+ { 0xf973, "\x62\xfe\0" },
+ { 0xf974, "\x82\xe5\0" },
+ { 0xf975, "\x63\xa0\0" },
+ { 0xf976, "\x75\x65\0" },
+ { 0xf977, "\x4e\xae\0" },
+ { 0xf978, "\x51\x69\0" },
+ { 0xf979, "\x51\xc9\0" },
+ { 0xf97a, "\x68\x81\0" },
+ { 0xf97b, "\x7c\xe7\0" },
+ { 0xf97c, "\x82\x6f\0" },
+ { 0xf97d, "\x8a\xd2\0" },
+ { 0xf97e, "\x91\xcf\0" },
+ { 0xf97f, "\x52\xf5\0" },
+ { 0xf980, "\x54\x42\0" },
+ { 0xf981, "\x59\x73\0" },
+ { 0xf982, "\x5e\xec\0" },
+ { 0xf983, "\x65\xc5\0" },
+ { 0xf984, "\x6f\xfe\0" },
+ { 0xf985, "\x79\x2a\0" },
+ { 0xf986, "\x95\xad\0" },
+ { 0xf987, "\x9a\x6a\0" },
+ { 0xf988, "\x9e\x97\0" },
+ { 0xf989, "\x9e\xce\0" },
+ { 0xf98a, "\x52\x9b\0" },
+ { 0xf98b, "\x66\xc6\0" },
+ { 0xf98c, "\x6b\x77\0" },
+ { 0xf98d, "\x8f\x62\0" },
+ { 0xf98e, "\x5e\x74\0" },
+ { 0xf98f, "\x61\x90\0" },
+ { 0xf990, "\x62\x00\0" },
+ { 0xf991, "\x64\x9a\0" },
+ { 0xf992, "\x6f\x23\0" },
+ { 0xf993, "\x71\x49\0" },
+ { 0xf994, "\x74\x89\0" },
+ { 0xf995, "\x79\xca\0" },
+ { 0xf996, "\x7d\xf4\0" },
+ { 0xf997, "\x80\x6f\0" },
+ { 0xf998, "\x8f\x26\0" },
+ { 0xf999, "\x84\xee\0" },
+ { 0xf99a, "\x90\x23\0" },
+ { 0xf99b, "\x93\x4a\0" },
+ { 0xf99c, "\x52\x17\0" },
+ { 0xf99d, "\x52\xa3\0" },
+ { 0xf99e, "\x54\xbd\0" },
+ { 0xf99f, "\x70\xc8\0" },
+ { 0xf9a0, "\x88\xc2\0" },
+ { 0xf9a1, "\x8a\xaa\0" },
+ { 0xf9a2, "\x5e\xc9\0" },
+ { 0xf9a3, "\x5f\xf5\0" },
+ { 0xf9a4, "\x63\x7b\0" },
+ { 0xf9a5, "\x6b\xae\0" },
+ { 0xf9a6, "\x7c\x3e\0" },
+ { 0xf9a7, "\x73\x75\0" },
+ { 0xf9a8, "\x4e\xe4\0" },
+ { 0xf9a9, "\x56\xf9\0" },
+ { 0xf9aa, "\x5b\xe7\0" },
+ { 0xf9ab, "\x5d\xba\0" },
+ { 0xf9ac, "\x60\x1c\0" },
+ { 0xf9ad, "\x73\xb2\0" },
+ { 0xf9ae, "\x74\x69\0" },
+ { 0xf9af, "\x7f\x9a\0" },
+ { 0xf9b0, "\x80\x46\0" },
+ { 0xf9b1, "\x92\x34\0" },
+ { 0xf9b2, "\x96\xf6\0" },
+ { 0xf9b3, "\x97\x48\0" },
+ { 0xf9b4, "\x98\x18\0" },
+ { 0xf9b5, "\x4f\x8b\0" },
+ { 0xf9b6, "\x79\xae\0" },
+ { 0xf9b7, "\x91\xb4\0" },
+ { 0xf9b8, "\x96\xb8\0" },
+ { 0xf9b9, "\x60\xe1\0" },
+ { 0xf9ba, "\x4e\x86\0" },
+ { 0xf9bb, "\x50\xda\0" },
+ { 0xf9bc, "\x5b\xee\0" },
+ { 0xf9bd, "\x5c\x3f\0" },
+ { 0xf9be, "\x65\x99\0" },
+ { 0xf9bf, "\x6a\x02\0" },
+ { 0xf9c0, "\x71\xce\0" },
+ { 0xf9c1, "\x76\x42\0" },
+ { 0xf9c2, "\x84\xfc\0" },
+ { 0xf9c3, "\x90\x7c\0" },
+ { 0xf9c4, "\x9f\x8d\0" },
+ { 0xf9c5, "\x66\x88\0" },
+ { 0xf9c6, "\x96\x2e\0" },
+ { 0xf9c7, "\x52\x89\0" },
+ { 0xf9c8, "\x67\x7b\0" },
+ { 0xf9c9, "\x67\xf3\0" },
+ { 0xf9ca, "\x6d\x41\0" },
+ { 0xf9cb, "\x6e\x9c\0" },
+ { 0xf9cc, "\x74\x09\0" },
+ { 0xf9cd, "\x75\x59\0" },
+ { 0xf9ce, "\x78\x6b\0" },
+ { 0xf9cf, "\x7d\x10\0" },
+ { 0xf9d0, "\x98\x5e\0" },
+ { 0xf9d1, "\x51\x6d\0" },
+ { 0xf9d2, "\x62\x2e\0" },
+ { 0xf9d3, "\x96\x78\0" },
+ { 0xf9d4, "\x50\x2b\0" },
+ { 0xf9d5, "\x5d\x19\0" },
+ { 0xf9d6, "\x6d\xea\0" },
+ { 0xf9d7, "\x8f\x2a\0" },
+ { 0xf9d8, "\x5f\x8b\0" },
+ { 0xf9d9, "\x61\x44\0" },
+ { 0xf9da, "\x68\x17\0" },
+ { 0xf9db, "\x73\x87\0" },
+ { 0xf9dc, "\x96\x86\0" },
+ { 0xf9dd, "\x52\x29\0" },
+ { 0xf9de, "\x54\x0f\0" },
+ { 0xf9df, "\x5c\x65\0" },
+ { 0xf9e0, "\x66\x13\0" },
+ { 0xf9e1, "\x67\x4e\0" },
+ { 0xf9e2, "\x68\xa8\0" },
+ { 0xf9e3, "\x6c\xe5\0" },
+ { 0xf9e4, "\x74\x06\0" },
+ { 0xf9e5, "\x75\xe2\0" },
+ { 0xf9e6, "\x7f\x79\0" },
+ { 0xf9e7, "\x88\xcf\0" },
+ { 0xf9e8, "\x88\xe1\0" },
+ { 0xf9e9, "\x91\xcc\0" },
+ { 0xf9ea, "\x96\xe2\0" },
+ { 0xf9eb, "\x53\x3f\0" },
+ { 0xf9ec, "\x6e\xba\0" },
+ { 0xf9ed, "\x54\x1d\0" },
+ { 0xf9ee, "\x71\xd0\0" },
+ { 0xf9ef, "\x74\x98\0" },
+ { 0xf9f0, "\x85\xfa\0" },
+ { 0xf9f1, "\x96\xa3\0" },
+ { 0xf9f2, "\x9c\x57\0" },
+ { 0xf9f3, "\x9e\x9f\0" },
+ { 0xf9f4, "\x67\x97\0" },
+ { 0xf9f5, "\x6d\xcb\0" },
+ { 0xf9f6, "\x81\xe8\0" },
+ { 0xf9f7, "\x7a\xcb\0" },
+ { 0xf9f8, "\x7b\x20\0" },
+ { 0xf9f9, "\x7c\x92\0" },
+ { 0xf9fa, "\x72\xc0\0" },
+ { 0xf9fb, "\x70\x99\0" },
+ { 0xf9fc, "\x8b\x58\0" },
+ { 0xf9fd, "\x4e\xc0\0" },
+ { 0xf9fe, "\x83\x36\0" },
+ { 0xf9ff, "\x52\x3a\0" },
+ { 0xfa00, "\x52\x07\0" },
+ { 0xfa01, "\x5e\xa6\0" },
+ { 0xfa02, "\x62\xd3\0" },
+ { 0xfa03, "\x7c\xd6\0" },
+ { 0xfa04, "\x5b\x85\0" },
+ { 0xfa05, "\x6d\x1e\0" },
+ { 0xfa06, "\x66\xb4\0" },
+ { 0xfa07, "\x8f\x3b\0" },
+ { 0xfa08, "\x88\x4c\0" },
+ { 0xfa09, "\x96\x4d\0" },
+ { 0xfa0a, "\x89\x8b\0" },
+ { 0xfa0b, "\x5e\xd3\0" },
+ { 0xfa0c, "\x51\x40\0" },
+ { 0xfa0d, "\x55\xc0\0" },
+ { 0xfa10, "\x58\x5a\0" },
+ { 0xfa12, "\x66\x74\0" },
+ { 0xfa15, "\x51\xde\0" },
+ { 0xfa16, "\x73\x2a\0" },
+ { 0xfa17, "\x76\xca\0" },
+ { 0xfa18, "\x79\x3c\0" },
+ { 0xfa19, "\x79\x5e\0" },
+ { 0xfa1a, "\x79\x65\0" },
+ { 0xfa1b, "\x79\x8f\0" },
+ { 0xfa1c, "\x97\x56\0" },
+ { 0xfa1d, "\x7c\xbe\0" },
+ { 0xfa1e, "\x7f\xbd\0" },
+ { 0xfa20, "\x86\x12\0" },
+ { 0xfa22, "\x8a\xf8\0" },
+ { 0xfa25, "\x90\x38\0" },
+ { 0xfa26, "\x90\xfd\0" },
+ { 0xfa2a, "\x98\xef\0" },
+ { 0xfa2b, "\x98\xfc\0" },
+ { 0xfa2c, "\x99\x28\0" },
+ { 0xfa2d, "\x9d\xb4\0" },
+ { 0xfb1f, "\x05\xf2\x05\xb7\0" },
+ { 0xfb2a, "\x05\xe9\x05\xc1\0" },
+ { 0xfb2b, "\x05\xe9\x05\xc2\0" },
+ { 0xfb2c, "\x05\xe9\x05\xbc\x05\xc1\0" },
+ { 0xfb2d, "\x05\xe9\x05\xbc\x05\xc2\0" },
+ { 0xfb2e, "\x05\xd0\x05\xb7\0" },
+ { 0xfb2f, "\x05\xd0\x05\xb8\0" },
+ { 0xfb30, "\x05\xd0\x05\xbc\0" },
+ { 0xfb31, "\x05\xd1\x05\xbc\0" },
+ { 0xfb32, "\x05\xd2\x05\xbc\0" },
+ { 0xfb33, "\x05\xd3\x05\xbc\0" },
+ { 0xfb34, "\x05\xd4\x05\xbc\0" },
+ { 0xfb35, "\x05\xd5\x05\xbc\0" },
+ { 0xfb36, "\x05\xd6\x05\xbc\0" },
+ { 0xfb38, "\x05\xd8\x05\xbc\0" },
+ { 0xfb39, "\x05\xd9\x05\xbc\0" },
+ { 0xfb3a, "\x05\xda\x05\xbc\0" },
+ { 0xfb3b, "\x05\xdb\x05\xbc\0" },
+ { 0xfb3c, "\x05\xdc\x05\xbc\0" },
+ { 0xfb3e, "\x05\xde\x05\xbc\0" },
+ { 0xfb40, "\x05\xe0\x05\xbc\0" },
+ { 0xfb41, "\x05\xe1\x05\xbc\0" },
+ { 0xfb43, "\x05\xe3\x05\xbc\0" },
+ { 0xfb44, "\x05\xe4\x05\xbc\0" },
+ { 0xfb46, "\x05\xe6\x05\xbc\0" },
+ { 0xfb47, "\x05\xe7\x05\xbc\0" },
+ { 0xfb48, "\x05\xe8\x05\xbc\0" },
+ { 0xfb49, "\x05\xe9\x05\xbc\0" },
+ { 0xfb4a, "\x05\xea\x05\xbc\0" },
+ { 0xfb4b, "\x05\xd5\x05\xb9\0" },
+ { 0xfb4c, "\x05\xd1\x05\xbf\0" },
+ { 0xfb4d, "\x05\xdb\x05\xbf\0" },
+ { 0xfb4e, "\x05\xe4\x05\xbf\0" }
+};
+
+/*
+ * WARNING!
+ *
+ * NO BUFFER CHECKING AHEAD!
+ *
+ */
+
+static gint
+e_canonical_decomposition (gunichar ch, gunichar * buf)
+{
+ gint len = 0;
+
+ if (ch <= 0xffff)
+ {
+ int start = 0;
+ int end = sizeof (e_decomp_table) / sizeof (e_decomp_table[0]);
+ while (start != end)
+ {
+ int half = (start + end) / 2;
+ if (ch == e_decomp_table[half].ch) {
+ /* Found it. */
+ int i;
+ /* We store as a double-nul terminated string. */
+ for (len = 0; (e_decomp_table[half].expansion[len] || e_decomp_table[half].expansion[len + 1]); len += 2) ;
+
+ /* We've counted twice as many bytes as there are
+ characters. */
+ len /= 2;
+
+ for (i = 0; i < len; i ++) {
+ buf[i] = (e_decomp_table[half].expansion[2 * i] << 8) | e_decomp_table[half].expansion[2 * i + 1];
+ }
+ break;
+ } else if (ch > e_decomp_table[half].ch) {
+ if (start == half) break;
+ start = half;
+ } else {
+ if (end == half) break;
+ end = half;
+ }
+ }
+ }
+
+ if (len == 0)
+ {
+ /* Not in our table. */
+ *buf = ch;
+ len = 1;
+ }
+
+ /* Supposedly following the Unicode 2.1.9 table means that the
+ decompositions come out in canonical order. I haven't tested
+ this, but we rely on it here. */
+ return len;
+}
+
+static gunichar
+e_stripped_char (gunichar ch)
+{
+ gunichar decomp[MAX_DECOMP];
+ GUnicodeType utype;
+ gint dlen;
+
+ utype = g_unichar_type (ch);
+
+ switch (utype) {
+ case G_UNICODE_CONTROL:
+ case G_UNICODE_FORMAT:
+ case G_UNICODE_UNASSIGNED:
+ case G_UNICODE_COMBINING_MARK:
+ /* Ignore those */
+ return 0;
+ default:
+ /* Convert to lowercase, fall through */
+ ch = g_unichar_tolower (ch);
+ case G_UNICODE_LOWERCASE_LETTER:
+ dlen = e_canonical_decomposition (ch, decomp);
+ if (dlen > 0) return *decomp;
+ break;
+ }
+
+ return 0;
+}
+
+gchar *
+e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent, const xmlChar *prop_name)
+{
+ xmlChar *prop;
+ gchar *ret_val = NULL;
+ gchar *combined_name;
+
+ g_return_val_if_fail (parent != NULL, NULL);
+ g_return_val_if_fail (prop_name != NULL, NULL);
+
+ prop = xmlGetProp ((xmlNode *) parent, prop_name);
+ if (prop != NULL) {
+ ret_val = g_strdup ((char *)prop);
+ xmlFree (prop);
+ return ret_val;
+ }
+
+ combined_name = g_strdup_printf("_%s", prop_name);
+ prop = xmlGetProp ((xmlNode *) parent, (unsigned char *)combined_name);
+ if (prop != NULL) {
+ ret_val = g_strdup (gettext ((char *)prop));
+ xmlFree (prop);
+ }
+ g_free(combined_name);
+
+ return ret_val;
+}
diff --git a/e-util/e-unicode.h b/e-util/e-unicode.h
new file mode 100644
index 0000000000..b745876b6d
--- /dev/null
+++ b/e-util/e-unicode.h
@@ -0,0 +1,113 @@
+/*
+ * e-unicode.h - utf-8 support functions for gal
+ *
+ * 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:
+ * Lauris Kaplinski <lauris@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef _E_UNICODE_H_
+#define _E_UNICODE_H_
+
+#include <sys/types.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libxml/tree.h>
+#include <iconv.h>
+
+G_BEGIN_DECLS
+
+#define G_UTF8_IN_GAL
+
+/*
+ * UTF-8 searching implementations
+ *
+ * e_utf8_strstrcase - case insensitive search
+ * e_utf8_strstrcasedecomp - case insensitive and decompositing search (i.e. accented
+ * letters are treated equal to their base letters, explicit accent marks (unicode
+ * not ascii/iso ones) are ignored).
+ */
+
+const gchar *e_utf8_strstrcase (const gchar *haystack,
+ const gchar *needle);
+const gchar *e_utf8_strstrcasedecomp (const gchar *haystack,
+ const gchar *needle);
+gchar *e_utf8_from_gtk_event_key (GtkWidget *widget,
+ guint keyval,
+ const gchar *string);
+gchar *e_utf8_from_iconv_string (iconv_t ic,
+ const gchar *string);
+gchar *e_utf8_from_iconv_string_sized (iconv_t ic,
+ const gchar *string,
+ gint bytes);
+gchar *e_utf8_to_iconv_string (iconv_t ic,
+ const gchar *string);
+gchar *e_utf8_to_iconv_string_sized (iconv_t ic,
+ const gchar *string,
+ gint bytes);
+gchar *e_utf8_from_charset_string (const gchar *charset,
+ const gchar *string);
+gchar *e_utf8_from_charset_string_sized (const gchar *charset,
+ const gchar *string,
+ gint bytes);
+gchar *e_utf8_to_charset_string (const gchar *charset,
+ const gchar *string);
+gchar *e_utf8_to_charset_string_sized (const gchar *charset,
+ const gchar *string,
+ gint bytes);
+gchar *e_utf8_from_locale_string (const gchar *string);
+gchar *e_utf8_from_locale_string_sized (const gchar *string,
+ gint bytes);
+gchar *e_utf8_to_locale_string (const gchar *string);
+gchar *e_utf8_to_locale_string_sized (const gchar *string,
+ gint bytes);
+gboolean e_utf8_is_ascii (const gchar *string);
+/*
+ * These are simple wrappers that save us some typing
+ */
+
+/* NB! This return newly allocated string, not const as gtk+ one */
+gchar *e_utf8_gtk_entry_get_text (GtkEntry *entry);
+void e_utf8_gtk_entry_set_text (GtkEntry *entry,
+ const gchar *text);
+gchar *e_utf8_gtk_editable_get_text (GtkEditable *editable);
+void e_utf8_gtk_editable_set_text (GtkEditable *editable,
+ const gchar *text);
+gchar *e_utf8_gtk_editable_get_chars (GtkEditable *editable,
+ gint start,
+ gint end);
+void e_utf8_gtk_editable_insert_text (GtkEditable *editable,
+ const gchar *text,
+ gint length,
+ gint *position);
+gchar *e_utf8_xml1_decode (const gchar *text);
+gchar *e_utf8_xml1_encode (const gchar *text);
+gint e_unichar_to_utf8 (gint c,
+ gchar *outbuf);
+gchar *e_unicode_get_utf8 (const gchar *text,
+ gunichar *out);
+guint32 gdk_keyval_to_unicode (guint keysym);
+gchar *e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent,
+ const xmlChar *prop_name);
+
+G_END_DECLS
+
+#endif
+
+
diff --git a/e-util/e-util-labels.c b/e-util/e-util-labels.c
deleted file mode 100644
index 85984da59c..0000000000
--- a/e-util/e-util-labels.c
+++ /dev/null
@@ -1,586 +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:
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include <gconf/gconf-client.h>
-
-#include <camel/camel-utf8.h>
-
-#include "e-util.h"
-#include "e-util-labels.h"
-#include "e-dialog-utils.h"
-#include "filter/filter-option.h"
-
-/* Note, the first element of each EUtilLabel must NOT be translated */
-EUtilLabel label_defaults[LABEL_DEFAULTS_NUM] = {
- { "$Labelimportant", N_("I_mportant"), "#EF2929" }, /* red */
- { "$Labelwork", N_("_Work"), "#F57900" }, /* orange */
- { "$Labelpersonal", N_("_Personal"), "#4E9A06" }, /* green */
- { "$Labeltodo", N_("_To Do"), "#3465A4" }, /* blue */
- { "$Labellater", N_("_Later"), "#75507B" } /* purple */
-};
-
-/**
- * e_util_labels_parse
- * Reads the setup from client and parses it to list of EUtilLabel objects.
- *
- * @param client The config client to be used for reading setup.
- * Can be NULL, in that case it will use the default client.
- * @return Newly allocated list of labels, should be freed with @ref e_util_labels_free.
- **/
-GSList *
-e_util_labels_parse (GConfClient *client)
-{
- GSList *labels, *list, *head;
- EUtilLabel *label;
- char *buf;
- int num = 0;
- gboolean unref_client = client == NULL;
-
- labels = NULL;
-
- if (!client)
- client = gconf_client_get_default ();
-
- head = gconf_client_get_list (client, E_UTIL_LABELS_GCONF_KEY, GCONF_VALUE_STRING, NULL);
-
- for (list = head; list; list = list->next) {
- char *color, *name, *tag;
- name = buf = list->data;
- color = strrchr (buf, ':');
- if (color == NULL) {
- g_free (buf);
- continue;
- }
-
- *color++ = '\0';
- tag = strchr (color, '|');
- if (tag)
- *tag++ = '\0';
-
- label = g_new (EUtilLabel, 1);
-
- /* Needed for Backward Compatibility */
- if (num < LABEL_DEFAULTS_NUM) {
- label->name = g_strdup ((buf && *buf) ? buf : _(label_defaults[num].name));
- label->tag = g_strdup (label_defaults[num].tag);
- num++;
- } else if (!tag) {
- g_free (buf);
- g_free (label);
- continue;
- } else {
- label->name = g_strdup (name);
- label->tag = g_strdup (tag);
- }
-
- label->colour = g_strdup (color);
- labels = g_slist_prepend (labels, label);
-
- g_free (buf);
- }
-
- if (head)
- g_slist_free (head);
-
- while (num < LABEL_DEFAULTS_NUM) {
- /* complete the list with defaults */
- label = g_new (EUtilLabel, 1);
- label->tag = g_strdup (label_defaults[num].tag);
- label->name = g_strdup (_(label_defaults[num].name));
- label->colour = g_strdup (label_defaults[num].colour);
-
- labels = g_slist_prepend (labels, label);
-
- num++;
- }
-
- if (unref_client)
- g_object_unref (client);
-
- return g_slist_reverse (labels);
-}
-
-static void
-free_label_struct (EUtilLabel *label)
-{
- if (!label)
- return;
-
- g_free (label->tag);
- g_free (label->name);
- g_free (label->colour);
- g_free (label);
-}
-
-/**
- * e_util_labels_free
- * Frees memory previously allocated by @ref e_util_labels_parse
- *
- * @param labels Labels list, previously allocated by @ref e_util_labels_parse
- * It is safe to call with NULL.
- **/
-void
-e_util_labels_free (GSList *labels)
-{
- if (!labels)
- return;
-
- g_slist_foreach (labels, (GFunc)free_label_struct, NULL);
- g_slist_free (labels);
-}
-
-/* stores the actual cache to gconf */
-static gboolean
-flush_labels_cache (GSList *labels, gboolean free_labels)
-{
- GSList *l, *text_labels;
- GConfClient *client;
-
- if (!labels)
- return FALSE;
-
- text_labels = NULL;
-
- for (l = labels; l; l = l->next) {
- EUtilLabel *label = l->data;
-
- if (label && label->tag && label->name && label->colour)
- text_labels = g_slist_prepend (text_labels, g_strdup_printf ("%s:%s|%s", label->name, label->colour, label->tag));
- }
-
- if (!text_labels) {
- if (free_labels)
- e_util_labels_free (labels);
-
- return FALSE;
- }
-
- text_labels = g_slist_reverse (text_labels);
-
- client = gconf_client_get_default ();
- gconf_client_set_list (client, E_UTIL_LABELS_GCONF_KEY, GCONF_VALUE_STRING, text_labels, NULL);
- g_object_unref (client);
-
- g_slist_foreach (text_labels, (GFunc)g_free, NULL);
- g_slist_free (text_labels);
-
- if (free_labels)
- e_util_labels_free (labels);
-
- /* not true if gconf failed to write; who cares */
- return TRUE;
-}
-
-/**
- * find_label
- *
- * Looks for label in labels cache by tag and returns actual pointer to cache.
- * @param labels The cache of labels; comes from @ref e_util_labels_parse
- * @param tag Tag of label you are looking for.
- * @return Pointer to cache data if label with such tag exists or NULL. Do not free it!
- **/
-static EUtilLabel *
-find_label (GSList *labels, const char *tag)
-{
- GSList *l;
-
- g_return_val_if_fail (tag != NULL, NULL);
-
- for (l = labels; l; l = l->next) {
- EUtilLabel *label = l->data;
-
- if (label && label->tag && !strcmp (tag, label->tag))
- return label;
- }
-
- return NULL;
-}
-
-
-static char *
-tag_from_name (const char *name)
-{
- /* this does thunderbird, just do not ask */
- char *s1, *s2, *p;
- const char *bads = " ()/{%*<>\\\"";
-
- if (!name || !*name)
- return NULL;
-
- s1 = g_strdup (name);
- for (p = s1; p && *p; p++) {
- if (strchr (bads, *p))
- *p = '_';
- }
-
- s2 = camel_utf8_utf7 (s1);
- g_free (s1);
-
- s1 = g_ascii_strdown (s2, -1);
- g_free (s2);
-
- return s1;
-}
-
-/**
- * e_util_labels_add
- * Creates new label at the end of actual list of labels.
- *
- * @param name User readable name of this label. Should not be NULL.
- * @param color Color assigned to this label. Should not be NULL.
- * @return If succeeded then new label tag, NULL otherwise.
- * Returned pointer should be freed with g_free.
- * It will return NULL when the tag will be same as already existed.
- * Tag name is generated in similar way as in Thunderbird.
- **/
-char *
-e_util_labels_add (const char *name, const GdkColor *color)
-{
- EUtilLabel *label;
- GSList *labels;
- char *tag;
-
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (color != NULL, NULL);
-
- labels = e_util_labels_parse (NULL);
- tag = tag_from_name (name);
-
- if (!tag || find_label (labels, tag) != NULL) {
- g_free (tag);
- e_util_labels_free (labels);
- return NULL;
- }
-
- label = g_new0 (EUtilLabel, 1);
- label->tag = g_strdup (tag);
- label->name = g_strdup (name);
- label->colour = gdk_color_to_string (color);
-
- labels = g_slist_append (labels, label);
-
- flush_labels_cache (labels, TRUE);
-
- return tag;
-}
-
-/**
- * e_util_labels_add_with_dlg
- * This will open a dialog to add or edit label.
- *
- * @param parent Parent widget for the dialog.
- * @param tag A tag for existing label to edit or NULL to add new label.
- * @return Tag for newly added label or NULL, if something failed.
- * Returned value should be freed with g_free.
- **/
-char *
-e_util_labels_add_with_dlg (GtkWindow *parent, const char *tag)
-{
- GtkWidget *table, *dialog, *l, *e, *c;
- const char *name;
- GdkColor color;
- gboolean is_edit = FALSE;
- char *new_tag = NULL;
- GSList *labels;
-
- table = gtk_table_new (2, 2, FALSE);
-
- labels = e_util_labels_parse (NULL);
- name = tag ? e_util_labels_get_name (labels, tag) : NULL;
-
- l = gtk_label_new_with_mnemonic (_("Label _Name:"));
- e = gtk_entry_new ();
- c = gtk_color_button_new ();
-
- if (!tag || !e_util_labels_get_color (labels, tag, &color))
- memset (&color, 0xCD, sizeof (GdkColor));
- else
- is_edit = TRUE;
-
- if (name)
- gtk_entry_set_text (GTK_ENTRY (e), name);
-
- gtk_entry_set_activates_default (GTK_ENTRY (e), TRUE);
- gtk_label_set_mnemonic_widget (GTK_LABEL (l), e);
- gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.0);
- gtk_color_button_set_color (GTK_COLOR_BUTTON (c), &color);
-
- gtk_table_attach (GTK_TABLE (table), l, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (table), e, 0, 1, 1, 2, 0, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (table), c, 1, 2, 1, 2, 0, 0, 0, 0);
- gtk_container_set_border_width (GTK_CONTAINER (table), 10);
- gtk_widget_show_all (table);
-
- dialog = gtk_dialog_new_with_buttons (is_edit ? _("Edit Label") : _("Add Label"),
- parent,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- NULL);
-
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0);
-
- while (!new_tag) {
- const char *error = NULL;
-
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
- name = gtk_entry_get_text (GTK_ENTRY (e));
- gtk_color_button_get_color (GTK_COLOR_BUTTON (c), &color);
-
- if (!name || !*name)
- error = _("Label name cannot be empty.");
- else if (is_edit) {
- e_util_labels_set_data (tag, name, &color);
- break;
- } else if (!(new_tag = e_util_labels_add (name, &color)))
- error = _("A label having the same tag already exists on the server. Please rename your label.");
- else
- break;
- } else
- break;
-
- if (error)
- e_notice (parent, GTK_MESSAGE_ERROR, error);
- }
-
- gtk_widget_destroy (dialog);
- e_util_labels_free (labels);
-
- return new_tag;
-}
-
-/**
- * e_util_labels_remove
- *
- * @param tag Tag of the label to remove.
- * @return Whether was removed.
- **/
-gboolean
-e_util_labels_remove (const char *tag)
-{
- EUtilLabel *label;
- GSList *labels;
-
- g_return_val_if_fail (tag != NULL, FALSE);
-
- labels = e_util_labels_parse (NULL);
- label = find_label (labels, tag);
-
- if (!label) {
- e_util_labels_free (labels);
- return FALSE;
- }
-
- labels = g_slist_remove (labels, label);
-
- free_label_struct (label);
-
- return flush_labels_cache (labels, TRUE);
-}
-
-/**
- * e_util_labels_set_data
- *
- * @param tag Tag of the label of our interest.
- * @param name New name for the label.
- * @param color New color for the label.
- * @return Whether successfully saved.
- **/
-gboolean
-e_util_labels_set_data (const char *tag, const char *name, const GdkColor *color)
-{
- EUtilLabel *label;
- GSList *labels;
-
- g_return_val_if_fail (tag != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
- g_return_val_if_fail (color != NULL, FALSE);
-
- labels = e_util_labels_parse (NULL);
- label = find_label (labels, tag);
-
- if (!label) {
- e_util_labels_free (labels);
- return FALSE;
- }
-
- g_free (label->name);
- label->name = g_strdup (name);
-
- g_free (label->colour);
- label->colour = gdk_color_to_string (color);
-
- return flush_labels_cache (labels, TRUE);
-}
-
-/**
- * e_util_labels_is_system
- *
- * @return Whether the tag is one of default/system labels or not.
- **/
-gboolean
-e_util_labels_is_system (const char *tag)
-{
- int i;
-
- if (!tag)
- return FALSE;
-
- for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
- if (strcmp (tag, label_defaults[i].tag) == 0)
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * e_util_labels_get_new_tag
- *
- * @param old_tag Tag of the label from old version of Evolution.
- * @return New tag name equivalent with the old tag, or NULL if no such name existed before.
- **/
-const char *
-e_util_labels_get_new_tag (const char *old_tag)
-{
- int i;
-
- if (!old_tag)
- return NULL;
-
- for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
- /* default labels have same name as those old, only with prefix "$Label" */
- if (!strcmp (old_tag, label_defaults[i].tag + 6))
- return label_defaults[i].tag;
- }
-
- return NULL;
-}
-
-/**
- * e_util_labels_get_name
- *
- * @param labels Cache of labels from call of @ref e_util_labels_parse.
- * The returned pointer will be taken from this list, so it's alive as long as the list.
- * @param tag Tag of the label of our interest.
- * @return Name of the label with that tag or NULL, if no such label exists.
- **/
-const char *
-e_util_labels_get_name (GSList *labels, const char *tag)
-{
- EUtilLabel *label;
-
- g_return_val_if_fail (tag != NULL, NULL);
-
- label = find_label (labels, tag);
- if (!label)
- return NULL;
-
- return label->name;
-}
-
-/**
- * e_util_labels_get_color
- *
- * @param labels Cache of labels from call of @ref e_util_labels_parse.
- * @param tag Tag of the label of our interest.
- * @param color [out] Actual color of the label with that tag, or unchanged if failed.
- * @return Whether found such label and color has been set.
- **/
-gboolean
-e_util_labels_get_color (GSList *labels, const char *tag, GdkColor *color)
-{
- EUtilLabel *label;
-
- g_return_val_if_fail (tag != NULL, FALSE);
- g_return_val_if_fail (color != NULL, FALSE);
-
- label = find_label (labels, tag);
- if (!label)
- return FALSE;
-
- return gdk_color_parse (label->colour, color);
-}
-
-/**
- * e_util_labels_get_color_str
- *
- * @param labels Cache of labels from call of @ref e_util_labels_parse.
- * The returned pointer will be taken from this list, so it's alive as long as the list.
- * @param tag Tag of the label of our interest.
- * @return String representation of that label, or NULL, is no such label exists.
- **/
-const char *
-e_util_labels_get_color_str (GSList *labels, const char *tag)
-{
- EUtilLabel *label;
-
- g_return_val_if_fail (tag != NULL, FALSE);
-
- label = find_label (labels, tag);
- if (!label)
- return FALSE;
-
- return label->colour;
-}
-
-/**
- * e_util_labels_get_filter_options:
- * Returns list of newly allocated struct _filter_option-s, to be used in filters.
- **/
-GSList *
-e_util_labels_get_filter_options (void)
-{
- GSList *known = e_util_labels_parse (NULL), *l;
- GSList *res = NULL;
-
- for (l = known; l; l = l->next) {
- EUtilLabel *label = l->data;
- const char *tag;
- struct _filter_option *fo;
-
- if (!label)
- continue;
-
- tag = label->tag;
-
- if (tag && strncmp (tag, "$Label", 6) == 0)
- tag += 6;
-
- fo = g_new0 (struct _filter_option, 1);
- fo->title = e_str_without_underscores (label->name);
- fo->value = g_strdup (tag);
-
- res = g_slist_prepend (res, fo);
- }
-
- e_util_labels_free (known);
-
- return g_slist_reverse (res);
-}
diff --git a/e-util/e-util-labels.h b/e-util/e-util-labels.h
deleted file mode 100644
index 26520ff226..0000000000
--- a/e-util/e-util-labels.h
+++ /dev/null
@@ -1,57 +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/>
- *
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _E_UTIL_LABELS_H
-#define _E_UTIL_LABELS_H
-
-#include <gtk/gtk.h>
-
-struct _GtkWindow;
-struct _GConfClient;
-
-typedef struct {
- char *tag;
- char *name;
- char *colour;
-} EUtilLabel;
-
-#define E_UTIL_LABELS_GCONF_KEY "/apps/evolution/mail/labels"
-
-#define LABEL_DEFAULTS_NUM 5
-extern EUtilLabel label_defaults[LABEL_DEFAULTS_NUM];
-
-GSList * e_util_labels_parse (struct _GConfClient *client);
-void e_util_labels_free (GSList *labels);
-
-char * e_util_labels_add (const char *name, const GdkColor *color);
-char * e_util_labels_add_with_dlg (struct _GtkWindow *parent, const char *tag);
-gboolean e_util_labels_remove (const char *tag);
-gboolean e_util_labels_set_data (const char *tag, const char *name, const GdkColor *color);
-
-gboolean e_util_labels_is_system (const char *tag);
-const char *e_util_labels_get_new_tag (const char *old_tag);
-
-const char *e_util_labels_get_name (GSList *labels, const char *tag);
-gboolean e_util_labels_get_color (GSList *labels, const char *tag, GdkColor *color);
-const char *e_util_labels_get_color_str (GSList *labels, const char *tag);
-
-GSList * e_util_labels_get_filter_options (void);
-
-#endif /* _E_UTIL_LABELS_H */
diff --git a/e-util/e-util.c b/e-util/e-util.c
index fc4f71f187..576f46e54b 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -521,6 +521,30 @@ e_write_file_uri (const gchar *filename, const gchar *data)
return res;
}
+/**
+ * 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)
+{
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+
+ g_return_val_if_fail (color != NULL, 0);
+
+ red = color->red >> 8;
+ green = color->green >> 8;
+ blue = color->blue >> 8;
+
+ return (guint32) (((red << 16) | (green << 8) | blue) & 0xffffff);
+}
+
static gint
epow10 (gint number)
{
@@ -1487,27 +1511,6 @@ e_util_read_file (const char *filename, gboolean filename_is_uri, char **buffer,
return res;
}
-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 char *cname = l->data;
- struct _filter_option *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);
-}
-
static gpointer
e_camel_object_copy (gpointer camel_object)
{
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 480da24eac..c748aaed8e 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -69,6 +69,7 @@ gint e_int_compare (gconstpointer x,
gconstpointer y);
gboolean e_write_file_uri (const gchar *filename,
const gchar *data);
+guint32 e_color_to_value (GdkColor *color);
/* This only makes a filename safe for usage as a filename.
* It still may have shell meta-characters in it. */
@@ -129,7 +130,8 @@ gboolean e_file_lock_create (void);
void e_file_lock_destroy (void);
gboolean e_file_lock_exists (void);
-gchar * e_util_guess_mime_type (const gchar *filename, gboolean localfile);
+gchar * e_util_guess_mime_type (const gchar *filename,
+ gboolean localfile);
gchar * e_util_filename_to_uri (const gchar *filename);
gchar * e_util_uri_to_filename (const gchar *uri);
@@ -139,7 +141,15 @@ gboolean e_util_read_file (const gchar *filename,
gsize *read,
GError **error);
-GSList *e_util_get_category_filter_options (void);
+/* Camel uses its own object system, so we have to box
+ * CamelObjects to safely use them as GObject properties. */
+#define E_TYPE_CAMEL_OBJECT (e_camel_object_get_type ())
+GType e_camel_object_get_type (void);
+
+/* Camel uses its own object system, so we have to box
+ * CamelObjects to safely use them as GObject properties. */
+#define E_TYPE_CAMEL_OBJECT (e_camel_object_get_type ())
+GType e_camel_object_get_type (void);
/* Camel uses its own object system, so we have to box
* CamelObjects to safely use them as GObject properties. */
diff --git a/e-util/gconf-bridge.c b/e-util/gconf-bridge.c
index 81fe08ef14..852d5f8f53 100644
--- a/e-util/gconf-bridge.c
+++ b/e-util/gconf-bridge.c
@@ -1082,17 +1082,17 @@ gconf_bridge_bind_string_list_store (GConfBridge *bridge,
(list_store_binding_store_changed_cb),
binding);
binding->row_changed_id =
- g_signal_connect_swapped (list_store, "row-inserted",
+ g_signal_connect_swapped (list_store, "row-changed",
G_CALLBACK
(list_store_binding_store_changed_cb),
binding);
binding->row_deleted_id =
- g_signal_connect_swapped (list_store, "row-inserted",
+ g_signal_connect_swapped (list_store, "row-deleted",
G_CALLBACK
(list_store_binding_store_changed_cb),
binding);
binding->rows_reordered_id =
- g_signal_connect_swapped (list_store, "row-inserted",
+ g_signal_connect_swapped (list_store, "rows-reordered",
G_CALLBACK
(list_store_binding_store_changed_cb),
binding);