summary refs log tree commit diff stats
path: root/src/fe-gtk/xtext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-gtk/xtext.c')
-rw-r--r--src/fe-gtk/xtext.c249
1 files changed, 135 insertions, 114 deletions
diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index 6a499f52..6692b360 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -31,13 +31,19 @@
 #include <stdlib.h>
 #include <time.h>
 
-#include "../../config.h"
+#include "config.h"
 #include "../common/hexchat.h"
 #include "../common/fe.h"
 #include "../common/util.h"
 #include "../common/hexchatc.h"
 #include "../common/url.h"
+
+#ifdef WIN32
+#include "marshal.h"
+#else
 #include "../common/marshal.h"
+#endif
+
 #include "fe-gtk.h"
 #include "xtext.h"
 #include "fkeys.h"
@@ -484,7 +490,10 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
 		adj->page_increment = adj->page_size;
 
 		if (adj->value > adj->upper - adj->page_size)
+		{
+			buf->scrollbar_down = TRUE;
 			adj->value = adj->upper - adj->page_size;
+		}
 
 		if (adj->value < 0)
 			adj->value = 0;
@@ -829,7 +838,6 @@ find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent)
 	int off, len, wid, mbl, mbw;
 
 	/* Skip to the first chunk of stuff for the subline */
-	list = ent->slp;
 	if (subline > 0)
 	{
 		suboff = GPOINTER_TO_INT (g_slist_nth_data (ent->sublines, subline - 1));
@@ -846,6 +854,8 @@ find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent)
 		list = ent->slp;
 	} 
 	/* Step to the first character of the subline */
+	if (list == NULL)
+		return 0;
 	meta = list->data;
 	off = meta->off;
 	len = meta->len;
@@ -934,12 +944,12 @@ gtk_xtext_find_x (GtkXText * xtext, int x, textentry * ent, int subline,
 }
 
 static textentry *
-gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
-							int *out_of_bounds, int *ret_subline)
+gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off, int *out_of_bounds)
 {
 	textentry *ent;
 	int line;
 	int subline;
+	int outofbounds;
 
 	/* Adjust y value for negative rounding, double to int */
 	if (y < 0)
@@ -948,13 +958,12 @@ gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
 	line = (y + xtext->pixel_offset) / xtext->fontsize;
 	ent = gtk_xtext_nth (xtext, line + (int)xtext->adj->value, &subline);
 	if (!ent)
-		return 0;
+		return NULL;
 
 	if (off)
-		*off = gtk_xtext_find_x (xtext, x, ent, subline, line, out_of_bounds);
-
-	if (ret_subline)
-		*ret_subline = subline;
+		*off = gtk_xtext_find_x (xtext, x, ent, subline, line, &outofbounds);
+	if (out_of_bounds)
+		*out_of_bounds = outofbounds;
 
 	return ent;
 }
@@ -1049,14 +1058,14 @@ gtk_xtext_paint (GtkWidget *widget, GdkRectangle *area)
 		return;
 	}
 
-	ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL, NULL);
+	ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL);
 	if (!ent_start)
 	{
 		xtext_draw_bg (xtext, area->x, area->y, area->width, area->height);
 		goto xit;
 	}
 	ent_end = gtk_xtext_find_char (xtext, area->x + area->width,
-											 area->y + area->height, NULL, NULL, NULL);
+											 area->y + area->height, NULL, NULL);
 	if (!ent_end)
 		ent_end = xtext->buffer->text_last;
 
@@ -1244,13 +1253,14 @@ lamejump:
 		}
 	}
 	/* marking upward? */
