[empathy] Replace GString param with a generic gpointer user_data, and port EmpathyChatTextView to new parser



commit 9c1e21c7ad3ba913ebf144b498aa2de6d22a7797
Author: Xavier Claessens <xclaesse gmail com>
Date:   Tue Nov 24 15:54:21 2009 +0100

    Replace GString param with a generic gpointer user_data, and port EmpathyChatTextView to new parser API.

 libempathy-gtk/empathy-chat-text-view.c |  147 ++++++++++++++-----------------
 libempathy-gtk/empathy-theme-adium.c    |   78 ++++++++++------
 libempathy-gtk/empathy-ui-utils.c       |   63 ++++++-------
 libempathy-gtk/empathy-ui-utils.h       |   39 ++++----
 tests/empathy-parser-test.c             |   26 +++++-
 5 files changed, 184 insertions(+), 169 deletions(-)
---
diff --git a/libempathy-gtk/empathy-chat-text-view.c b/libempathy-gtk/empathy-chat-text-view.c
index 6dd8b30..a46f6a4 100644
--- a/libempathy-gtk/empathy-chat-text-view.c
+++ b/libempathy-gtk/empathy-chat-text-view.c
@@ -1256,44 +1256,60 @@ empathy_chat_text_view_set_only_if_date (EmpathyChatTextView *view,
 }
 
 static void
-chat_text_view_insert_text_with_emoticons (EmpathyChatTextView *view,
-					   GtkTextIter         *iter,
-					   const gchar         *str)
+chat_text_view_replace_link (const gchar *text,
+			     gssize len,
+			     gpointer match_data,
+			     gpointer user_data)
 {
-	EmpathyChatTextViewPriv *priv = GET_PRIV (view);
-	gboolean                 use_smileys = FALSE;
-	GSList                  *hits, *l;
-	guint                    last = 0;
+	GtkTextBuffer *buffer = GTK_TEXT_BUFFER (user_data);
+	GtkTextIter iter;
 
-	empathy_conf_get_bool (empathy_conf_get (),
-			       EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
-			       &use_smileys);
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
+						  text, len,
+						  EMPATHY_CHAT_TEXT_VIEW_TAG_LINK,
+						  NULL);
+}
 
-	if (!use_smileys) {
-		gtk_text_buffer_insert (priv->buffer, iter, str, -1);
-		return;
-	}
+static void
+chat_text_view_replace_smiley (const gchar *text,
+			       gssize len,
+			       gpointer match_data,
+			       gpointer user_data)
+{
+	EmpathySmileyHit *hit = match_data;
+	GtkTextBuffer *buffer = GTK_TEXT_BUFFER (user_data);
+	GtkTextIter iter;
 
-	hits = empathy_smiley_manager_parse_len (priv->smiley_manager, str, -1);
-	for (l = hits; l; l = l->next) {
-		EmpathySmileyHit *hit = l->data;
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert_pixbuf (buffer, &iter, hit->pixbuf);
+}
 
-		if (hit->start > last) {
-			/* Append the text between last smiley (or the
-			 * start of the message) and this smiley */
-			gtk_text_buffer_insert (priv->buffer, iter, str + last,
-						hit->start - last);
-		}
-		gtk_text_buffer_insert_pixbuf (priv->buffer, iter, hit->pixbuf);
+static void
+chat_text_view_replace_verbatim (const gchar *text,
+				 gssize len,
+				 gpointer match_data,
+				 gpointer user_data)
+{
+	GtkTextBuffer *buffer = GTK_TEXT_BUFFER (user_data);
+	GtkTextIter iter;
 
-		last = hit->end;
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert (buffer, &iter, text, len);
+}
 
-		empathy_smiley_hit_free (hit);
-	}
-	g_slist_free (hits);
+static EmpathyStringParser string_parsers[] = {
+	{empathy_string_match_link, chat_text_view_replace_link},
+	{empathy_string_match_all, chat_text_view_replace_verbatim},
+	{NULL, NULL}
+};
 
