ekiga r6456 - trunk/lib/gui



Author: jpuydt
Date: Tue Jul 15 13:58:11 2008
New Revision: 6456
URL: http://svn.gnome.org/viewvc/ekiga?rev=6456&view=rev

Log:
New code to handle anchored text styles and smileys in text buffers -- the previous code was having issues with things like "<u><b>foo</b></u>", for example!

Added:
   trunk/lib/gui/gm-text-anchored-tag.c
   trunk/lib/gui/gm-text-anchored-tag.h
   trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.c
   trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.h
   trunk/lib/gui/gm-text-buffer-enhancer.c
   trunk/lib/gui/gm-text-buffer-enhancer.h
   trunk/lib/gui/gm-text-smiley.c
   trunk/lib/gui/gm-text-smiley.h
Modified:
   trunk/lib/gui/Makefile.am

Modified: trunk/lib/gui/Makefile.am
==============================================================================
--- trunk/lib/gui/Makefile.am	(original)
+++ trunk/lib/gui/Makefile.am	Tue Jul 15 13:58:11 2008
@@ -36,7 +36,15 @@
 	gmcellrendererexpander.c  \
 	gmcellrendererexpander.h  \
 	gm-cell-renderer-bitext.c \
-	gm-cell-renderer-bitext.h
+	gm-cell-renderer-bitext.h \
+	gm-text-buffer-enhancer-helper-iface.c \
+	gm-text-buffer-enhancer-helper-iface.h \
+	gm-text-anchored-tag.c \
+	gm-text-anchored-tag.h \
+	gm-text-smiley.c \
+	gm-text-smiley.h \
+	gm-text-buffer-enhancer.c \
+	gm-text-buffer-enhancer.h
 
 
 if !WIN32

