[pango] Handle NUL in text in places that g_utf8_strlen () was used



commit 67052645e6afcd7f72ef852c99ee88897d2022da
Author: Behdad Esfahbod <behdad behdad org>
Date:   Wed Jul 15 13:59:20 2009 -0400

    Handle NUL in text in places that g_utf8_strlen () was used
    
    While pango-layout doesn't allow NUL in text, the lower level API should
    handle it correctly.  We were using g_utf8_strlen() in a number of
    places.  This is problematic since that function stops processing at
    NUL even if length>1.  We now use an internal pango_utf8_strlen() instead.
    
    Inspired by:
    Bug 588678 â?? pango crash: install a new theme from gnome-appearance-properties

 pango/break.c            |    3 ++-
 pango/ellipsize.c        |    5 +++--
 pango/glyphstring.c      |    6 ++++--
 pango/pango-engine.c     |    2 +-
 pango/pango-glyph-item.c |    8 ++++----
 pango/pango-impl-utils.h |   27 +++++++++++++++++++++++++++
 pango/pango-layout.c     |   16 ++++++++--------
 7 files changed, 49 insertions(+), 18 deletions(-)
---
diff --git a/pango/break.c b/pango/break.c
index c170745..b17dc60 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -24,6 +24,7 @@
 #include "pango-break.h"
 #include "pango-modules.h"
 #include "pango-script-private.h"
+#include "pango-impl-utils.h"
 #include <string.h>
 
 #define PARAGRAPH_SEPARATOR 0x2029