-	gtk_text_buffer_insert (priv->buffer, iter, str + last, -1);
-}
+static EmpathyStringParser string_parsers_with_smiley[] = {
+	{empathy_string_match_link, chat_text_view_replace_link},
+	{empathy_string_match_smiley, chat_text_view_replace_smiley},
+	{empathy_string_match_all, chat_text_view_replace_verbatim},
+	{NULL, NULL}
+};
 
 void
 empathy_chat_text_view_append_body (EmpathyChatTextView *view,
@@ -1301,71 +1317,38 @@ empathy_chat_text_view_append_body (EmpathyChatTextView *view,
 				    const gchar         *tag)
 {
 	EmpathyChatTextViewPriv *priv = GET_PRIV (view);
-	GtkTextIter              start_iter, end_iter;
-	GtkTextMark             *mark;
+	EmpathyStringParser     *parsers;
+	gboolean                 use_smileys;
+	GtkTextIter              start_iter;
 	GtkTextIter              iter;
-	GRegex                  *uri_regex;
-	GMatchInfo              *match_info;
-	gboolean                 match;
-	gint                     last = 0;
-	gint                     s = 0, e = 0;
-	gchar                   *tmp;
+	GtkTextMark             *mark;
 
-	priv = GET_PRIV (view);
+	/* Check if we have to parse smileys */
+	empathy_conf_get_bool (empathy_conf_get (),
+			       EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
+			       &use_smileys);
+	if (use_smileys)
+		parsers = string_parsers_with_smiley;
+	else
+		parsers = string_parsers;
 
+	/* Create a mark at the place we'll start inserting */
 	gtk_text_buffer_get_end_iter (priv->buffer, &start_iter);
 	mark = gtk_text_buffer_create_mark (priv->buffer, NULL, &start_iter, TRUE);
 
-	uri_regex = empathy_uri_regex_dup_singleton ();
-	for (match = g_regex_match (uri_regex, body, 0, &match_info); match;
-	     match = g_match_info_next (match_info, NULL)) {
-		if (!g_match_info_fetch_pos (match_info, 0, &s, &e))
-			continue;
-
-		if (s > last) {
-			tmp = empathy_substring (body, last, s);
-
-			gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-			chat_text_view_insert_text_with_emoticons (view,
-								   &iter,
-								   tmp);
-			g_free (tmp);
-		}
-
-		tmp = empathy_substring (body, s, e);
-
-		gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-		gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-							  &iter,
-							  tmp,
-							  -1,
-							  EMPATHY_CHAT_TEXT_VIEW_TAG_LINK,
-							  NULL);
-
-		g_free (tmp);
-		last = e;
-	}
-	g_match_info_free (match_info);
-	g_regex_unref (uri_regex);
-
-	if (last < (gint) strlen (body)) {
-		gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-		chat_text_view_insert_text_with_emoticons (view,
-							   &iter,
-							   body + last);
-	}
+	/* Parse text for links/smileys and insert in the buffer */
+	empathy_string_parser_substr (body, -1, parsers, priv->buffer);
 
+	/* Insert a newline after the text inserted */
 	gtk_text_buffer_get_end_iter (priv->buffer, &iter);
 	gtk_text_buffer_insert (priv->buffer, &iter, "\n", 1);
 
 	/* Apply the style to the inserted text. */
 	gtk_text_buffer_get_iter_at_mark (priv->buffer, &start_iter, mark);
-	gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
-
-	gtk_text_buffer_apply_tag_by_name (priv->buffer,
-					   tag,
+	gtk_text_buffer_get_end_iter (priv->buffer, &iter);
+	gtk_text_buffer_apply_tag_by_name (priv->buffer, tag,
 					   &start_iter,
-					   &end_iter);
+					   &iter);
 
 	gtk_text_buffer_delete_mark (priv->buffer, mark);
 }
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index e0aff10..a702ded 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -192,12 +192,13 @@ theme_adium_open_address_cb (GtkMenuItem *menuitem,
 }
 
 static void