Added: trunk/lib/gui/gm-text-anchored-tag.c
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-anchored-tag.c	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,239 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-anchored-tag.c  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Implementation of an anchor-based text decorator
+ *
+ */
+
+#include "gm-text-anchored-tag.h"
+
+#include <string.h>
+
+typedef struct _GmTextAnchoredTagPrivate GmTextAnchoredTagPrivate;
+
+struct _GmTextAnchoredTagPrivate {
+  gchar* anchor;
+  GtkTextTag* tag;
+  gboolean opening;
+};
+
+#define GM_TEXT_ANCHORED_TAG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), GM_TYPE_TEXT_ANCHORED_TAG, GmTextAnchoredTagPrivate))
+
+static GObjectClass* parent_class = NULL;
+
+/* declaration of the GmTextBufferEnhancerHelperIFace code */
+
+static void enhancer_helper_check (GmTextBufferEnhancerHelperIFace* self,
+				   const gchar* full_text,
+				   gint from,
+				   gint* start,
+				   gint* length);
+
+static void enhancer_helper_enhance (GmTextBufferEnhancerHelperIFace* self,
+				     GtkTextBuffer* buffer,
+				     GtkTextIter* iter,
+				     GSList** tags,
+				     const gchar* full_text,
+				     gint* start,
+				     gint length);
+
+static void enhancer_helper_iface_init (gpointer g_iface,
+					gpointer iface_data);
+
+/* implementation of the GmTextBufferEnhancerHelperIFace code */
+
+static void
+enhancer_helper_check (GmTextBufferEnhancerHelperIFace* self,
+		       const gchar* full_text,
+		       gint from,
+		       gint* start,
+		       gint* length)
+{
+  GmTextAnchoredTagPrivate* priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE (self);
+  char* found = NULL;
+
+  found = strstr (full_text + from, priv->anchor);
+
+  if (found != NULL) {
+
+    *start = found - full_text;
+    *length = strlen (priv->anchor);
+  } else
+    *length = 0;
+}
+
+static void
+enhancer_helper_enhance (GmTextBufferEnhancerHelperIFace* self,
+			 G_GNUC_UNUSED GtkTextBuffer* buffer,
+			 G_GNUC_UNUSED GtkTextIter* iter,
+			 GSList** tags,
+			 G_GNUC_UNUSED const gchar* full_text,
+			 gint* start,
+			 gint length)
+{
+  GmTextAnchoredTagPrivate* priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE (self);
+
+  if (priv->opening)
+    *tags = g_slist_prepend (*tags, priv->tag);
+  else
+    *tags = g_slist_remove (*tags, priv->tag);
+
+  *start = *start + length;
+}
+
+static void
+enhancer_helper_iface_init (gpointer g_iface,
+			    G_GNUC_UNUSED gpointer iface_data)
+{
+  GmTextBufferEnhancerHelperIFaceClass* iface = NULL;
+
+  iface = (GmTextBufferEnhancerHelperIFaceClass*)g_iface;
+  iface->do_check = &enhancer_helper_check;
+  iface->do_enhance = &enhancer_helper_enhance;
+}
+
+/* GObject boilerplate */
+
+static void
+gm_text_anchored_tag_dispose (GObject* obj)
+{
+  GmTextAnchoredTagPrivate* priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE(obj);
+
+  if (priv->tag != NULL) {
+
+    g_object_unref (priv->tag);
+    priv->tag = NULL;
+  }
+
+  parent_class->dispose (obj);
+}
+
+static void
+gm_text_anchored_tag_finalize (GObject* obj)
+{
+  GmTextAnchoredTagPrivate* priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE(obj);
+
+  if (priv->anchor != NULL) {
+
+    g_free (priv->anchor);
+    priv->anchor = NULL;
+  }
+
+  parent_class->finalize (obj);
+}
+
+static void
+gm_text_anchored_tag_class_init (GmTextAnchoredTagClass* g_class)
+{
+  GObjectClass* gobject_class = NULL;
+
+  parent_class = g_type_class_peek_parent (g_class);
+
+  gobject_class = (GObjectClass*)g_class;
+  gobject_class->dispose = gm_text_anchored_tag_dispose;
+  gobject_class->finalize = gm_text_anchored_tag_finalize;
+
+  g_type_class_add_private (gobject_class, sizeof (GmTextAnchoredTagPrivate));
+}
+
+static void
+gm_text_anchored_tag_init (GmTextAnchoredTag* obj)
+{
+  GmTextAnchoredTagPrivate* priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE(obj);
+
+  priv->anchor = NULL;
+  priv->tag = NULL;
+  priv->opening = TRUE;
+}
+
+GType
+gm_text_anchored_tag_get_type (void)
+{
+  static GType result = 0;
+  if (!result) {
+
+    static const GTypeInfo my_info = {
+      sizeof(GmTextAnchoredTagClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gm_text_anchored_tag_class_init,
+      NULL,
+      NULL,
+      sizeof(GmTextAnchoredTag),
+      0,
+      (GInstanceInitFunc) gm_text_anchored_tag_init,
+      NULL
+    };
+
+    static const GInterfaceInfo enhancer_helper_info = {
+      enhancer_helper_iface_init,
+      NULL,
+      NULL
+    };
+
+    result = g_type_register_static (G_TYPE_OBJECT,
+				     "GmTextAnchoredTag",
+				     &my_info, 0);
+    g_type_add_interface_static (result,
+				 GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE,
+				 &enhancer_helper_info);
+  }
+  return result;
+}
+
+/* Implementation of the public api */
+
+GmTextBufferEnhancerHelperIFace*
+gm_text_anchored_tag_new (const gchar* anchor,
+			  GtkTextTag* tag,
+			  gboolean opening)
+{
+  GmTextAnchoredTag* result = NULL;
+  GmTextAnchoredTagPrivate* priv = NULL;
+
+  g_return_val_if_fail (anchor != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), NULL);
+
+  result = (GmTextAnchoredTag*)g_object_new (GM_TYPE_TEXT_ANCHORED_TAG, NULL);
+
+  priv = GM_TEXT_ANCHORED_TAG_GET_PRIVATE (result);
+
+  priv->anchor = g_strdup (anchor);
+
+  g_object_ref (tag);
+  priv->tag = tag;
+
+  priv->opening = opening;
+
+  return GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE (result);
+}

