summary refs log tree commit diff stats
path: root/src/fe-gtk/xtext.c
diff options
context:
space:
mode:
authorRichardHitt <rbh00@netcom.com>2013-01-02 14:50:26 -0800
committerRichardHitt <rbh00@netcom.com>2013-01-02 14:50:26 -0800
commit4af624627eafdd5db9e0200bfd05c59aa60292b9 (patch)
tree602d296c8e34a36396979ea0b82cb7bb471af7da /src/fe-gtk/xtext.c
parent7f2846a5bddbfaf78e99b303db4c9152460bb4d3 (diff)
overhauling of URL detection, including channel, nick, etc 'words'
Diffstat (limited to 'src/fe-gtk/xtext.c')
-rw-r--r--src/fe-gtk/xtext.c125
1 files changed, 85 insertions, 40 deletions
diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index e8419b5a..4d2a8a69 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -13,7 +13,7 @@
  *
  * 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  * =========================================================================
  *
  * xtext, the text widget used by X-Chat.
@@ -73,6 +73,7 @@
 #include "../common/fe.h"
 #include "../common/util.h"
 #include "../common/hexchatc.h"
+#include "../common/url.h"
 #include "fe-gtk.h"
 #include "xtext.h"
 #include "fkeys.h"
@@ -1901,7 +1902,7 @@ gtk_xtext_selection_update (GtkXText * xtext, GdkEventMotion * event, int p_y, g
 
 static char *
 gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
-						  int *ret_off, int *ret_len)
+						  int *ret_off, int *ret_len, GSList **slp)
 {
 	textentry *ent;
 	int offset;
@@ -1950,9 +1951,9 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 	if (ret_off)
 		*ret_off = word - ent->str;
 	if (ret_len)
-		*ret_len = str - word;
+		*ret_len = len;		/* Length before stripping */
 
-	return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, NULL, FALSE);
+	return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, slp, FALSE);
 }
 
 #ifdef MOTION_MONITOR
@@ -2028,14 +2029,62 @@ gtk_xtext_check_mark_stamp (GtkXText *xtext, GdkModifierType mask)
 	return redraw;
 }
 
+static int
+gtk_xtext_get_word_adjust (GtkXText *xtext, int x, int y, textentry **word_ent, int *offset, int *len)
+{
+	GSList *slp = NULL;
+	unsigned char *word;
+	int word_type = 0;
+
+	word = gtk_xtext_get_word (xtext, x, y, word_ent, offset, len, &slp);
+	if (word)
+	{
+		int laststart, lastend;
+
+		word_type = xtext->urlcheck_function (GTK_WIDGET (xtext), word);
+		if (word_type > 0)
+		{
+			if (url_last (&laststart, &lastend))
+			{
+				int cumlen, startadj = 0, endadj = 0;
+				offlen_t o;
+				GSList *sl;
+
+				for (sl = slp, cumlen = 0; sl; sl = g_slist_next (sl))
+				{
+					o.u = GPOINTER_TO_UINT (sl->data);
+					startadj = o.o.off - cumlen;
+					cumlen += o.o.len;
+					if (laststart < cumlen)
+						break;
+				}
+				for (sl = slp, cumlen = 0; sl; sl = g_slist_next (sl))
+				{
+					o.u = GPOINTER_TO_UINT (sl->data);
+					endadj = o.o.off - cumlen;
+					cumlen += o.o.len;
+					if (lastend < cumlen)
+						break;
+				}
+				laststart += startadj;
+				*offset += laststart;
+				*len = lastend + endadj - laststart;
+			}
+		}
+	}
+	g_slist_free (slp);
+
+	return word_type;
+}
+
 static gboolean
 gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event)
 {
 	GtkXText *xtext = GTK_XTEXT (widget);
 	GdkModifierType mask;
 	int redraw, tmp, x, y, offset, len, line_x;
-	unsigned char *word;
 	textentry *word_ent;
+	int word_type;
 
 	gdk_window_get_pointer (widget->window, &x, &y, &mask);
 
@@ -2104,43 +2153,40 @@ gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event)
 	if (xtext->urlcheck_function == NULL)
 		return FALSE;
 
