From: Ben Pfaff Date: Sun, 6 May 2012 15:06:57 +0000 (-0700) Subject: gui: Make lex_gtk_text_buffer_read() count bytes, not characters. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=5841c349770a82f091e77dfe90fd68eee6032f66 gui: Make lex_gtk_text_buffer_read() count bytes, not characters. The N parameter to lex_gtk_text_buffer_read() is a count of bytes, but the implementation treated it as characters. Also fixes a memory leak, since gtk_text_iter_get_text()'s caller is responsible for freeing the memory that it returns. Reported by Alle . First investigated by John Darrington . Reviewed by John Darrington . --- diff --git a/src/ui/gui/psppire-lex-reader.c b/src/ui/gui/psppire-lex-reader.c index ae043b0b7b..d8e53c4461 100644 --- a/src/ui/gui/psppire-lex-reader.c +++ b/src/ui/gui/psppire-lex-reader.c @@ -26,15 +26,24 @@ #include "libpspp/cast.h" +#include "gl/minmax.h" + static const struct lex_reader_class lex_gtk_text_buffer_reader_class ; struct lex_gtk_text_buffer_reader { struct lex_reader reader; + + /* The GtkTextBuffer from which we are reading. */ GtkTextBuffer *buffer; GtkTextIter start; GtkTextIter stop; + + /* Text pulled from part of the GtkTextBuffer. */ + gchar *part; + gsize part_len; /* Number of bytes in 'part'. */ + gsize part_ofs; /* Current offset into 'part'. */ }; static struct lex_gtk_text_buffer_reader * @@ -57,6 +66,10 @@ lex_reader_for_gtk_text_buffer (GtkTextBuffer *buffer, GtkTextIter start, GtkTex r->start = start; r->stop = stop; + r->part = NULL; + r->part_len = 0; + r->part_ofs = 0; + return &r->reader; } @@ -66,26 +79,38 @@ lex_gtk_text_buffer_read (struct lex_reader *r_, char *buf, size_t n, enum prompt_style prompt_style UNUSED) { struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_); - int n_chars = n; - char *s; + gsize chunk; + + if (r->part_ofs == r->part_len) + { + /* Read up to N characters into r->part. N characters might be more than + N bytes, but that's OK: we'll just buffer up some of those bytes for + the next read. */ + int n_chars = n; + + GtkTextIter iter = r->start ; + + int offset = gtk_text_iter_get_offset (&iter); + int end_offset = gtk_text_iter_get_offset (&r->stop); - GtkTextIter iter = r->start ; - - int offset = gtk_text_iter_get_offset (&iter); - int end_offset = gtk_text_iter_get_offset (&r->stop); + if ( end_offset - offset < n) + n_chars = end_offset - offset; - if ( end_offset - offset < n) - n_chars = end_offset - offset; - - gtk_text_iter_set_offset (&iter, offset + n_chars); + gtk_text_iter_set_offset (&iter, offset + n_chars); - s = gtk_text_iter_get_text (&r->start, &iter); + g_free (r->part); + r->part = gtk_text_iter_get_text (&r->start, &iter); + r->part_len = strlen (r->part); + r->part_ofs = 0; - strncpy (buf, s, n_chars); + r->start = iter; + } - r->start = iter; + chunk = MIN (r->part_len - r->part_ofs, n); + memcpy (buf, r->part + r->part_ofs, chunk); + r->part_ofs += chunk; - return strlen (s); + return chunk; } @@ -96,6 +121,7 @@ lex_gtk_text_buffer_close (struct lex_reader *r_) struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_); g_object_unref (r->buffer); + g_free (r->part); }