Added: trunk/lib/gui/gm-text-anchored-tag.h
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-anchored-tag.h	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,93 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-anchored-tag.h  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Declaration of an anchor-based text decorator
+ *
+ */
+
+#ifndef __GM_TEXT_ANCHORED_TAG_H__
+#define __GM_TEXT_ANCHORED_TAG_H__
+
+#include "gm-text-buffer-enhancer-helper-iface.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/* public api */
+
+/* The anchor parameter is the text this decorator should look for,
+ * the tag parameter is the tag which this decorator should apply/unapply,
+ * and the opening parameter tells if it must apply (TRUE) or unapply (FALSE)
+ *
+ * Here is sample code showing how to use it :
+ *  tag = gtk_text_buffer_create_tag (buffer, "bold",
+ *				      "weight", PANGO_WEIGHT_BOLD,
+ *				      NULL);
+ *  helper = gm_text_anchored_tag_new ("<b>", tag, TRUE);
+ *  gm_text_buffer_enhancer_add_helper (enhancer, helper);
+ *  g_object_unref (helper);
+ *  helper = gm_text_anchored_tag_new ("</b>", tag, FALSE);
+ *  gm_text_buffer_enhancer_add_helper (enhancer, helper);
+ *  g_object_unref (helper);
+ *
+ */
+GmTextBufferEnhancerHelperIFace* gm_text_anchored_tag_new (const gchar* anchor,
+							   GtkTextTag* tag,
+							   gboolean opening);
+
+/* GObject boilerplate */
+
+typedef struct _GmTextAnchoredTag      GmTextAnchoredTag;
+typedef struct _GmTextAnchoredTagClass GmTextAnchoredTagClass;
+
+struct _GmTextAnchoredTag {
+  GObject parent;
+};
+
+struct _GmTextAnchoredTagClass {
+  GObjectClass parent_class;
+};
+
+GType gm_text_anchored_tag_get_type () G_GNUC_CONST;
+
+#define GM_TYPE_TEXT_ANCHORED_TAG (gm_text_anchored_tag_get_type())
+#define GM_TEXT_ANCHORED_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GM_TYPE_TEXT_ANCHORED_TAG,GmTextAnchoredTag))
+#define GM_TEXT_ANCHORED_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GM_TYPE_TEXT_ANCHORED_TAG,GObject))
+#define GM_IS_TEXT_ANCHORED_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GM_TYPE_TEXT_ANCHORED_TAG))
+#define GM_IS_TEXT_ANCHORED_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GM_TYPE_TEXT_ANCHORED_TAG))
+#define GM_TEXT_ANCHORED_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GM_TYPE_TEXT_ANCHORED_TAG,GmTextAnchoredTagClass))
+
+G_END_DECLS
+
+#endif /* __GM_TEXT_ANCHORED_TAG_H__ */

Added: trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.c
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.c	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,102 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-buffer-enhancer-helper-iface.c  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Implementation of the interface of a text decorator
+ *                          (for use with GmTextBufferEnhancer)
+ *
+ */
+
+#include "gm-text-buffer-enhancer-helper-iface.h"
+
+/* GObject code */
+
+static void
+gm_text_buffer_enhancer_helper_iface_base_init (G_GNUC_UNUSED gpointer g_class)
+{
+  static gboolean initialized = FALSE;
+  if (!initialized) {
+    /* nothing */
+    initialized = TRUE;
+  }
+}
+GType
+gm_text_buffer_enhancer_helper_iface_get_type (void)
+{
+  static GType result = 0;
+  if (!result) {
+
+    static const GTypeInfo my_info = {
+      sizeof(GmTextBufferEnhancerHelperIFaceClass),
+      gm_text_buffer_enhancer_helper_iface_base_init,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+      0,
+      0,
+      NULL,
+      NULL
+    };
+
+    result = g_type_register_static (G_TYPE_INTERFACE,
+				     "GmTextBufferEnhancerHelperIFace",
+				     &my_info, 0);
+
+    g_type_interface_add_prerequisite (result, G_TYPE_OBJECT);
+  }
+  return result;
+}
+
+/* public api */
+
+void
+gm_text_buffer_enhancer_helper_check (GmTextBufferEnhancerHelperIFace* self,
+				      const gchar* full_text,
+				      gint from,
+				      gint* start,
+				      gint* length)
+{
+  return GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_GET_CLASS (self)->do_check (self, full_text, from, start, length);
+}
+
+void
+gm_text_buffer_enhancer_helper_enhance (GmTextBufferEnhancerHelperIFace* self,
+					GtkTextBuffer* buffer,
+					GtkTextIter* iter,
+					GSList** tags,
+					const gchar* full_text,
+					gint* start,
+					gint length)
+{
+  GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_GET_CLASS (self)->do_enhance (self, buffer, iter, tags, full_text, start, length);
+}