-	else if (xtext->buffer->last_ent_end == end_ent &&
+	else if (xtext->buffer->last_ent_start != NULL &&
+				xtext->buffer->last_ent_end == end_ent &&
 				xtext->buffer->last_offset_end == end_offset)
 	{
 		ent = end_ent;
 		while (ent)
 		{
-			if (ent == start_ent)
+			if (ent == start_ent && xtext->buffer->last_ent_start)
 			{
 				gtk_xtext_selection_up (xtext, xtext->buffer->last_ent_start, ent, start_offset);
 				/*gtk_xtext_render_ents (xtext, xtext->buffer->last_ent_start, ent);*/
@@ -1299,99 +1309,104 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 	textentry *ent;
 	textentry *ent_end;
 	textentry *ent_start;
-	int offset_start;
-	int offset_end;
-	int subline_start;
-	int subline_end;
-	int oob;
-	int marking_up = FALSE;
-	int len_start;
-	int len_end;
+	int offset_start = 0;
+	int offset_end = 0;
+	textentry *low_ent, *high_ent;
+	int low_x, low_y, low_offs;
+	int high_x, high_y, high_offs, high_len;
 
-	ent_start = gtk_xtext_find_char (xtext, xtext->select_start_x, xtext->select_start_y, &offset_start, &oob, &subline_start);
-	ent_end = gtk_xtext_find_char (xtext, xtext->select_end_x, xtext->select_end_y, &offset_end, &oob, &subline_end);
+	if (xtext->buffer->text_first == NULL)
+		return;
 
-	if ((!ent_start || !ent_end) && !xtext->buffer->text_last && xtext->adj->value != xtext->buffer->old_value)
-	{
-		gtk_xtext_render_page (xtext);
+	ent_start = gtk_xtext_find_char (xtext, xtext->select_start_x, xtext->select_start_y, &offset_start, NULL);
+	ent_end = gtk_xtext_find_char (xtext, xtext->select_end_x, xtext->select_end_y, &offset_end, NULL);
+	if (ent_start == NULL && ent_end == NULL)
 		return;
-	}
 
-	if (!ent_start)
+	if	((ent_start != ent_end && xtext->select_start_y > xtext->select_end_y) || /* different entries */
+		(ent_start == ent_end && offset_start > offset_end))	/* same entry, different character offsets */
 	{
-		ent_start = xtext->buffer->text_last;
-		offset_start = ent_start->str_len;
+		/* marking up */
+		low_ent = ent_end;
+		low_x = xtext->select_end_x;
+		low_y = xtext->select_end_y;
+		low_offs = offset_end;
+		high_ent = ent_start;
+		high_x = xtext->select_start_x;
+		high_y = xtext->select_start_y;
+		high_offs = offset_start;
 	}
-
-	if (!ent_end)
+	else
 	{
-		ent_end = xtext->buffer->text_last;
-		offset_end = ent_end->str_len;
+		/* marking down */
+		low_ent = ent_start;
+		low_x = xtext->select_start_x;
+		low_y = xtext->select_start_y;
+		low_offs = offset_start;
+		high_ent = ent_end;
+		high_x = xtext->select_end_x;
+		high_y = xtext->select_end_y;
+		high_offs = offset_end;
 	}
-
-	if ((ent_start != ent_end && xtext->select_start_y > xtext->select_end_y) || /* different entries */
-		(ent_start == ent_end && subline_start > subline_end) || /* different lines */
-		(ent_start == ent_end && subline_start == subline_end && xtext->select_start_x > xtext->select_end_x)) /* marking to the left */
+	if (low_ent == NULL)
+	{
+		low_ent = xtext->buffer->text_first;
+		low_offs = 0;
+	}
+	if (high_ent == NULL)
 	{
-		marking_up = TRUE;
+		high_ent = xtext->buffer->text_last;
+		high_offs = high_ent->str_len;
 	}
 
 	/* word selection */
 	if (xtext->word_select)
 	{
 		/* a word selection cannot be started if the cursor is out of bounds in gtk_xtext_button_press */
-		gtk_xtext_get_word (xtext, xtext->select_start_x, xtext->select_start_y, NULL, &offset_start, &len_start, NULL);
+		gtk_xtext_get_word (xtext, low_x, low_y, NULL, &low_offs, NULL, NULL);
 
 		/* in case the cursor is out of bounds we keep offset_end from gtk_xtext_find_char and fix the length */
-		if (gtk_xtext_get_word (xtext, xtext->select_end_x, xtext->select_end_y, NULL, &offset_end, &len_end, NULL) == NULL)
-			len_end = offset_end == ent_end->str_len? 0: -1; /* -1 for the space, 0 if at the end */
-
-		if (!marking_up)
-			offset_end += len_end;
-		else
-			offset_start += len_start;
+		if (gtk_xtext_get_word (xtext, high_x, high_y, NULL, &high_offs, &high_len, NULL) == NULL)
+			high_len = high_offs == high_ent->str_len? 0: -1; /* -1 for the space, 0 if at the end */
+		high_offs += high_len;
+		if (low_y < 0)
+			low_offs = xtext->buffer->last_offset_start;
+		if (high_y > xtext->buffer->window_height)
+			high_offs = xtext->buffer->last_offset_end;
 	}
 	/* line/ent selection */
 	else if (xtext->line_select)
 	{
-		offset_start = marking_up? ent_start->str_len: 0;
-		offset_end = marking_up? 0: ent_end->str_len;
+		low_offs = 0;
+		high_offs = high_ent->str_len;
 	}
-
-	if (marking_up)
+	/* character selection */
+	else
 	{
-		int temp;
-
-		/* ensure ent_start is above ent_end */
-		if (ent_start != ent_end)
-		{
-			ent = ent_start;
-			ent_start = ent_end;
-			ent_end = ent;
-		}
-
-		/* switch offsets as well */
-		temp = offset_start;
-		offset_start = offset_end;
-		offset_end = temp;
+		if (low_y < 0)
+			low_offs = xtext->buffer->last_offset_start;
+		if (high_y > xtext->buffer->window_height)
+			high_offs = xtext->buffer->last_offset_end;
 	}
 
 	/* set all the old mark_ fields to -1 */
 	gtk_xtext_selection_clear (xtext->buffer);
 
-	/* set the default values */
-	ent_start->mark_end = ent_start->str_len;
-	ent_end->mark_start = 0;
+	low_ent->mark_start = low_offs;
+	low_ent->mark_end = high_offs;
 
-	/* set the calculated values (this overwrites the default values if we're on the same ent) */
-	ent_start->mark_start = offset_start;
-	ent_end->mark_end = offset_end;
-
-	/* set all the mark_ fields of the ents within the selection */
-	if (ent_start != ent_end)
+	if (low_ent != high_ent)
 	{
-		ent = ent_start->next;
-		while (ent && ent != ent_end)
+		low_ent->mark_end = low_ent->str_len;
+		if (high_offs != 0)
+		{
+			high_ent->mark_start = 0;
+			high_ent->mark_end = high_offs;
+		}
+
+		/* set all the mark_ fields of the ents within the selection */
+		ent = low_ent->next;
+		while (ent && ent != high_ent)
 		{
 			ent->mark_start = 0;
 			ent->mark_end = ent->str_len;
@@ -1400,7 +1415,7 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
 	}
 
 	if (render)
-		gtk_xtext_selection_render (xtext, ent_start, ent_end);
+		gtk_xtext_selection_render (xtext, low_ent, high_ent);
 }
 
 static int
@@ -1532,7 +1547,7 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 	int out_of_bounds = 0;
 	int len_to_offset = 0;
 
-	ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds, NULL);
+	ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds);
 	if (ent == NULL || out_of_bounds || offset < 0 || offset >= ent->str_len)
 		return NULL;
 
@@ -1585,11 +1600,11 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
 
 		/* make sure we're not before the start of the match */
 		if (len_to_offset < start)
-			return 0;
+			return NULL;
 
 		/* and not after it */
 		if (len_to_offset - start >= end - start)
-			return 0;
+			return NULL;
 	}
 
 	return word;
@@ -1646,7 +1661,8 @@ gtk_xtext_check_mark_stamp (GtkXText *xtext, GdkModifierType mask)
 {
 	gboolean redraw = FALSE;
 
-	if (mask & STATE_SHIFT || prefs.hex_text_autocopy_stamp)
+	if ((mask & STATE_SHIFT || prefs.hex_text_autocopy_stamp)
+	    && (!prefs.hex_stamp_text || prefs.hex_text_indent))
 	{
 		if (!xtext->mark_stamp)
 		{
@@ -1707,7 +1723,7 @@ gtk_xtext_get_word_adjust (GtkXText *xtext, int x, int y, textentry **word_ent,
 			}
 		}
 	}
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 
 	return word_type;
 }
@@ -1853,7 +1869,7 @@ gtk_xtext_set_clip_owner (GtkWidget * xtext, GdkEventButton * event)
 			gtk_selection_owner_set (xtext, GDK_SELECTION_SECONDARY, event ? event->time : GDK_CURRENT_TIME);
 		}
 