-	word = gtk_xtext_get_word (xtext, x, y, &word_ent, &offset, &len);
-	if (word)
+	word_type = gtk_xtext_get_word_adjust (xtext, x, y, &word_ent, &offset, &len);
+	if (word_type > 0)
 	{
-		if (xtext->urlcheck_function (GTK_WIDGET (xtext), word, len) > 0)
+		if (!xtext->cursor_hand ||
+			 xtext->hilight_ent != word_ent ||
+			 xtext->hilight_start != offset ||
+			 xtext->hilight_end != offset + len)
 		{
-			if (!xtext->cursor_hand ||
-				 xtext->hilight_ent != word_ent ||
-				 xtext->hilight_start != offset ||
-				 xtext->hilight_end != offset + len)
+			if (!xtext->cursor_hand)
 			{
-				if (!xtext->cursor_hand)
-				{
-					gdk_window_set_cursor (GTK_WIDGET (xtext)->window,
-											  		xtext->hand_cursor);
-					xtext->cursor_hand = TRUE;
-				}
+				gdk_window_set_cursor (GTK_WIDGET (xtext)->window,
+										  		xtext->hand_cursor);
+				xtext->cursor_hand = TRUE;
+			}
 
-				/* un-render the old hilight */
-				if (xtext->hilight_ent)
-					gtk_xtext_unrender_hilight (xtext);
+			/* un-render the old hilight */
+			if (xtext->hilight_ent)
+				gtk_xtext_unrender_hilight (xtext);
 
-				xtext->hilight_ent = word_ent;
-				xtext->hilight_start = offset;
-				xtext->hilight_end = offset + len;
+			xtext->hilight_ent = word_ent;
+			xtext->hilight_start = offset;
+			xtext->hilight_end = offset + len;
 
-				xtext->skip_border_fills = TRUE;
-				xtext->render_hilights_only = TRUE;
-				xtext->skip_stamp = TRUE;
+			xtext->skip_border_fills = TRUE;
+			xtext->render_hilights_only = TRUE;
+			xtext->skip_stamp = TRUE;
 
-				gtk_xtext_render_ents (xtext, word_ent, NULL);
+			gtk_xtext_render_ents (xtext, word_ent, NULL);
 
-				xtext->skip_border_fills = FALSE;
-				xtext->render_hilights_only = FALSE;
-				xtext->skip_stamp = FALSE;
-			}
-			return FALSE;
+			xtext->skip_border_fills = FALSE;
+			xtext->render_hilights_only = FALSE;
+			xtext->skip_stamp = FALSE;
 		}
+		return FALSE;
 	}
 
 	gtk_xtext_leave_notify (widget, NULL);
@@ -2280,7 +2326,7 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
 
 		if (!xtext->hilighting)
 		{
-			word = gtk_xtext_get_word (xtext, event->x, event->y, 0, 0, 0);
+			word = gtk_xtext_get_word (xtext, event->x, event->y, 0, 0, 0, 0);
 			g_signal_emit (G_OBJECT (xtext), xtext_signals[WORD_CLICK], 0, word ? word : NULL, event);
 		} else
 		{
@@ -2288,7 +2334,6 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
 		}
 	}
 
-
 	return FALSE;
 }
 
@@ -2305,7 +2350,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
 
 	if (event->button == 3 || event->button == 2) /* right/middle click */
 	{
-		word = gtk_xtext_get_word (xtext, x, y, 0, 0, 0);
+		word = gtk_xtext_get_word (xtext, x, y, 0, 0, 0, 0);
 		if (word)
 		{
 			g_signal_emit (G_OBJECT (xtext), xtext_signals[WORD_CLICK], 0,
@@ -2322,7 +2367,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
 	if (event->type == GDK_2BUTTON_PRESS)	/* WORD select */
 	{
 		gtk_xtext_check_mark_stamp (xtext, mask);
-		if (gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len))
+		if (gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len, 0))
 		{
 			if (len == 0)
 				return FALSE;
@@ -2343,7 +2388,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
 	if (event->type == GDK_3BUTTON_PRESS)	/* LINE select */
 	{
 		gtk_xtext_check_mark_stamp (xtext, mask);
-		if (gtk_xtext_get_word (xtext, x, y, &ent, 0, 0))
+		if (gtk_xtext_get_word (xtext, x, y, &ent, 0, 0, 0))
 		{
 			gtk_xtext_selection_clear (xtext->buffer);
 			ent->mark_start = 0;
@@ -2852,7 +2897,7 @@ gtk_xtext_render_flush (GtkXText * xtext, int x, int y, unsigned char *str,
 {
 	int str_width, dofill;
 	GdkDrawable *pix = NULL;
-	int dest_x, dest_y;
+	int dest_x = 0, dest_y = 0;
 
 	if (xtext->dont_render || len < 1 || xtext->hidden)
 		return 0;
@@ -5904,7 +5949,7 @@ gtk_xtext_set_tint (GtkXText *xtext, int tint_red, int tint_green, int tint_blue
 }
 
 void
-gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *, int))
+gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *))
 {
 	xtext->urlcheck_function = urlcheck_function;
 }