Added: trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.h
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-buffer-enhancer-helper-iface.h	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,129 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-buffer-enhancer-helper-iface.h  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Declaration of the interface of a text decorator
+ *                          (for use with GmTextBufferEnhancer)
+ *
+ */
+
+#ifndef __GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_H__
+#define __GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GmTextBufferEnhancerHelperIFace      GmTextBufferEnhancerHelperIFace;
+typedef struct _GmTextBufferEnhancerHelperIFaceClass GmTextBufferEnhancerHelperIFaceClass;
+
+/* public api */
+
+/* This method is used to have all enhancers tell what they think they can do
+ * to enhance a text ; then the enhancer will choose the most suitable helper
+ * and use the next method.
+ * For this reason, the helper receives :
+ * - the full text (full_text parameter) ;
+ * - where in the full text it should start looking for interesting things (from
+ *   parameter) ;
+ * and it returns two values (the start and length out parameters) :
+ * - where it thinks it can do something (the start parameter) ;
+ * - on which length it will do it (the length parameter).
+ *
+ * The idea is :
+ * - return a zero length if nothing interesting can be done (start will then
+ *   be ignored by the caller) ;
+ * - the length allows the enhancer to prefer the helper which saw "fooz" when
+ *   compared to the one which saw "foo".
+ */
+void gm_text_buffer_enhancer_helper_check (GmTextBufferEnhancerHelperIFace* self,
+					   const gchar* full_text,
+					   gint from,
+					   gint* start,
+					   gint* length);
+
+
+/* This method is called by the enhancer when the helper has been choosen
+ * to act ; it receives :
+ * - the buffer (buffer parameter) in which the enhanced text has to go ;
+ * - the iterator (iter parameter) where to insert the enhanced text ;
+ * - the active tags (tags parameter), which is an in&out parameter, hence
+ *   the enhancer can change them and use them ;
+ * - the full text which the enhancer is trying to insert ;
+ * - where in the text the helper said it would work (the start parameter),
+ *   as in&out parameter so the helper can swallow it ;
+ * - the length (length parameter) of the part the helper said was interested
+ *   in.
+ *
+ * "the helper said" means those values are those the helper answered in its
+ * check method.
+ */
+void gm_text_buffer_enhancer_helper_enhance (GmTextBufferEnhancerHelperIFace* self,
+					     GtkTextBuffer* buffer,
+					     GtkTextIter* iter,
+					     GSList** tags,
+					     const gchar* full_text,
+					     gint* start,
+					     gint length);
+
+/* GObject boilerplate */
+
+struct _GmTextBufferEnhancerHelperIFaceClass {
+  GTypeInterface parent;
+
+  void (*do_check) (GmTextBufferEnhancerHelperIFace* self,
+		    const gchar* full_text,
+		    gint from,
+		    gint* start,
+		    gint* length);
+
+  void (*do_enhance) (GmTextBufferEnhancerHelperIFace* self,
+		      GtkTextBuffer* buffer,
+		      GtkTextIter* iter,
+		      GSList** tags,
+		      const gchar* full_text,
+		      gint* start,
+		      gint length);
+};
+
+#define GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE (gm_text_buffer_enhancer_helper_iface_get_type())
+#define GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE,GmTextBufferEnhancerHelperIFace))
+#define GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable),GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE,GTypeInterface))
+#define GM_IS_TEXT_BUFFER_ENHANCER_HELPER_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE))
+#define GM_IS_TEXT_BUFFER_ENHANCER_HELPER_IFACE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable),GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE))
+#define GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst),GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE,GmTextBufferEnhancerHelperIFaceClass))
+
+GType gm_text_buffer_enhancer_helper_iface_get_type () G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE_H__ */