-		free (str);
+		g_free (str);
 	}
 }
 
@@ -2107,7 +2123,7 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
 		return NULL;
 
 	/* now allocate mem and copy buffer */
-	pos = txt = malloc (len);
+	pos = txt = g_malloc (len);
 	ent = buf->last_ent_start;
 	while (ent)
 	{
@@ -2147,10 +2163,11 @@ gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret)
 		/*stripped = gtk_xtext_conv_color (txt, strlen (txt), &len);*/
 		stripped = txt;
 		len = strlen (txt);
-	} else
+	}
+	else
 	{
 		stripped = gtk_xtext_strip_color (txt, strlen (txt), NULL, &len, NULL, FALSE);
-		free (txt);
+		g_free (txt);
 	}
 
 	*len_ret = len;
@@ -2205,7 +2222,7 @@ gtk_xtext_selection_get (GtkWidget * widget,
 		g_free (new_text);
 	}
 
-	free (stripped);
+	g_free (stripped);
 }
 
 static gboolean
@@ -2360,7 +2377,7 @@ xtext_do_chunk(chunk_t *c)
 	if (c->len1 == 0)
 		return;
 
-	meta = malloc (sizeof *meta);
+	meta = g_new (offlen_t, 1);
 	meta->off = c->off1;
 	meta->len = c->len1;
 	meta->emph = c->emph;
