[evolution-patches] Tab selection and long line optimization



Rodo and I have been passing versions of this patch back and forth for
the last few weeks.  It fixes problems with selecting text with tabs and
fixes some rather extreme speed problems gtkhtml had when text contain
very long unbroken words.

--Larry

? .MY_PATCH8.diff.swp
? EVOCRASH_IN_PIXMAPNEW.stack
? MY_PATCH.diff
? MY_PATCH2.diff
? MY_PATCH3.diff
? MY_PATCH4.diff
? MY_PATCH6.diff
? MY_PATCH7.diff
? MY_PATCH8.diff
? htmltext.bork.c
? htmltext.c.mine.c
? htmltext.c.orig.c
? test.html
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/ChangeLog,v
retrieving revision 1.1785
diff -u -p -r1.1785 ChangeLog
--- ChangeLog	29 Apr 2003 16:02:48 -0000	1.1785
+++ ChangeLog	29 Apr 2003 18:46:22 -0000
@@ -1,3 +1,53 @@
+2003-04-29  Larry Ewing  <lewing ximian com>
+
+	* htmltext.c (calc_word_width): walk the string in our own loop
+	and use the offsets directly rather than calulating them from the
+	pointer.
+	(min_word_width_calc_tabs): only calc the tabs in the segment if
+	we find a tab in the segment while walking it. 
+	(html_text_magic_link): remove broken logic that was running the
+	regex over and over and over.
+
+	* htmltextslave.c (get_offset_for_pointer): don't do a linear
+	search for the cursor position, measuring the strings is too
+	expensive.
+	(get_words_width): replace strchr with our own walking loops so
+	that we don't have to walk the string twice.
+	(get_offset_for_bounded_width): ditto.
+	(hts_fit_line): same as above, and make the logic a little easier
+	to read.
+	(draw_highlighted): only do the measurments and drawing that is
+	actually on screen and within this slave.
+
+2003-04-23  Radek Doulik  <rodo ximian com>
+	
+	* htmltextslave.c (get_words_width): fix len calculation, we are
+	incrementing the space now so we have to substract 1 here
+
+	* htmlclueflow.c (layout_line): set current object y to let object
+	know on what line it lives
+
+2003-04-21  Radek Doulik  <rodo ximian com>
+
+	* htmlclueflow.c (html_clueflow_get_line_offset): go forward
+	instead of backward from head of line when calculating line offset
+
+	* htmltext.c (html_text_text_line_length): modify line_offset only
+	if != -1
+
+2003-04-18  Radek Doulik  <rodo ximian com>
+ 
+	* htmltext.c (min_word_width): renamed to express the
+	functionality better
+	(min_word_width_calc_tabs): renamed as well, fix the
+	calculation. the minimal word width is the width of word idx (with
+	optional non-breaking prefix) on begin of line
+
+	* htmltextslave.c (get_words_width): locate the right word, do not
+	stay at first space
+	(get_words_width): don't substract tabs, they are already included
+	in len and width has already one space width for each of them
+
 2003-04-24  Radek Doulik  <rodo ximian com>
 
 	* htmlengine.c (html_engine_freeze): call gtk_html_im_reset when
Index: htmlclueflow.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlclueflow.c,v
retrieving revision 1.285
diff -u -p -r1.285 htmlclueflow.c
--- htmlclueflow.c	8 Apr 2003 20:04:21 -0000	1.285
+++ htmlclueflow.c	29 Apr 2003 18:46:25 -0000
@@ -877,6 +877,7 @@ layout_line (HTMLObject *o, HTMLPainter 
 			need_update_height = TRUE;
 		}
 
+		cur->y = o->ascent + a;
 		fit = html_object_fit_line (cur, painter, first, first, FALSE, width_left (o, x, *rmargin));
 		first = FALSE;
 		if (fit == HTML_FIT_NONE)