Added: trunk/lib/gui/gm-text-buffer-enhancer.c
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-buffer-enhancer.c	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,228 @@
+/* gm-text-buffer-enhancer.c */
+
+/* insert (c)/licensing information) */
+
+#include "gm-text-buffer-enhancer.h"
+
+#include <string.h>
+
+static void gm_text_buffer_enhancer_class_init (GmTextBufferEnhancerClass* g_class);
+static void gm_text_buffer_enhancer_init (GmTextBufferEnhancer* obj);
+static void gm_text_buffer_enhancer_dispose (GObject* obj);
+static void gm_text_buffer_enhancer_finalize (GObject* obj);
+
+typedef struct _GmTextBufferEnhancerPrivate GmTextBufferEnhancerPrivate;
+struct _GmTextBufferEnhancerPrivate {
+  GtkTextBuffer* buffer;
+  GSList* helpers;
+};
+
+#define GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+										 GM_TYPE_TEXT_BUFFER_ENHANCER, \
+										 GmTextBufferEnhancerPrivate))
+
+static GObjectClass* parent_class = NULL;
+
+GType
+gm_text_buffer_enhancer_get_type (void)
+{
+  static GType result = 0;
+  if (!result) {
+    static const GTypeInfo my_info = {
+      sizeof(GmTextBufferEnhancerClass),
+      NULL,		/* base init */
+      NULL,		/* base finalize */
+      (GClassInitFunc) gm_text_buffer_enhancer_class_init,
+      NULL,		/* class finalize */
+      NULL,		/* class data */
+      sizeof(GmTextBufferEnhancer),
+      1,		/* n_preallocs */
+      (GInstanceInitFunc) gm_text_buffer_enhancer_init,
+      NULL
+    };
+    result = g_type_register_static (G_TYPE_OBJECT,
+				     "GmTextBufferEnhancer",
+				     &my_info, 0);
+  }
+  return result;
+}
+
+static void
+gm_text_buffer_enhancer_class_init (GmTextBufferEnhancerClass* g_class)
+{
+  GObjectClass* gobject_class = NULL;
+
+  parent_class = g_type_class_peek_parent (g_class);
+
+  gobject_class = (GObjectClass*)g_class;
+  gobject_class->dispose = gm_text_buffer_enhancer_dispose;
+  gobject_class->finalize = gm_text_buffer_enhancer_finalize;
+
+  g_type_class_add_private (gobject_class,
+			    sizeof(GmTextBufferEnhancerPrivate));
+}
+
+static void
+gm_text_buffer_enhancer_init (GmTextBufferEnhancer* obj)
+{
+  GmTextBufferEnhancerPrivate* priv = GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE(obj);
+
+  priv->buffer = NULL;
+  priv->helpers = NULL;
+}
+
+static void
+gm_text_buffer_enhancer_dispose (GObject* obj)
+{
+  GmTextBufferEnhancerPrivate* priv = GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE(obj);
+
+  if (priv->buffer != NULL) {
+
+    g_object_unref (priv->buffer);
+    priv->buffer = NULL;
+  }
+
+  if (priv->helpers != NULL) {
+
+    g_slist_foreach (priv->helpers, (GFunc)g_object_unref, NULL);
+    g_slist_free (priv->helpers);
+    priv->helpers = NULL;
+  }
+
+  G_OBJECT_CLASS(parent_class)->dispose (obj);
+}
+
+static void
+gm_text_buffer_enhancer_finalize (GObject* obj)
+{
+  G_OBJECT_CLASS(parent_class)->finalize (obj);
+}
+
+GmTextBufferEnhancer*
+gm_text_buffer_enhancer_new (GtkTextBuffer* buffer)
+{
+  GmTextBufferEnhancer* result = NULL;
+  GmTextBufferEnhancerPrivate* priv = NULL;
+
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+  result
+    = (GmTextBufferEnhancer*)g_object_new(GM_TYPE_TEXT_BUFFER_ENHANCER, NULL);
+
+  priv =  GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE (result);
+  g_object_ref (buffer);
+  priv->buffer = buffer;
+
+  return result;
+}
+
+void
+gm_text_buffer_enhancer_add_helper (GmTextBufferEnhancer* self,
+				    GmTextBufferEnhancerHelperIFace* helper)
+{
+  GmTextBufferEnhancerPrivate* priv = NULL;
+
+  g_return_if_fail (GM_IS_TEXT_BUFFER_ENHANCER (self));
+  g_return_if_fail (GM_IS_TEXT_BUFFER_ENHANCER_HELPER_IFACE (helper));
+
+  priv = GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE(self);
+  g_object_ref (helper);
+  priv->helpers = g_slist_prepend (priv->helpers, helper);
+}
+
+void
+gm_text_buffer_enhancer_insert_text (GmTextBufferEnhancer* self,
+				     GtkTextIter* iter,
+				     const gchar* text,
+				     gint len)
+{
+  GmTextBufferEnhancerPrivate* priv = NULL;
+  gint position = 0;
+  gint length = 0;
+  GSList* active_tags = NULL;
+  GmTextBufferEnhancerHelperIFace* best_helper = NULL;
+  gint best_start = 0;
+  gint best_length = 0;
+  GSList* helper_ptr = NULL;
+  GmTextBufferEnhancerHelperIFace* considered_helper = NULL;
+  gint considered_start = 0;
+  gint considered_length = 0;
+  GSList* tag_ptr = NULL;
+  GtkTextMark* mark = NULL;
+  GtkTextIter tag_start_iter;
+
+  g_return_if_fail (GM_IS_TEXT_BUFFER_ENHANCER (self));
+  g_return_if_fail (iter != NULL); // can't do better
+  g_return_if_fail (text != NULL);
+
+  priv = GM_TEXT_BUFFER_ENHANCER_GET_PRIVATE (self);
+
+  if (len < 0)
+    length = strlen (text);
+  else
+    length = len;
+
+  mark = gtk_text_buffer_create_mark (priv->buffer, NULL, iter, TRUE);
+
+  while (position < length) {
+
+    /* try to find the best helper,
+     * starting for the worse case that none is good */
+    best_helper = NULL;
+    best_start = length;
+    best_length = 0;
+    for (helper_ptr = priv->helpers ;
+	 helper_ptr != NULL ;
+	 helper_ptr = g_slist_next (helper_ptr)) {
+
+      considered_helper
+	= GM_TEXT_BUFFER_ENHANCER_HELPER_IFACE (helper_ptr->data);
+      gm_text_buffer_enhancer_helper_check (considered_helper,
+					    text, position,
+					    &considered_start,
+					    &considered_length);
+      if (((considered_start < best_start)
+	   && (considered_length > 0))
+	  || ((considered_start == best_start)
+	      && (considered_length > best_length))) {
+
+	best_helper = considered_helper;
+	best_start = considered_start;
+	best_length = considered_length;
+      }
+    }
+
+    /* whatever we found can be further down : just apply the tags to
+     * the part of the text before */
+    if (position < best_start) {
+
+      gtk_text_buffer_move_mark (priv->buffer, mark, iter);
+      gtk_text_buffer_insert (priv->buffer, iter,
+			      text + position, best_start - position);
+      gtk_text_buffer_get_iter_at_mark (priv->buffer, &tag_start_iter, mark);
+      for (tag_ptr = active_tags;
+	   tag_ptr != NULL;
+	   tag_ptr = g_slist_next (tag_ptr)) {
+
+	gtk_text_buffer_apply_tag (priv->buffer, GTK_TEXT_TAG (tag_ptr->data),
+				   &tag_start_iter, iter);
+      }
+      position = best_start;
+    }
+
+    /* ok, now we're either at the end without a best helper or still in the
+     * middle with a best helper : apply that one if it's there!
+     */
+    if (best_helper != NULL)
+      gm_text_buffer_enhancer_helper_enhance (best_helper,
+					      priv->buffer,
+					      iter,
+					      &active_tags,
+					      text,
+					      &position,
+					      best_length);
+  }
+
+  gtk_text_buffer_delete_mark (priv->buffer, mark);
+  g_slist_free (active_tags);
+}

