You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/07/05 23:42:58 UTC
svn commit: r1357948 - /subversion/trunk/subversion/svn/file-merge.c
Author: stsp
Date: Thu Jul 5 21:42:58 2012
New Revision: 1357948
URL: http://svn.apache.org/viewvc?rev=1357948&view=rev
Log:
Be more careful when trimming lines for display in the internal merge tool.
Convert lines to UTF-8 for internal handling, and make sure not to display
an invalid UTF-8 string.
We're still missing a way of determining the actual display width of
the string, i.e. the of equivalent of wcswidth(). However, not writing
invalid UTF-8 is already an improvement.
* subversion/svn/file-merge.c
(prepare_line_for_display): When trimming lines, take care not to produce
invalid UTF-8. Introduce local variable 'width' for clarity.
(merge_chunks): Always convert lines to UTF-8 before display.
Modified:
subversion/trunk/subversion/svn/file-merge.c
Modified: subversion/trunk/subversion/svn/file-merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/file-merge.c?rev=1357948&r1=1357947&r2=1357948&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/file-merge.c (original)
+++ subversion/trunk/subversion/svn/file-merge.c Thu Jul 5 21:42:58 2012
@@ -29,10 +29,12 @@
#include "svn_error.h"
#include "svn_pools.h"
#include "svn_io.h"
+#include "svn_utf.h"
#include "cl.h"
#include "svn_private_config.h"
+#include "private/svn_utf_private.h"
#include "private/svn_dep_compat.h"
/* Baton for functions in this file which implement svn_diff_output_fns_t. */
@@ -365,12 +367,14 @@ read_diff_chunk(apr_array_header_t **lin
#define MAX_LINE_DISPLAY_LEN ((80 / 2) - 4)
/* Prepare LINE for display, pruning or extending it to MAX_LINE_DISPLAY_LEN
- * characters, and stripping the EOL marker, if any. */
+ * characters, and stripping the EOL marker, if any.
+ * This function assumes that the data in LINE is encoded in UTF-8. */
static const char *
prepare_line_for_display(const char *line, apr_pool_t *result_pool)
{
svn_stringbuf_t *buf = svn_stringbuf_create(line, result_pool);
int max_len = MAX_LINE_DISPLAY_LEN;
+ apr_size_t width;
/* Trim EOL. */
if (buf->len > 2 &&
@@ -384,15 +388,30 @@ prepare_line_for_display(const char *lin
/* Trim further in case line is still too long, or add padding in case
* it is too short. */
- if (buf->len > 0 && ((buf->len - 1) > max_len))
- svn_stringbuf_chop(buf, (buf->len - 1) - max_len);
+ width = buf->len; /* ### assumes width == 1 for all characters */
+ if (width > max_len)
+ {
+ const char *last_valid;
+
+ svn_stringbuf_chop(buf, width - max_len);
+ width = max_len;
+
+ /* Be careful not to invalidate the UTF-8 string by trimming
+ * just part of a character. */
+ last_valid = svn_utf__last_valid(buf->data, buf->len);
+ if (last_valid < buf->data + buf->len)
+ svn_stringbuf_chop(buf, (buf->data + buf->len) - last_valid);
+ }
else
{
- while (buf->len == 0 || ((buf->len - 1) < max_len))
- svn_stringbuf_appendbyte(buf, ' ');
+ while (width == 0 || width < max_len)
+ {
+ svn_stringbuf_appendbyte(buf, ' ');
+ width++;
+ }
}
- SVN_ERR_ASSERT_NO_RETURN((buf->len - 1) == MAX_LINE_DISPLAY_LEN);
+ SVN_ERR_ASSERT_NO_RETURN(width == MAX_LINE_DISPLAY_LEN);
return buf->data;
}
@@ -448,16 +467,28 @@ merge_chunks(apr_array_header_t **merged
svn_pool_clear(iterpool);
if (i < chunk1->nelts)
- line1 = prepare_line_for_display(
- APR_ARRAY_IDX(chunk1, i, svn_stringbuf_t*)->data,
- iterpool);
+ {
+ svn_stringbuf_t *line_utf8;
+
+ SVN_ERR(svn_utf_stringbuf_to_utf8(&line_utf8,
+ APR_ARRAY_IDX(chunk1, i,
+ svn_stringbuf_t*),
+ iterpool));
+ line1 = prepare_line_for_display(line_utf8->data, iterpool);
+ }
else
line1 = prepare_line_for_display("", iterpool);
if (i < chunk2->nelts)
- line2 = prepare_line_for_display(
- APR_ARRAY_IDX(chunk2, i, svn_stringbuf_t*)->data,
- iterpool);
+ {
+ svn_stringbuf_t *line_utf8;
+
+ SVN_ERR(svn_utf_stringbuf_to_utf8(&line_utf8,
+ APR_ARRAY_IDX(chunk2, i,
+ svn_stringbuf_t*),
+ iterpool));
+ line2 = prepare_line_for_display(line_utf8->data, iterpool);
+ }
else
line2 = prepare_line_for_display("", iterpool);