xed-document-output-stream: Factor out validate_and_insert method

This commit is contained in:
JosephMcc 2017-01-19 03:45:06 -08:00
parent e3e9566570
commit 176dac188b
1 changed files with 79 additions and 46 deletions

View File

@ -496,6 +496,65 @@ xed_document_output_stream_get_num_fallbacks (XedDocumentOutputStream *stream)
return g_charset_converter_get_num_fallbacks (stream->priv->charset_conv) != 0; return g_charset_converter_get_num_fallbacks (stream->priv->charset_conv) != 0;
} }
static gboolean
validate_and_insert (XedDocumentOutputStream *stream,
const gchar *buffer,
gsize count)
{
const gchar *end;
gsize nvalid;
gboolean valid;
gsize len;
len = count;
/* validate */
valid = g_utf8_validate (buffer, len, &end);
nvalid = end - buffer;
if (!valid)
{
gsize remainder;
remainder = len - nvalid;
if ((remainder < MAX_UNICHAR_LEN) && (g_utf8_get_char_validated (buffer + nvalid, remainder) == (gunichar)-2))
{
stream->priv->buffer = g_strndup (end, remainder);
stream->priv->buflen = remainder;
len -= remainder;
}
else
{
return FALSE;
}
}
else
{
gchar *ptr;
/* Note: this is a workaround for a 'bug' in GtkTextBuffer where
inserting first a \r and then in a second insert, a \n,
will result in two lines being added instead of a single
one */
ptr = g_utf8_find_prev_char (buffer, buffer + len);
if (ptr && *ptr == '\r' && ptr - buffer == len - 1)
{
stream->priv->buffer = g_new (gchar, 1);
stream->priv->buffer[0] = '\r';
stream->priv->buflen = 1;
--len;
}
}
gtk_text_buffer_insert (GTK_TEXT_BUFFER (stream->priv->doc), &stream->priv->pos, buffer, len);
return TRUE;
}
/* If the last char is a newline, remove it from the buffer (otherwise /* If the last char is a newline, remove it from the buffer (otherwise
GtkTextView shows it as an empty line). See bug #324942. */ GtkTextView shows it as an empty line). See bug #324942. */
static void static void
@ -542,10 +601,10 @@ xed_document_output_stream_write (GOutputStream *stream,
gchar *text; gchar *text;
gsize len; gsize len;
gboolean freetext = FALSE; gboolean freetext = FALSE;
const gchar *end; // const gchar *end;
gboolean valid; // gboolean valid;
gsize nvalid; // gsize nvalid;
gsize remainder; // gsize remainder;
if (g_cancellable_set_error_if_cancelled (cancellable, error)) if (g_cancellable_set_error_if_cancelled (cancellable, error))
{ {
@ -654,19 +713,21 @@ xed_document_output_stream_write (GOutputStream *stream,
/* If we reached here is because we need to convert the text so, we /* If we reached here is because we need to convert the text so, we
convert it with the charset converter */ convert it with the charset converter */
conv_text = g_convert_with_iconv (text, conv_text = g_convert_with_iconv (text,
len, len,
ostream->priv->iconv, ostream->priv->iconv,
&conv_read, &conv_read,
&conv_written, &conv_written,
&err); &err);
if (freetext) if (freetext)
{ {
g_free (text); g_free (text);
} }
if (err != NULL) if (err != NULL)
{ {
gsize remainder;
remainder = len - conv_read; remainder = len - conv_read;
/* Store the partial char for the next conversion */ /* Store the partial char for the next conversion */
@ -694,49 +755,21 @@ xed_document_output_stream_write (GOutputStream *stream,
} }
/* validate */ if (!validate_and_insert (ostream, text, len))
valid = g_utf8_validate (text, len, &end);
nvalid = end - text;
/* Avoid keeping a CRLF across two buffers. */
if (valid && len > 1 && end[-1] == '\r')
{ {
valid = FALSE; /* TODO: we could escape invalid text and tag it in red
end--; * and make the doc readonly.
} */
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, _("Invalid UTF-8 sequence in input"));
if (!valid) if (freetext)
{
// gsize nvalid = end - text;
remainder = len - nvalid;
gunichar ch;
if ((remainder < MAX_UNICHAR_LEN) &&
((ch = g_utf8_get_char_validated (text + nvalid, remainder)) == (gunichar)-2 ||
ch == (gunichar)'\r'))
{ {
ostream->priv->buffer = g_strndup (end, remainder); g_free (text);
ostream->priv->buflen = remainder;
len -= remainder;
} }
else
{
/* TODO: we could escape invalid text and tag it in red
* and make the doc readonly.
*/
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, _("Invalid UTF-8 sequence in input"));
if (freetext) return -1;
{
g_free (text);
}
return -1;
}
} }
gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc), &ostream->priv->pos, text, len);
if (freetext) if (freetext)
{ {
g_free (text); g_free (text);