From 67052645e6afcd7f72ef852c99ee88897d2022da Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Jul 2009 13:59:20 -0400 Subject: Handle NUL in text in places that g_utf8_strlen () was used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 c1707456..b17dc606 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 #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 3a39a789..1c8aa241 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 2e3a9f80..9e7c5f85 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 2891762a..974e2d5a 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 9a90a4ca..8d19d94a 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 a04d4241..3ef3a0c4 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 4326eb47..23c5dbfc 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; -- cgit v1.2.1