Added: trunk/lib/gui/gm-text-buffer-enhancer.h
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-buffer-enhancer.h	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,46 @@
+/* gm-text-buffer-enhancer.h */
+/* insert (c)/licensing information) */
+
+#ifndef __GM_TEXT_BUFFER_ENHANCER_H__
+#define __GM_TEXT_BUFFER_ENHANCER_H__
+
+#include <gtk/gtk.h>
+#include "gm-text-buffer-enhancer-helper-iface.h"
+
+G_BEGIN_DECLS
+
+/* convenience macros */
+#define GM_TYPE_TEXT_BUFFER_ENHANCER             (gm_text_buffer_enhancer_get_type())
+#define GM_TEXT_BUFFER_ENHANCER(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GM_TYPE_TEXT_BUFFER_ENHANCER,GmTextBufferEnhancer))
+#define GM_TEXT_BUFFER_ENHANCER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),GM_TYPE_TEXT_BUFFER_ENHANCER,GObject))
+#define GM_IS_TEXT_BUFFER_ENHANCER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GM_TYPE_TEXT_BUFFER_ENHANCER))
+#define GM_IS_TEXT_BUFFER_ENHANCER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GM_TYPE_TEXT_BUFFER_ENHANCER))
+#define GM_TEXT_BUFFER_ENHANCER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj),GM_TYPE_TEXT_BUFFER_ENHANCER,GmTextBufferEnhancerClass))
+
+typedef struct _GmTextBufferEnhancer      GmTextBufferEnhancer;
+typedef struct _GmTextBufferEnhancerClass GmTextBufferEnhancerClass;
+
+struct _GmTextBufferEnhancer {
+  GObject parent;
+};
+
+struct _GmTextBufferEnhancerClass {
+  GObjectClass parent_class;
+};
+
+/* member functions */
+GType gm_text_buffer_enhancer_get_type () G_GNUC_CONST;
+
+GmTextBufferEnhancer* gm_text_buffer_enhancer_new (GtkTextBuffer* buffer);
+
+void gm_text_buffer_enhancer_add_helper (GmTextBufferEnhancer* self,
+					 GmTextBufferEnhancerHelperIFace* helper);
+
+void gm_text_buffer_enhancer_insert_text (GmTextBufferEnhancer* self,
+					  GtkTextIter* iter,
+					  const gchar* text,
+					  gint len);
+
+G_END_DECLS
+
+#endif /* __GM_TEXT_BUFFER_ENHANCER_H__ */