@@ -1319,7 +1320,8 @@ check_point (HTMLObject *self,
 	 * shift any selection inside the indent block to the 
 	 * left edge of the flow.
 	 */
-	x = MAX (x, get_indent (HTML_CLUEFLOW (self), painter));
+	if (for_cursor)
+		x = MAX (x, get_indent (HTML_CLUEFLOW (self), painter));
 
 	for (p = clue->head; p; ) {
 
@@ -2887,7 +2889,7 @@ html_clueflow_get_line_offset (HTMLClueF
 		if (head == child)
 			break;
 		line_offset += html_object_get_line_length (head, painter, line_offset);
-		head = html_object_prev_not_slave (head);
+		head = html_object_next_not_slave (head);
 	}
 	/* printf ("lo: %d\n", line_offset); */
 	return line_offset;
Index: htmlengine.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlengine.c,v
retrieving revision 1.537
diff -u -p -r1.537 htmlengine.c
--- htmlengine.c	29 Apr 2003 16:02:49 -0000	1.537
+++ htmlengine.c	29 Apr 2003 18:46:27 -0000
@@ -3828,6 +3828,7 @@ html_engine_begin (HTMLEngine *e, char *
 	
 	free_block (e); /* Clear the block stack */
 
+	html_image_factory_stop_animations (e->image_factory);
 	html_engine_stop_parser (e);
 	e->writing = TRUE;
 	e->begin = TRUE;
@@ -3836,7 +3837,6 @@ html_engine_begin (HTMLEngine *e, char *
 	html_engine_id_table_clear (e);
 	html_engine_class_data_clear (e);
 	html_engine_map_table_clear (e);
-	html_image_factory_stop_animations (e->image_factory);
 
 	new_stream = gtk_html_stream_new (GTK_HTML (e->widget),
 					  html_engine_stream_types,
Index: htmltext.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmltext.c,v
retrieving revision 1.197
diff -u -p -r1.197 htmltext.c
--- htmltext.c	8 Apr 2003 09:13:49 -0000	1.197
+++ htmltext.c	29 Apr 2003 18:46:28 -0000
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /* This file is part of the GtkHTML library.
 
    Copyright (C) 1997 Martin Jones (mjones kde org)
@@ -549,6 +549,7 @@ html_text_text_line_length (const gchar 
 			skip = 8 - (*line_offset % 8);
 		}
 		tab  = found_tab + 1;
+
 		*line_offset  += skip;
 		if (*line_offset != -1)
 			sum_skip += skip - 1;
@@ -557,7 +558,8 @@ html_text_text_line_length (const gchar 
 			(*tabs) ++;
 	}
 
-	(*line_offset) += len - l;
+	if (*line_offset != -1)
+		(*line_offset) += len - l;
 	/* printf ("ll: %d\n", len + sum_skip); */
 
 	return len + sum_skip;
@@ -652,31 +654,38 @@ calc_word_width (HTMLText *text, HTMLPai
 	}
 
 	/* printf ("calc ww m1\n"); */
-	begin = text->text;
+	begin = end = text->text;
 	start_offset = end_offset = 0;
 	il = items;
 	gl = glyphs;
 	cl = 0;
 	for (i = 0; i < text->words; i++) {
-		end   = strchr (begin + (i ? 1 : 0), ' ');
+		while (*end && *end != ' ') {
+			end = g_utf8_next_char (end);
+			end_offset++;
+		}			
 
 		if (il && gl) {
-			/* end_offset = start_offset + (end ? g_utf8_pointer_to_offset (begin, end) : g_utf8_strlen (begin, -1)); */
-			end_offset = start_offset + (end ? g_utf8_pointer_to_offset (begin, end) : g_utf8_strlen (begin, -1));
-			/* printf ("start offset: %d (%d)\n", start_offset, end_offset - start_offset); */
 			cl = word_size (cl, start_offset, end_offset, &il, &gl, &width, &asc, &dsc);
 		} else
 			html_painter_calc_text_size_bytes (painter,
-							   begin, end ? end - begin : strlen (begin), NULL, NULL, 0,
+							   begin, end - begin, NULL, NULL, 0,
 							   NULL, font, style, &width, &asc, &dsc);
+
 		text->word_width [i] = (i ? text->word_width [i - 1] : 0) + width;
 
 		if (obj->ascent < asc)
 			obj->ascent = asc;
 		if (obj->descent < dsc)
 			obj->descent = dsc;
+
 		begin = end;
 		start_offset = end_offset;
+
+		if (*end) {
+			end = g_utf8_next_char (end);
+			end_offset++;
+		}
 	}
 	/* printf ("calc ww m2\n"); */
 
@@ -801,49 +810,77 @@ get_next_nb_width (HTMLText *text, HTMLP
 		return html_text_get_nb_width (HTML_TEXT (obj), painter, begin);
 }
 
-static inline gint
-word_tabs (HTMLText *text, HTMLPainter *p, gint idx)
+static gint
+min_word_width_calc_tabs (HTMLText *text, HTMLPainter *p, gint idx, gint *len)
 {
 	gchar *str, *end;
-	gint rv = 0, line_offset, t1, t2, l1, l2;
-
+	gint rv = 0, line_offset, wt, wl, i;
+	gint epos;
+	gboolean tab = FALSE;
+	
 	if (!html_clueflow_tabs (HTML_CLUEFLOW (HTML_OBJECT (text)->parent), p))
 		return 0;
 
+	/* printf ("tabs %d\n", idx); */
+
 	str = text->text;
-	while (idx > 0 && str && *str) {
-		str = strchr (str, ' ');
-		if (str)
-			str ++;
-		idx --;
+	i = idx;
+	while (i > 0 && *str) {
+		if (*str == ' ')
+			i--;
+
+		str = g_utf8_next_char (str);
 	}
 
-	if (!str || !*str)
+	if (!*str)
 		return 0;
 
-	end = strchr (str, ' ');
-	if (!end)
-		end = str + strlen (str);
-
-	line_offset = html_text_get_line_offset (text, p);
-	l1 = html_text_text_line_length (text->text, &line_offset, g_utf8_pointer_to_offset (text->text, str), &t1);
-	l2 = html_text_text_line_length (text->text, &line_offset, g_utf8_pointer_to_offset (str, end), &t2);
+	epos = 0;
+	end = str;
+	while (*end && *end != ' ') {
+		tab |= *end == '\t';
 
-	rv = l2 - l1 - g_utf8_pointer_to_offset (str, end);
+		end = g_utf8_next_char (end);
+		epos++;
+	}
+	
+
+	if (tab) {
+		line_offset = 0;
+		
+		if (idx == 0) {
+			HTMLObject *prev;
+			
+			prev = html_object_prev_not_slave (HTML_OBJECT (text));
+			if (prev && html_object_is_text (prev) && HTML_TEXT (prev)->words > 0) {
+				min_word_width_calc_tabs (HTML_TEXT (prev), p, HTML_TEXT (prev)->words - 1, &line_offset);
+				/* printf ("lo: %d\n", line_offset); */
+			}
+		}
+
+		wl = html_text_text_line_length (str, &line_offset, epos, &wt);
+	} else {
+		wl = epos;
+	}
+	
+	rv = wl - epos;
+		
+	if (len)
+		*len = wl;
 
 	/* printf ("tabs delta %d\n", rv); */
 	return rv;
 }
 
 static guint
-word_width (HTMLText *text, HTMLPainter *p, guint i)
+min_word_width (HTMLText *text, HTMLPainter *p, guint i)
 {
 	g_assert (i < text->words);
 
 	return text->word_width [i]
 		- (i > 0 ? text->word_width [i - 1]
 		   + html_painter_get_space_width (p, html_text_get_font_style (text), text->face) : 0)
-		+ word_tabs (text, p, i)*html_painter_get_space_width (p, html_text_get_font_style (text), text->face);
+		+ min_word_width_calc_tabs (text, p, i, NULL)*html_painter_get_space_width (p, html_text_get_font_style (text), text->face);
 }
 
 /* return non-breakable text width on begin/end of this text */
@@ -861,7 +898,7 @@ html_text_get_nb_width (HTMLText *text, 
 
 	html_text_request_word_width (text, painter);
 
-	return word_width (text, painter, begin ? 0 : text->words - 1)
+	return min_word_width (text, painter, begin ? 0 : text->words - 1)
 		+ (text->words == 1 ? get_next_nb_width (text, painter, begin) : 0);
 }
 
@@ -939,7 +976,7 @@ calc_min_width (HTMLObject *self, HTMLPa
 	mw = 0;
 
 	for (i = 0; i < text->words; i++) {
-		w = word_width (text, painter, i);
+		w = min_word_width (text, painter, i);
 		prev = next = NULL;
 		if (i == 0) {
 			obj = html_object_prev_not_slave (self);
@@ -1944,18 +1981,14 @@ html_text_magic_link (HTMLText *text, HT
 	}
 
 	if (exec) {
-		while (offset < text->text_len && !rv) {
-			for (i=0; i<MIM_N; i++) {
-				if (mim [i].preg && !regexec (mim [i].preg, str, 2, pmatch, 0)) {
-					paste_link (engine, text,
-						    g_utf8_pointer_to_offset (text->text, str + pmatch [0].rm_so),
-						    g_utf8_pointer_to_offset (text->text, str + pmatch [0].rm_eo), mim [i].prefix);
+		for (i=0; i<MIM_N; i++) {
+			if (mim [i].preg && !regexec (mim [i].preg, str, 2, pmatch, 0)) {
+				paste_link (engine, text,
+					    g_utf8_pointer_to_offset (text->text, str + pmatch [0].rm_so),
+					    g_utf8_pointer_to_offset (text->text, str + pmatch [0].rm_eo), mim [i].prefix);
 					rv = TRUE;
 					break;
-				}
 			}
-			str = g_utf8_next_char (str);
-			offset++;
 		}
 	}
 
Index: htmltextslave.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmltextslave.c,v
retrieving revision 1.145
diff -u -p -r1.145 htmltextslave.c
--- htmltextslave.c	3 Apr 2003 02:13:41 -0000	1.145
+++ htmltextslave.c	29 Apr 2003 18:46:29 -0000
@@ -107,20 +107,22 @@ get_words_width (HTMLTextSlave *slave, H
 
 	if (html_clueflow_tabs (HTML_CLUEFLOW (HTML_OBJECT (slave)->parent), p)) {
 		gchar *space, *str = html_text_slave_get_text (slave);
-		gint tabs, len, line_offset = html_text_slave_get_line_offset (slave, 0, p);
+		gint line_offset = html_text_slave_get_line_offset (slave, 0, p);
+		gint tabs, len = 0; 
 
 		space = str;
-		while (words && space && *space) {
-			space = strchr (space, ' ');
-			words --;
+		while (words && *space && len < slave->posLen) {
+			if (*space == ' ')
+				words --;
+
+			if (words) {
+				space = g_utf8_next_char (space);
+				len++;
+			}
 		}
 
-		if (!space || !*space)
-			len = slave->posLen;
-		else
-			len = g_utf8_pointer_to_offset (str, space);
 		/* printf ("width %d --> ", width); */
-		width += html_painter_get_space_width (p, html_text_get_font_style (text), text->face)*(html_text_text_line_length (str, &line_offset, len, &tabs) - len - tabs);
+		width += html_painter_get_space_width (p, html_text_get_font_style (text), text->face)*(html_text_text_line_length (str, &line_offset, len, &tabs) - len);
 		/* printf ("%d\n", width); */
 	}
 
@@ -195,6 +197,7 @@ get_offset_for_bounded_width (HTMLTextSl
 	HTMLText *text = slave->owner;
 	gint upper = slave->posLen;
 	gint lower = 0;
+	gint off = 0;
 	gint len, width, asc, dsc;
 	gint line_offset = -1;
 	gchar *sep, *str;
@@ -220,12 +223,12 @@ get_offset_for_bounded_width (HTMLTextSl
 	*words = 0;
 	str = sep = buffer;
 
-	while ((sep = strchr (sep, ' '))) {
-		if (g_utf8_pointer_to_offset (str, sep) < len)
+	while (off < len && *sep) {
+		if (*sep == ' ') 
 			(*words) ++;
-		else
-			break;
-		sep = sep + 1;
+
+		sep = g_utf8_next_char (sep);
+		off++;
 	}
 
 	return len;
@@ -442,7 +445,7 @@ hts_fit_line (HTMLObject *o, HTMLPainter
 	HTMLText *text;
 	HTMLObject *prev;
 	guint  pos = 0;
-	gchar *sep = NULL, *lsep;
+	gchar *sep = NULL;
 	gchar *begin;
 	guint words = 0;
 	gint orig_start_word;
@@ -464,10 +467,17 @@ hts_fit_line (HTMLObject *o, HTMLPainter
 	while ((sep && *sep
 		&& widthLeft >= html_text_slave_nb_width (slave, painter, words + 1))
 	       || (words == 0 && text->words - slave->start_word > 0 && forceFit)) {
+		if (words) {
+			sep = g_utf8_next_char (sep);
+			pos++;
+		}
+		
 		words ++;
-		lsep   = sep;
-		sep    = strchr (lsep + (words > 1 ? 1 : 0), ' ');
-		pos    = sep ? g_utf8_pointer_to_offset (begin, sep) : g_utf8_strlen (begin, -1);
+		while (*sep && *sep != ' ') {
+			sep = g_utf8_next_char (sep);
+			pos++;
+		}
+
 		if (words + slave->start_word >= text->words)
 			break;
 	}
@@ -489,18 +499,23 @@ hts_fit_line (HTMLObject *o, HTMLPainter
 		} else if (slave->start_word + 1 == text->words)
 			rv = next_to_floating ? HTML_FIT_NONE : HTML_FIT_COMPLETE;
 		else {
-			words ++;
+			if (words && *sep) {
+				sep = g_utf8_next_char (sep);
+				pos++;
+			}
 
-			if (sep)
-				sep = strchr (sep + (words > 1 ? 0 : 1), ' ');
+			words ++;
 
-			pos = sep ? g_utf8_pointer_to_offset (begin, sep) : g_utf8_strlen (begin, -1);
+			while (*sep && *sep != ' ') {
+				sep = g_utf8_next_char (sep);
+				pos ++;
+			}
 		}
 	}
 
 	if (rv == HTML_FIT_PARTIAL)
 		if (pos < slave->posLen) {
-			split (slave, pos, slave->start_word + words, sep);
+			split (slave, pos, slave->start_word + words, *sep ? sep : NULL);
 		o->width = get_words_width (slave, painter, words);
 	}
 
@@ -774,64 +789,71 @@ draw_highlighted (HTMLTextSlave *slave,
 
 	lo_start = lo = html_text_slave_get_line_offset (slave, 0, p);
 
+	html_painter_set_font_style (p, font_style);
+	html_painter_set_font_face  (p, HTML_TEXT (owner)->face);
+	html_color_alloc (HTML_TEXT (owner)->color, p);
+
+	/* 1. Draw the leftmost non-highlighted part, if any.  */
 	if (start > slave->posStart) {
 		glyphs1 = get_glyphs_part (slave, p, 0, start - slave->posStart, &items1);
 		html_painter_calc_text_size (p, slave_begin, start - slave->posStart, items1, glyphs1, slave_begin - text, &lo,
 					     font_style, HTML_TEXT (owner)->face, &offset_width, &asc, &dsc);
+
+		html_painter_set_pen (p, &HTML_TEXT (owner)->color->color);
+
+		if (obj->x + offset_width >= x)
+			html_painter_draw_text (p,
+						obj->x + tx, obj->y + ty + get_ys (HTML_TEXT (slave->owner), p),
+						slave_begin,
+						start - slave->posStart, items1, glyphs1, slave_begin - slave->owner->text,
+						lo_start);
+
+		if (glyphs1)
+			glyphs_destroy (glyphs1);
+
 	} else
 		offset_width = 0;
+
 	lo_sel = lo;
+	
+	/* Check bounds again */
+	if (obj->x + offset_width > x + width)
+		return;
 
+	/* Draw the highlighted part with a highlight background.  */
 	if (len) {
 		glyphs2 = get_glyphs_part (slave, p, start - slave->posStart, len, &items2);
 
 		html_painter_calc_text_size (p, highlight_begin, len, items2, glyphs2, highlight_begin - text, &lo,
 					     font_style, HTML_TEXT (owner)->face, &text_width, &asc, &dsc);
 		/* printf ("s: %d l: %d - %d %d\n", start, len, offset_width, text_width); */
-	} else
-		text_width = 0;
-
-	/* printf ("lo %d - %d(%d) - %d(%d)\n", lo_start, lo_sel, start, lo, end); */
 
-	html_painter_set_font_style (p, font_style);
-	html_painter_set_font_face  (p, HTML_TEXT (owner)->face);
-
-	/* Draw the highlighted part with a highlight background.  */
-
-	html_color_alloc (HTML_TEXT (owner)->color, p);
-	html_painter_set_pen (p, &html_colorset_get_color_allocated
-			      (p, p->focus ? HTMLHighlightColor : HTMLHighlightNFColor)->color);
-	html_painter_fill_rect (p, obj->x + tx + offset_width, obj->y + ty - obj->ascent,
-				text_width, obj->ascent + obj->descent);
-	html_painter_set_pen (p, &html_colorset_get_color_allocated
-			      (p, p->focus ? HTMLHighlightTextColor : HTMLHighlightTextNFColor)->color);
-
-	if (len) {
-		html_painter_draw_text (p, obj->x + tx + offset_width, 
-					obj->y + ty + get_ys (HTML_TEXT (slave->owner), p),
-					highlight_begin, len, items2, glyphs2, highlight_begin - slave->owner->text,
-					lo_sel);
+		html_painter_set_pen (p, &html_colorset_get_color_allocated
+				      (p, p->focus ? HTMLHighlightColor : HTMLHighlightNFColor)->color);
+		html_painter_fill_rect (p, obj->x + tx + offset_width, obj->y + ty - obj->ascent,
+					text_width, obj->ascent + obj->descent);
+		html_painter_set_pen (p, &html_colorset_get_color_allocated
+				      (p, p->focus ? HTMLHighlightTextColor : HTMLHighlightTextNFColor)->color);
+		
+		if (obj->x + offset_width + text_width >= x)
+			html_painter_draw_text (p, obj->x + tx + offset_width, 
+						obj->y + ty + get_ys (HTML_TEXT (slave->owner), p),
+						highlight_begin, len, items2, glyphs2, highlight_begin - slave->owner->text,
+						lo_sel);
 		if (glyphs2)
 			glyphs_destroy (glyphs2);
-	}
-	/* Draw the non-highlighted part.  */
-	html_painter_set_pen (p, &HTML_TEXT (owner)->color->color);
+	} else
+		text_width = 0;
 
-	/* 1. Draw the leftmost non-highlighted part, if any.  */
-	if (start > slave->posStart) {
-		html_painter_draw_text (p,
-					obj->x + tx, obj->y + ty + get_ys (HTML_TEXT (slave->owner), p),
-					slave_begin,
-					start - slave->posStart, items1, glyphs1, slave_begin - slave->owner->text,
-					lo_start);
-		if (glyphs1)
-			glyphs_destroy (glyphs1);
-	}
+	/* Check bounds one last time */
+	if (obj->x + offset_width + text_width > x + width)
+		return;
 
 	/* 2. Draw the rightmost non-highlighted part, if any.  */
 	if (end < slave->posStart + slave->posLen) {
 		gchar *end_text;
 		glyphs3 = get_glyphs_part (slave, p, start + len - slave->posStart, slave->posLen - start - len + slave->posStart, &items3);
+		html_painter_set_pen (p, &HTML_TEXT (owner)->color->color);
 		end_text = g_utf8_offset_to_pointer (highlight_begin, end - start);
 		html_painter_draw_text (p,
 					obj->x + tx + offset_width + text_width,
@@ -908,9 +930,15 @@ get_offset_for_pointer (HTMLTextSlave *s
 	HTMLText *owner;
 	GtkHTMLFontStyle font_style;
 	guint width, prev_width;
-	guint i;
-	gint line_offset, lo, word;
+	gint line_offset;
 	gchar *text;
+	guint upper;
+	guint len;
+	guint lower;
+	GList *items;
+	GList *glyphs;
+	gint lo;
+	gint asc, dsc;
 
 	g_return_val_if_fail (slave != NULL, 0);
 
@@ -919,45 +947,47 @@ get_offset_for_pointer (HTMLTextSlave *s
 
 	x -= HTML_OBJECT (slave)->x;
 
+	if (x <= 0)
+		return 0;
+
+	if (x >= HTML_OBJECT (slave)->width)
+		return slave->posLen;
+				      
+	len = 0;
+	width = 0;
 	prev_width  = 0;
-	line_offset = html_text_slave_get_line_offset (slave, 0, painter);
+	lower = 0;
+	upper = slave->posLen;
 
-	i = 1;
-	word = 1;
 	text = html_text_slave_get_text (slave);
-	/*space = strchr (text, ' ');
-	if (space && g_utf8_pointer_to_offset (text, space) <= slave->posLen) {
-		html_text_request_word_width (owner, painter);
-
-		ww = get_words_width (owner, painter, slave->start_word, word);
-		while (ww < x && space) {
-			i = g_utf8_pointer_to_offset (text, space);
-			space = strchr (space + 1, ' ');
-			if (space && g_utf8_pointer_to_offset (text, space) >= slave->posLen) {
-				break;
-			}
-			word ++;
-			ww = get_words_width (owner, painter, slave->start_word, word);
-		}
-		}*/
+	line_offset = html_text_slave_get_line_offset (slave, 0, painter);	
 
-	for ( ; i <= slave->posLen; i++) {
-		GList *items;
-		GList *glyphs;
-		gint asc, dsc;
 
+	while (upper - lower > 1) {
 		lo = line_offset;
-		glyphs = get_glyphs_part (slave, painter, 0, i, &items);
-		html_painter_calc_text_size (painter, text, i, items, glyphs, html_text_slave_get_start_byte_offset (slave), &lo, font_style, owner->face, &width, &asc, &dsc);
-		glyphs_destroy (glyphs);
+		prev_width = width;
 
-		if ((width + prev_width) / 2 >= x)
-			return i - 1;
+		if (width > x)
+			upper = len;
+		else 
+			lower = len;
+	
+		len = (lower + upper + 1) / 2;
 
-		prev_width = width;
+		if (len) {
+			glyphs = get_glyphs_part (slave, painter, 0, len, &items);
+			html_painter_calc_text_size (painter, text, len, items, glyphs, html_text_slave_get_start_byte_offset (slave), 
+						     &lo, font_style, owner->face, &width, &asc, &dsc);
+			glyphs_destroy (glyphs);
+		} else {
+			width = 0;
+		}
 	}
 
-	return slave->posLen;
+	if ((width + prev_width) / 2 >= x)
+		len--;
+
+	return len;
 }
 
 static HTMLObject *


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