@@ -1809,7 +1810,7 @@ tailor_segment (const char      *range_start,
   PangoLogAttr attr_before = log_attrs[0];
 
   analysis->lang_engine = range_engine;
-  chars_in_range = g_utf8_strlen (range_start, range_end - range_start);
+  chars_in_range = pango_utf8_strlen (range_start, range_end - range_start);
 
 
   if (tailor_break (range_start,
diff --git a/pango/ellipsize.c b/pango/ellipsize.c
index 3a39a78..1c8aa24 100644
--- a/pango/ellipsize.c
+++ b/pango/ellipsize.c
@@ -25,6 +25,7 @@
 #include "pango-glyph-item.h"
 #include "pango-layout-private.h"
 #include "pango-engine-private.h"
+#include "pango-impl-utils.h"
 
 typedef struct _EllipsizeState EllipsizeState;
 typedef struct _RunInfo        RunInfo;
@@ -123,7 +124,7 @@ init_state (EllipsizeState  *state,
   state->n_runs = g_slist_length (line->runs);
   state->run_info = g_new (RunInfo, state->n_runs);
 
-  start_offset = g_utf8_strlen (line->layout->text,
+  start_offset = pango_utf8_strlen (line->layout->text,
 				line->start_index);
 
   state->total_width = 0;
@@ -636,7 +637,7 @@ fixup_ellipsis_run (EllipsizeState *state)
   /* Fix up the item to point to the entire elided text */
   item->offset = state->gap_start_iter.run_iter.start_index;
   item->length = state->gap_end_iter.run_iter.end_index - item->offset;
-  item->num_chars = g_utf8_strlen (state->layout->text + item->offset, item->length);
+  item->num_chars = pango_utf8_strlen (state->layout->text + item->offset, item->length);
 
   /* The level for the item is the minimum level of the elided text */
   level = G_MAXINT;
diff --git a/pango/glyphstring.c b/pango/glyphstring.c
index 2e3a9f8..9e7c5f8 100644
--- a/pango/glyphstring.c
+++ b/pango/glyphstring.c
@@ -320,7 +320,9 @@ pango_glyph_string_get_width (PangoGlyphString *glyphs)
  * @text: the text corresponding to the glyphs
  * @length: the length of @text, in bytes
  * @embedding_level: the embedding level of the string
- * @logical_widths: an array whose length is g_utf8_strlen (text, length)
+ * @logical_widths: an array whose length is the number of characters in
+ *                  text (equal to g_utf8_strlen (text, length) unless
+ *                  text has NUL bytes)
  *                  to be filled in with the resulting character widths.
  *
  * Given a #PangoGlyphString resulting from pango_shape() and the corresponding
@@ -337,7 +339,7 @@ pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
 {
   /* Build a PangoGlyphItem so we can use PangoGlyphItemIter.
    * This API should have been made to take a PangoGlyphItem... */
-  PangoItem item = {0, length, g_utf8_strlen (text, length),
+  PangoItem item = {0, length, pango_utf8_strlen (text, length),
 		    {NULL, NULL, NULL,
 		     embedding_level, PANGO_GRAVITY_AUTO, 0,
 		     PANGO_SCRIPT_UNKNOWN, NULL,
diff --git a/pango/pango-engine.c b/pango/pango-engine.c
index 2891762..974e2d5 100644
--- a/pango/pango-engine.c
+++ b/pango/pango-engine.c
@@ -107,7 +107,7 @@ fallback_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
   int cluster = 0;
   int i;
 
-  n_chars = text ? g_utf8_strlen (text, length) : 0;
+  n_chars = text ? pango_utf8_strlen (text, length) : 0;
 
   pango_glyph_string_set_size (glyphs, n_chars);
 
diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c
index 9a90a4c..8d19d94 100644
--- a/pango/pango-glyph-item.c
+++ b/pango/pango-glyph-item.c
@@ -300,7 +300,7 @@ pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
 	  if (glyphs->log_clusters[glyph_index] != cluster)
 	    {
 	      iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
-	      iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
+	      iter->end_char += pango_utf8_strlen (iter->text + iter->start_index,
 					       iter->end_index - iter->start_index);
 	      break;
 	    }
@@ -323,7 +323,7 @@ pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
 	  if (glyphs->log_clusters[glyph_index] != cluster)
 	    {
 	      iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
-	      iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
+	      iter->end_char += pango_utf8_strlen (iter->text + iter->start_index,
 					       iter->end_index - iter->start_index);
 	      break;
 	    }
@@ -388,7 +388,7 @@ pango_glyph_item_iter_prev_cluster (PangoGlyphItemIter *iter)
 	    {
 	      glyph_index++;
 	      iter->start_index = item->offset + glyphs->log_clusters[glyph_index];
-	      iter->start_char -= g_utf8_strlen (iter->text + iter->start_index,
+	      iter->start_char -= pango_utf8_strlen (iter->text + iter->start_index,
 						 iter->end_index - iter->start_index);
 	      break;
 	    }
@@ -412,7 +412,7 @@ pango_glyph_item_iter_prev_cluster (PangoGlyphItemIter *iter)
 	    {
 	      glyph_index--;
 	      iter->start_index = item->offset + glyphs->log_clusters[glyph_index];
-	      iter->start_char -= g_utf8_strlen (iter->text + iter->start_index,
+	      iter->start_char -= pango_utf8_strlen (iter->text + iter->start_index,
 						 iter->end_index - iter->start_index);
 	      break;
 	    }
diff --git a/pango/pango-impl-utils.h b/pango/pango-impl-utils.h
index a04d424..3ef3a0c 100644
--- a/pango/pango-impl-utils.h
+++ b/pango/pango-impl-utils.h
@@ -122,6 +122,33 @@ pango_utf8_strwidth (const gchar *p)
   return len;
 }
 
+/* Glib's g_utf8_strlen() is broken and stops at embedded NUL's.
+ * Wrap it here. */
+static G_GNUC_UNUSED glong
+pango_utf8_strlen (const gchar *p, gssize max)
+{
+  glong len = 0;
+  const gchar *start = p;
+  g_return_val_if_fail (p != NULL || max == 0, 0);
+
+  if (max <= 0)
+    return g_utf8_strlen (p, max);
+
+  p = g_utf8_next_char (p);
+  while (p - start < max)
+    {
+      ++len;
+      p = g_utf8_next_char (p);
+    }
+
+  /* only do the last len increment if we got a complete
+   * char (don't count partial chars)
+   */
+  if (p - start <= max)
+    ++len;
+
+  return len;
+}
 
 G_END_DECLS
 
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 4326eb4..23c5dbf 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -1084,7 +1084,7 @@ pango_layout_set_text (PangoLayout *layout,
     /* TODO: Write out the beginning excerpt of text? */
     g_warning ("Invalid UTF-8 string passed to pango_layout_set_text()");
 
-  layout->n_chars = g_utf8_strlen (layout->text, -1);
+  layout->n_chars = pango_utf8_strlen (layout->text, -1);
 
   pango_layout_clear_lines (layout);
 
@@ -1737,7 +1737,7 @@ pango_layout_move_cursor_visually (PangoLayout *layout,
     old_index = g_utf8_next_char (layout->text + old_index) - layout->text;
 
   log2vis_map = pango_layout_line_get_log2vis_map (line, strong);
-  n_vis = g_utf8_strlen (layout->text + line->start_index, line->length);
+  n_vis = pango_utf8_strlen (layout->text + line->start_index, line->length);
 
   /* Clamp old_index to fit on the line */
   if (old_index > (line->start_index + line->length))
@@ -1793,7 +1793,7 @@ pango_layout_move_cursor_visually (PangoLayout *layout,
 	  paragraph_boundary = (line->start_index != old_index);
 	}
 
-      n_vis = g_utf8_strlen (layout->text + line->start_index, line->length);
+      n_vis = pango_utf8_strlen (layout->text + line->start_index, line->length);
       start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
 
       if (vis_pos == 0 && direction < 0)
@@ -2052,7 +2052,7 @@ pango_layout_line_get_vis2log_map (PangoLayoutLine *line,
   int n_chars;
 
   pango_layout_line_get_range (line, &start, &end);
-  n_chars = g_utf8_strlen (start, end - start);
+  n_chars = pango_utf8_strlen (start, end - start);
 
   result = g_new (int, n_chars + 1);
 
@@ -2139,7 +2139,7 @@ pango_layout_line_get_log2vis_map (PangoLayoutLine *line,
   int n_chars;
 
   pango_layout_line_get_range (line, &start, &end);
-  n_chars = g_utf8_strlen (start, end - start);
+  n_chars = pango_utf8_strlen (start, end - start);
   result = g_new0 (int, end - start + 1);
 
   reverse_map = pango_layout_line_get_vis2log_map (line, strong);
@@ -3635,7 +3635,7 @@ get_items_log_attrs (const char   *text,
       /* Break the paragraph delimiters with the last item */
       if (items->next == NULL)
 	{
-	  tmp_item.num_chars += g_utf8_strlen (text + index + tmp_item.length, para_delimiter_len);
+	  tmp_item.num_chars += pango_utf8_strlen (text + index + tmp_item.length, para_delimiter_len);
 	  tmp_item.length += para_delimiter_len;
 	}
 
@@ -3874,7 +3874,7 @@ pango_layout_check_lines (PangoLayout *layout)
 	done = TRUE;
 
       if (!done)
-	start_offset += g_utf8_strlen (start, (end - start) + delim_len);
+	start_offset += pango_utf8_strlen (start, (end - start) + delim_len);
 
       start = end + delim_len;
     }
@@ -5362,7 +5362,7 @@ update_cluster (PangoLayoutIter *iter,
     }
 
   cluster_text = iter->layout->text + iter->run->item->offset + cluster_start_index;
-  iter->cluster_num_chars = g_utf8_strlen (cluster_text, cluster_length);
+  iter->cluster_num_chars = pango_utf8_strlen (cluster_text, cluster_length);
 
   if (iter->ltr)
     iter->index = cluster_text - iter->layout->text;



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