diff options
Diffstat (limited to 'src/ibusobservedpath.c')
-rw-r--r-- | src/ibusobservedpath.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/ibusobservedpath.c b/src/ibusobservedpath.c new file mode 100644 index 0000000..4dea00b --- /dev/null +++ b/src/ibusobservedpath.c @@ -0,0 +1,335 @@ +/* vim:set et sts=4: */ +/* ibus - The Input IBus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library 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) any later version. + * + * This library 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 this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <glib/gstdio.h> +#include <stdlib.h> +#include "ibusobservedpath.h" + + +enum { + LAST_SIGNAL, +}; + + +/* IBusObservedPathPriv */ +struct _IBusObservedPathPrivate { + gpointer pad; +}; +typedef struct _IBusObservedPathPrivate IBusObservedPathPrivate; + +#define IBUS_OBSERVED_PATH_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_observed_path_class_init (IBusObservedPathClass *klass); +static void ibus_observed_path_init (IBusObservedPath *path); +static void ibus_observed_path_destroy (IBusObservedPath *path); +static gboolean ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src); +static gboolean ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_observed_path_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusObservedPathClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_observed_path_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusObservedPath), + 0, + (GInstanceInitFunc) ibus_observed_path_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusObservedPath", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_observed_path_class_init (IBusObservedPathClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + // g_type_class_add_private (klass, sizeof (IBusObservedPathPrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_observed_path_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_observed_path_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_observed_path_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_observed_path_copy; + + g_string_append (serializable_class->signature, "sx"); +} + + +static void +ibus_observed_path_init (IBusObservedPath *path) +{ + path->path = NULL; +} + +static void +ibus_observed_path_destroy (IBusObservedPath *path) +{ + g_free (path->path); + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (path)); +} + +static gboolean +ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &(path->path)); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + path->path = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + dest->path = g_strdup (src->path); + dest->mtime = src->mtime; + + return TRUE; +} + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_observed_path_output (IBusObservedPath *path, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (output); + + g_string_append_indent (output, indent); + g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n", + path->mtime, + path->path); +} + +gboolean +ibus_observed_path_check_modification (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + struct stat buf; + + if (g_stat (path->path, &buf) != 0) { + buf.st_mtime = 0; + } + + if (path->mtime == buf.st_mtime) + return FALSE; + return TRUE; +} + +static void +ibus_observed_path_fill_stat (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + struct stat buf; + + if (g_stat (path->path, &buf) == 0) { + path->is_exist = 1; + if (S_ISDIR (buf.st_mode)) { + path->is_dir = 1; + } + path->mtime = buf.st_mtime; + } + else { + path->is_dir = 0; + path->is_exist = 0; + path->mtime = 0; + } +} + +GList * +ibus_observed_path_traverse (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + GDir *dir; + const gchar *name; + GList *paths = NULL; + + dir = g_dir_open (path->path, 0, NULL); + + if (dir == NULL) + return NULL; + + while ((name = g_dir_read_name (dir)) != NULL) { + IBusObservedPath *sub; + + sub = g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + sub->path = g_build_filename (path->path, name, NULL); + + ibus_observed_path_fill_stat (sub); + paths = g_list_append (paths, sub); + + if (sub->is_exist && sub->is_dir) + paths = g_list_concat (paths, ibus_observed_path_traverse (sub)); + } + g_dir_close (dir); + + return paths; +} + +static gboolean +ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (node); + + if (G_UNLIKELY (g_strcmp0 (node->name, "path") != 0)) { + return FALSE; + } + + if (node->text[0] == '~' && node->text[1] != G_DIR_SEPARATOR) { + g_warning ("invalide path \"%s\"", node->text); + return FALSE; + } + + if (node->text[0] == '~') { + const gchar *homedir = g_getenv ("HOME"); + if (homedir == NULL) + homedir = g_get_home_dir (); + path->path = g_build_filename (homedir, node->text + 2, NULL); + } + else { + path->path = g_strdup (node->text); + } + + gchar **attr; + for (attr = node->attributes; attr[0]; attr += 2) { + if (g_strcmp0 (*attr, "mtime") == 0) { + path->mtime = atol (attr[1]); + continue; + } + g_warning ("Unkonwn attribute %s", attr[0]); + } + + return TRUE; +} + +IBusObservedPath * +ibus_observed_path_new_from_xml_node (XMLNode *node, + gboolean fill_stat) +{ + g_assert (node); + + IBusObservedPath *path; + + path = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + + if (!ibus_observed_path_parse_xml_node (path, node)) { + g_object_unref (path); + path = NULL; + } + else if (fill_stat) { + ibus_observed_path_fill_stat (path); + } + + return path; +} + +IBusObservedPath * +ibus_observed_path_new (const gchar *path, + gboolean fill_stat) +{ + g_assert (path); + + IBusObservedPath *op; + + op = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + op->path = g_strdup (path); + + if (fill_stat) { + ibus_observed_path_fill_stat (op); + } + + return op; +} + |