@@ -2383,7 +2400,7 @@ gtk_xtext_strip_color (unsigned char *text, int len, unsigned char *outbuf,
 	int mbl;	/* multi-byte length */
 
 	if (outbuf == NULL)
-		new_str = malloc (len + 2);
+		new_str = g_malloc (len + 2);
 	else
 		new_str = outbuf;
 
@@ -2459,7 +2476,7 @@ bad_utf8:		/* Normal ending sequence, and give up if bad utf8 */
 	if (slpp)
 		*slpp = c.slp;
 	else
-		g_slist_free_full (c.slp, free);
+		g_slist_free_full (c.slp, g_free);
 
 	return new_str;
 }
@@ -2475,7 +2492,7 @@ gtk_xtext_text_width_ent (GtkXText *xtext, textentry *ent)
 
 	if (ent->slp)
 	{
-		g_slist_free_full (ent->slp, free);
+		g_slist_free_full (ent->slp, g_free);
 		ent->slp = NULL;
 	}
 
@@ -2507,7 +2524,7 @@ gtk_xtext_text_width (GtkXText *xtext, unsigned char *text, int len)
 												&new_len, &slp, !xtext->ignore_hidden);
 
 	width =  backend_get_text_width_slp (xtext, new_buf, slp);
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 
 	return width;
 }
@@ -3254,7 +3271,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
 {
 	textentry tmp_ent;
 	int jo, ji, hs;
-	int xsize, y;
+	int xsize, y, emphasis;
 
 	/* trashing ent here, so make a backup first */
 	memcpy (&tmp_ent, ent, sizeof (tmp_ent));
@@ -3264,7 +3281,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
 	xtext->jump_out_offset = 0;
 	xtext->jump_in_offset = 0;
 	xtext->hilight_start = 0xffff;	/* temp disable */
-	int emphasis = 0;
+	emphasis = 0;
 
 	if (xtext->mark_stamp)
 	{
@@ -3530,7 +3547,7 @@ gtk_xtext_save (GtkXText * xtext, int fh)
 											  &newlen, NULL, FALSE);
 		write (fh, buf, newlen);
 		write (fh, "\n", 1);
-		free (buf);
+		g_free (buf);
 		ent = ent->next;
 	}
 }
@@ -3641,7 +3658,7 @@ gtk_xtext_nth (GtkXText *xtext, int line, int *subline)
 					break;
 				lines -= g_slist_length (ent->sublines);
 			}
-			return 0;
+			return NULL;
 		}
 	}
 	/* -- end of optimization -- */
@@ -3656,7 +3673,7 @@ gtk_xtext_nth (GtkXText *xtext, int line, int *subline)
 		}
 		ent = ent->next;
 	}
-	return 0;
+	return NULL;
 }
 
 /* render enta (or an inclusive range enta->entb) */
@@ -3895,10 +3912,10 @@ gtk_xtext_kill_ent (xtext_buffer *buffer, textentry *ent)
 		gtk_xtext_search_textentry_del (buffer, ent);
 	}
 
-	g_slist_free_full (ent->slp, free);
+	g_slist_free_full (ent->slp, g_free);
 	g_slist_free (ent->sublines);
 
-	free (ent);
+	g_free (ent);
 	return visible;
 }
 
@@ -4033,7 +4050,7 @@ gtk_xtext_clear (xtext_buffer *buf, int lines)
 		while (buf->text_first)
 		{
 			next = buf->text_first->next;
-			free (buf->text_first);
+			g_free (buf->text_first);
 			buf->text_first = next;
 		}
 		buf->text_last = NULL;