-theme_adium_match_newline (GString *string,
-			   const gchar *text,
+theme_adium_match_newline (const gchar *text,
 			   gssize len,
 			   EmpathyStringReplace replace_func,
-			   EmpathyStringParser *sub_parsers)
+			   EmpathyStringParser *sub_parsers,
+			   gpointer user_data)
 {
+	GString *string = user_data;
 	gint i;
 	gint prev = 0;
 
@@ -208,21 +209,24 @@ theme_adium_match_newline (GString *string,
 	/* Replace \n by <br/> */
 	for (i = 0; i < len && text[i] != '\0'; i++) {
 		if (text[i] == '\n') {
-			empathy_string_parser_substr (string, text + prev,
-						      i - prev, sub_parsers);
+			empathy_string_parser_substr (text + prev,
+						      i - prev, sub_parsers,
+						      user_data);
 			g_string_append (string, "<br/>");
 			prev = i + 1;
 		}
 	}
-	empathy_string_parser_substr (string, text + prev, i - prev, sub_parsers);
+	empathy_string_parser_substr (text + prev, i - prev,
+				      sub_parsers, user_data);
 }
 
 static void
-theme_adium_replace_link (GString *string,
-			  const gchar *text,
+theme_adium_replace_link (const gchar *text,
 			  gssize len,
+			  gpointer match_data,
 			  gpointer user_data)
 {
+	GString *string = user_data;
 	gchar *real_url;
 
 	/* Append the link inside <a href=""></a> tag */
@@ -238,12 +242,13 @@ theme_adium_replace_link (GString *string,
 static gboolean use_smileys = FALSE;
 
 static void
-theme_adium_replace_smiley (GString *string,
-			    const gchar *text,
+theme_adium_replace_smiley (const gchar *text,
 			    gssize len,
+			    gpointer match_data,
 			    gpointer user_data)
 {
-	EmpathySmileyHit *hit = user_data;
+	EmpathySmileyHit *hit = match_data;
+	GString *string = user_data;
 
 	if (use_smileys) {
 		/* Replace smileys by a <img/> tag */
@@ -258,40 +263,55 @@ theme_adium_replace_smiley (GString *string,
 	}
 }
 
+static void
+theme_adium_replace_escaped (const gchar *text,
+			     gssize len,
+			     gpointer match_data,
+			     gpointer user_data)
+{
+	GString *string = user_data;
+	gchar *escaped;
+
+	escaped = g_markup_escape_text (text, len);
+	g_string_append (string, escaped);
+	g_free (escaped);
+}
+
 static EmpathyStringParser string_parsers[] = {
 	{empathy_string_match_link, theme_adium_replace_link},
+	{theme_adium_match_newline, NULL},
+	{empathy_string_match_all, theme_adium_replace_escaped},
+	{NULL, NULL}
+};
+
+static EmpathyStringParser string_parsers_with_smiley[] = {
+	{empathy_string_match_link, theme_adium_replace_link},
 	{empathy_string_match_smiley, theme_adium_replace_smiley},
 	{theme_adium_match_newline, NULL},
-	{empathy_string_match_escape, NULL},
+	{empathy_string_match_all, theme_adium_replace_escaped},
 	{NULL, NULL}
 };
 
 static gchar *
 theme_adium_parse_body (const gchar *text)
 {
+	EmpathyStringParser *parsers;
 	GString *string;
 
-	/* Get use_smileys value now to avoid getting it for each match */
+	/* Check if we have to parse smileys */
 	empathy_conf_get_bool (empathy_conf_get (),
 			       EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
 			       &use_smileys);
-
-	/* We parse text in 4 steps: url, smiley, newline, escape.
-	 * For each step, we detect the position of tokens in the text, and
-	 * we give text between each token to the next level parser.
-	 *
-	 * For example the string "Hello :)\n www.test.com"
-	 * 1) The url parser detects "www.test.com" and gives "Hello :)\n " to
-	 *    the smiley parser, then insert the <a> tag for the link.
-	 * 2) The smiley parser will detect ":)". It first gives "Hello "
-	 *    to the newline parser, then insert the <img/> tag for the smiley,
-	 *    and finally give "\n " to the newline parser.
-	 * 3a) The newline parser gets "Hello " and escape it.
-	 * 3b) The newline parser gets "\n " and replace to "<br/> ".
-	 */
-
+	if (use_smileys)
+		parsers = string_parsers_with_smiley;
+	else
+		parsers = string_parsers;
+
+	/* Parse text and construct string with links and smileys replaced
+	 * by html tags. Also escape text to make sure html code is
+	 * displayed verbatim. */
 	string = g_string_sized_new (strlen (text));
-	empathy_string_parser_substr (string, text, -1, string_parsers);
+	empathy_string_parser_substr (text, -1, parsers, string);
 
 	return g_string_free (string, FALSE);
 }
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 137dd3b..a72a06b 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -1572,25 +1572,24 @@ empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
 }
 
 void
-empathy_string_parser_substr (GString *string,
-			      const gchar *text,
+empathy_string_parser_substr (const gchar *text,
 			      gssize len,
-			      EmpathyStringParser *parsers)
+			      EmpathyStringParser *parsers,
+			      gpointer user_data)
 {
 	if (parsers != NULL && parsers[0].match_func != NULL) {
-		parsers[0].match_func (string, text, len,
-			parsers[0].replace_func, parsers + 1);
-	} else {
-		g_string_append_len (string, text, len);
+		parsers[0].match_func (text, len,
+				       parsers[0].replace_func, parsers + 1,
+				       user_data);
 	}
 }
 
 void
-empathy_string_match_link (GString *string,
-			   const gchar *text,
+empathy_string_match_link (const gchar *text,
 			   gssize len,
 			   EmpathyStringReplace replace_func,
-			   EmpathyStringParser *sub_parsers)
+			   EmpathyStringParser *sub_parsers,
+			   gpointer user_data)
 {
 	GRegex     *uri_regex;
 	GMatchInfo *match_info;
@@ -1608,29 +1607,31 @@ empathy_string_match_link (GString *string,
 			if (s > last) {
 				/* Append the text between last link (or the
 				 * start of the message) and this link */
-				empathy_string_parser_substr (string, text + last,
+				empathy_string_parser_substr (text + last,
 							      s - last,
-							      sub_parsers);
+							      sub_parsers,
+							      user_data);
 			}
 
-			replace_func (string, text + s, e - s, NULL);
+			replace_func (text + s, e - s, NULL, user_data);
 
 			last = e;
 		} while (g_match_info_next (match_info, NULL));
 	}
 
-	empathy_string_parser_substr (string, text + last, len - last, sub_parsers);
+	empathy_string_parser_substr (text + last, len - last,
+				      sub_parsers, user_data);
 
 	g_match_info_free (match_info);
 	g_regex_unref (uri_regex);
 }
 
 void
-empathy_string_match_smiley (GString *string,
-			     const gchar *text,
+empathy_string_match_smiley (const gchar *text,
 			     gssize len,
 			     EmpathyStringReplace replace_func,
-			     EmpathyStringParser *sub_parsers)
+			     EmpathyStringParser *sub_parsers,
+			     gpointer user_data)
 {
 	guint last = 0;
 	EmpathySmileyManager *smiley_manager;
@@ -1645,14 +1646,13 @@ empathy_string_match_smiley (GString *string,
 		if (hit->start > last) {
 			/* Append the text between last smiley (or the
 			 * start of the message) and this smiley */
-			empathy_string_parser_substr (string, text + last,
+			empathy_string_parser_substr (text + last,
 						      hit->start - last,
-						      sub_parsers);
+						      sub_parsers, user_data);
 		}
 
-		replace_func (string,
-			      text + hit->start, hit->end - hit->start,
-			      hit);
+		replace_func (text + hit->start, hit->end - hit->start,
+			      hit, user_data);
 
 		last = hit->end;
 
@@ -1661,20 +1661,17 @@ empathy_string_match_smiley (GString *string,
 	g_slist_free (hits);
 	g_object_unref (smiley_manager);
 
-	empathy_string_parser_substr (string, text + last, len - last, sub_parsers);
+	empathy_string_parser_substr (text + last, len - last,
+				      sub_parsers, user_data);
 }
 
 void
-empathy_string_match_escape (GString *string,
-			     const gchar *text,
-			     gssize len,
-			     EmpathyStringReplace replace_func,
-			     EmpathyStringParser *sub_parsers)
+empathy_string_match_all (const gchar *text,
+			  gssize len,
+			  EmpathyStringReplace replace_func,
+			  EmpathyStringParser *sub_parsers,
+			  gpointer user_data)
 {
-	gchar *escaped;
-
-	escaped = g_markup_escape_text (text, len);
-	g_string_append (string, escaped);
-	g_free (escaped);
+	replace_func (text, len, NULL, user_data);
 }
 
diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h
index f125b06..65fc9ac 100644
--- a/libempathy-gtk/empathy-ui-utils.h
+++ b/libempathy-gtk/empathy-ui-utils.h
@@ -118,18 +118,17 @@ gchar *     empathy_make_absolute_url_len               (const gchar *url,
 							 guint len);
 
 /* String parser */
-
 typedef struct _EmpathyStringParser EmpathyStringParser;
 
-typedef void (*EmpathyStringReplace) (GString *string,
-				      const gchar *text,
+typedef void (*EmpathyStringReplace) (const gchar *text,
 				      gssize len,
+				      gpointer match_data,
 				      gpointer user_data);
-typedef void (*EmpathyStringMatch) (GString *string,
-				    const gchar *text,
+typedef void (*EmpathyStringMatch) (const gchar *text,
 				    gssize len,
 				    EmpathyStringReplace replace_func,
-				    EmpathyStringParser *sub_parsers);
+				    EmpathyStringParser *sub_parsers,
+				    gpointer user_data);
 
 struct _EmpathyStringParser {
 	EmpathyStringMatch match_func;
@@ -137,31 +136,31 @@ struct _EmpathyStringParser {
 };
 
 void
-empathy_string_parser_substr (GString *string,
-			      const gchar *text,
+empathy_string_parser_substr (const gchar *text,
 			      gssize len,
-			      EmpathyStringParser *parsers);
+			      EmpathyStringParser *parsers,
+			      gpointer user_data);
 
 void
-empathy_string_match_link (GString *string,
-			   const gchar *text,
+empathy_string_match_link (const gchar *text,
 			   gssize len,
 			   EmpathyStringReplace replace_func,
-			   EmpathyStringParser *sub_parsers);
+			   EmpathyStringParser *sub_parsers,
+			   gpointer user_data);
 
 void
-empathy_string_match_smiley (GString *string,
-			     const gchar *text,
+empathy_string_match_smiley (const gchar *text,
 			     gssize len,
 			     EmpathyStringReplace replace_func,
-			     EmpathyStringParser *sub_parsers);
+			     EmpathyStringParser *sub_parsers,
+			     gpointer user_data);
 
 void
-empathy_string_match_escape (GString *string,
-			     const gchar *text,
-			     gssize len,
-			     EmpathyStringReplace replace_func,
-			     EmpathyStringParser *sub_parsers);
+empathy_string_match_all (const gchar *text,
+			  gssize len,
+			  EmpathyStringReplace replace_func,
+			  EmpathyStringParser *sub_parsers,
+			  gpointer user_data);
 
 G_END_DECLS
 
diff --git a/tests/empathy-parser-test.c b/tests/empathy-parser-test.c
index dce91c7..30a28c5 100644
--- a/tests/empathy-parser-test.c
+++ b/tests/empathy-parser-test.c
@@ -10,28 +10,43 @@
 #include <libempathy-gtk/empathy-ui-utils.h>
 
 static void
-test_replace_link (GString *string,
-                   const gchar *text,
+test_replace_link (const gchar *text,
                    gssize len,
+                   gpointer match_data,
                    gpointer user_data)
 {
+  GString *string = user_data;
+
   g_string_append_c (string, '[');
   g_string_append_len (string, text, len);
   g_string_append_c (string, ']');
 }
 
 static void
-test_replace_smiley (GString *string,
-                     const gchar *text,
+test_replace_smiley (const gchar *text,
                      gssize len,
+                     gpointer match_data,
                      gpointer user_data)
 {
+  GString *string = user_data;
+
   g_string_append_c (string, '<');
   g_string_append_len (string, text, len);
   g_string_append_c (string, '>');
 }
 
 static void
+test_replace_verbatim (const gchar *text,
+                       gssize len,
+                       gpointer match_data,
+                       gpointer user_data)
+{
+  GString *string = user_data;
+
+  g_string_append_len (string, text, len);
+}
+
+static void
 test_parsers (void)
 {
   guint i;
@@ -45,6 +60,7 @@ test_parsers (void)
     {
       {empathy_string_match_link, test_replace_link},
       {empathy_string_match_smiley, test_replace_smiley},
+      {empathy_string_match_all, test_replace_verbatim},
       {NULL, NULL}
     };
 
@@ -54,7 +70,7 @@ test_parsers (void)
       GString *string;
 
       string = g_string_new (NULL);
-      empathy_string_parser_substr (string, tests[i], -1, parsers);
+      empathy_string_parser_substr (tests[i], -1, parsers, string);
 
       DEBUG ("'%s' => '%s'", tests[i], string->str);
       g_assert_cmpstr (tests[i + 1], ==, string->str);



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