Added: trunk/lib/gui/gm-text-smiley.c
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-smiley.c	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,224 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-smiley.c  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Implementation of a text decorator for smileys
+ *
+ */
+
+#include "gm-text-smiley.h"
+
+#include <string.h>
+
+/* here are the smileys */
+static const char* smileys[] = {
+  /* smiley, pixbux */
+  "0:-)", "face-angel",
+  "B-)", "face-cool",
+  ":'-(", "face-crying",
+  ":-[", "face-embarassed",
+  ">:-)", "face-devilish",
+  ":-*", "face-kiss",
+  ":-(|)", "face-monkey",
+  ":-|", "face-plain",
+  ":-P", "face-raspberry",
+  ":-(", "face-sad",
+  ":-)", "face-smile",
+  ":-D", "face-smile-big",
+  ":-!", "face-smirk",
+  ":-O", "face-surprise",
+  ";-)", "face-wink",
+  NULL
+};
+
+static GObjectClass* parent_class = NULL;
+
+/* declaration of the GmTextBufferEnhancerHelperIFace code */
+
+static void enhancer_helper_check (GmTextBufferEnhancerHelperIFace* self,
+				   const gchar* full_text,
+				   gint from,
+				   gint* start,
+				   gint* length);
+
+static void enhancer_helper_enhance (GmTextBufferEnhancerHelperIFace* self,
+				     GtkTextBuffer* buffer,
+				     GtkTextIter* iter,
+				     GSList** tags,
+				     const gchar* full_text,
+				     gint* start,
+				     gint length);
+
+static void enhancer_helper_iface_init (gpointer g_iface,
+					gpointer iface_data);
+
+/* implementation of the GmTextBufferEnhancerHelperIFace code */
+
+static void
+enhancer_helper_check (G_GNUC_UNUSED GmTextBufferEnhancerHelperIFace* self,
+		       const gchar* full_text,
+		       gint from,
+		       gint* start,
+		       gint* length)
+{
+  gint smiley = 0;
+  gint best_start = 0;
+  gint best_smiley = -1;
+  char* found = NULL;
+  gint found_start = 0;
+
+  for (smiley = 0;
+       smileys[smiley] != NULL;
+       smiley = smiley + 2) {
+
+    found = strstr (full_text + from, smileys[smiley]);
+    if (found != NULL) {
+
+      found_start = found - full_text;
+      if ((best_smiley == -1)
+	  || ((found_start <= best_start)
+	      && (strlen (smileys[smiley]) > strlen (smileys[best_smiley])))) {
+
+	best_smiley = smiley;
+	best_start = found_start;
+      }
+    }
+  }
+
+
+  if (best_smiley != -1) {
+
+    *start = best_start;
+    *length = strlen (smileys[best_smiley]);
+  } else
+    *length = 0;
+}
+
+static void
+enhancer_helper_enhance (G_GNUC_UNUSED GmTextBufferEnhancerHelperIFace* self,
+			 GtkTextBuffer* buffer,
+			 GtkTextIter* iter,
+			 G_GNUC_UNUSED GSList** tags,
+			 G_GNUC_UNUSED const gchar* full_text,
+			 gint* start,
+			 gint length)
+{
+  gchar* smiley = NULL;
+  gint ii = 0;
+  const gchar* pixbuf_name = NULL;
+  GdkPixbuf* pixbuf = NULL;
+
+  smiley = g_malloc0 (length + 1);
+
+  strncpy (smiley, full_text + *start, length);
+
+  for (ii = 0;
+       smileys[ii] != NULL;
+       ii = ii + 2) {
+
+    if (strcmp (smiley, smileys[ii]) == 0)
+      pixbuf_name = smileys[ii + 1];
+  }
+
+  if (pixbuf_name != NULL) {
+
+    pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+				       pixbuf_name, 16, 0, NULL);
+    gtk_text_buffer_insert_pixbuf (buffer, iter, pixbuf);
+    g_object_unref (pixbuf);
+    *start = *start + length;
+  }
+
+  g_free (smiley);
+}
+
+static void
+enhancer_helper_iface_init (gpointer g_iface,
+			    G_GNUC_UNUSED gpointer iface_data)
+{
+  GmTextBufferEnhancerHelperIFaceClass* iface = NULL;
+
+  iface = (GmTextBufferEnhancerHelperIFaceClass*)g_iface;
+  iface->do_check = &enhancer_helper_check;
+  iface->do_enhance = &enhancer_helper_enhance;
+}
+
+/* GObject boilerplate */
+
+static void
+gm_text_smiley_class_init (GmTextSmileyClass* g_class)
+{
+  parent_class = g_type_class_peek_parent (g_class);
+}
+
+GType
+gm_text_smiley_get_type ()
+{
+  static GType result = 0;
+  if (!result) {
+
+    static const GTypeInfo my_info = {
+      sizeof(GmTextSmileyClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gm_text_smiley_class_init,
+      NULL,
+      NULL,
+      sizeof(GmTextSmiley),
+      0,
+      NULL,
+      NULL
+    };
+
+    static const GInterfaceInfo enhancer_helper_info = {
+      enhancer_helper_iface_init,
+      NULL,
+      NULL
+    };
+
+    result = g_type_register_static (G_TYPE_OBJECT,
+				     "GmTextSmiley",
+				     &my_info, 0);
+    g_type_add_interface_static (result,
+				 GM_TYPE_TEXT_BUFFER_ENHANCER_HELPER_IFACE,
+				 &enhancer_helper_info);
+  }
+  return result;
+}
+
+/* public api */
+
+GmTextBufferEnhancerHelperIFace*
+gm_text_smiley_new (void)
+{
+  return (GmTextBufferEnhancerHelperIFace*)g_object_new(GM_TYPE_TEXT_SMILEY, NULL);
+}

Added: trunk/lib/gui/gm-text-smiley.h
==============================================================================
--- (empty file)
+++ trunk/lib/gui/gm-text-smiley.h	Tue Jul 15 13:58:11 2008
@@ -0,0 +1,73 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                        gm-text-smiley.h  -  description
+ *                         --------------------------------
+ *   begin                : written in july 2008 by Julien Puydt
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Declaration of a text decorator for smileys
+ *
+ */
+
+#ifndef __GM_TEXT_SMILEY_H__
+#define __GM_TEXT_SMILEY_H__
+
+#include "gm-text-buffer-enhancer-helper-iface.h"
+
+G_BEGIN_DECLS
+
+/* public api */
+
+GmTextBufferEnhancerHelperIFace* gm_text_smiley_new ();
+
+/* GObject boilerplate */
+
+typedef struct _GmTextSmiley      GmTextSmiley;
+typedef struct _GmTextSmileyClass GmTextSmileyClass;
+
+struct _GmTextSmiley {
+  GObject parent;
+};
+
+struct _GmTextSmileyClass {
+  GObjectClass parent_class;
+};
+
+#define GM_TYPE_TEXT_SMILEY (gm_text_smiley_get_type())
+#define GM_TEXT_SMILEY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GM_TYPE_TEXT_SMILEY,GmTextSmiley))
+#define GM_TEXT_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GM_TYPE_TEXT_SMILEY,GObject))
+#define GM_IS_TEXT_SMILEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GM_TYPE_TEXT_SMILEY))
+#define GM_IS_TEXT_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GM_TYPE_TEXT_SMILEY))
+#define GM_TEXT_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GM_TYPE_TEXT_SMILEY,GmTextSmileyClass))
+
+GType gm_text_smiley_get_type () G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GM_TEXT_SMILEY_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]