@@ -4191,7 +4208,6 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent)
 
 		hay = match? g_strdup (str): g_utf8_casefold (str, lstr);
 		lhay = strlen (hay);
-		off = 0;
 
 		for (pos = hay, len = lhay; len;
 			  off += buf->search_lnee, pos = hay + off, len = lhay - off)
@@ -4210,7 +4226,7 @@ gtk_xtext_search_textentry (xtext_buffer *buf, textentry *ent)
 	}
 
 	/* Common processing --- */
-	g_slist_free_full (slp, free);
+	g_slist_free_full (slp, g_free);
 	return gl;
 }
 
@@ -4639,7 +4655,7 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 	if (right_text[right_len-1] == '\n')
 		right_len--;
 
-	ent = malloc (left_len + right_len + 2 + sizeof (textentry));
+	ent = g_malloc (left_len + right_len + 2 + sizeof (textentry));
 	str = (unsigned char *) ent + sizeof (textentry);
 
 	memcpy (str, left_text, left_len);
@@ -4660,7 +4676,9 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 		space = 0;
 
 	/* do we need to auto adjust the separator position? */
-	if (buf->xtext->auto_indent && ent->indent < MARGIN + space)
+	if (buf->xtext->auto_indent &&
+		 buf->indent < buf->xtext->max_auto_indent &&
+		 ent->indent < MARGIN + space)
 	{
 		tempindent = MARGIN + space + buf->xtext->space_width + left_width;
 
@@ -4681,7 +4699,7 @@ gtk_xtext_append_indent (xtext_buffer *buf,
 }
 
 void
-gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
+gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len, time_t stamp)
 {
 	textentry *ent;
 
@@ -4694,7 +4712,7 @@ gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
 	if (len >= sizeof (buf->xtext->scratch_buffer))
 		len = sizeof (buf->xtext->scratch_buffer) - 1;
 
-	ent = malloc (len + 1 + sizeof (textentry));
+	ent = g_malloc (len + 1 + sizeof (textentry));
 	ent->str = (unsigned char *) ent + sizeof (textentry);
 	ent->str_len = len;
 	if (len)
@@ -4703,7 +4721,7 @@ gtk_xtext_append (xtext_buffer *buf, unsigned char *text, int len)
 	ent->indent = 0;
 	ent->left_len = -1;
 
-	gtk_xtext_append_entry (buf, ent, 0);
+	gtk_xtext_append_entry (buf, ent, stamp);
 }
 
 gboolean
@@ -4738,11 +4756,14 @@ gtk_xtext_lastlog (xtext_buffer *out, xtext_buffer *search_area)
 			}
 			else
 			{
-				gtk_xtext_append (out, ent->str, ent->str_len);
+				gtk_xtext_append (out, ent->str, ent->str_len, 0);
 			}
 
-			out->text_last->stamp = ent->stamp;
-			gtk_xtext_search_textentry_add (out, out->text_last, gl, TRUE);
+			if (out->text_last)
+			{
+				out->text_last->stamp = ent->stamp;
+				gtk_xtext_search_textentry_add (out, out->text_last, gl, TRUE);
+			}
 		}
 		ent = ent->next;
 	}
@@ -4936,6 +4957,7 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
 		if (buf->window_width != w)
 		{
 			buf->window_width = w;
+			buf->window_height = h;
 			gtk_xtext_calc_lines (buf, FALSE);
 			if (buf->scrollbar_down)
 				gtk_adjustment_set_value (xtext->adj, xtext->adj->upper -
@@ -4959,8 +4981,7 @@ gtk_xtext_buffer_new (GtkXText *xtext)
 {
 	xtext_buffer *buf;
 
-	buf = malloc (sizeof (xtext_buffer));
-	memset (buf, 0, sizeof (xtext_buffer));
+	buf = g_new0 (xtext_buffer, 1);
 	buf->old_value = -1;
 	buf->xtext = xtext;
 	buf->scrollbar_down = TRUE;
@@ -4990,9 +5011,9 @@ gtk_xtext_buffer_free (xtext_buffer *buf)
 	while (ent)
 	{
 		next = ent->next;
-		free (ent);
+		g_free (ent);
 		ent = next;
 	}
 
-	free (buf);
+	g_free (buf);
 }