summaryrefslogtreecommitdiff
path: root/diff.c
diff options
context:
space:
mode:
authorJunio C Hamano <junio@pobox.com>2008-01-02 01:50:11 -0800
committerJunio C Hamano <gitster@pobox.com>2008-01-06 22:44:44 -0800
commit23707811c56a7756cbd6188e510f0a486c35c929 (patch)
tree013ac44e706c265e2543c5afca53dad4afefe591 /diff.c
parent44b25b872f926ba92bae9ddf2495e7f59d0c96e2 (diff)
downloadgit-23707811c56a7756cbd6188e510f0a486c35c929.tar.gz
diff: do not chomp hunk-header in the middle of a character
We truncate hunk-header line at 80 bytes, but that 80th byte could be in the middle of a character, which is bad. This uses pick_one_utf8_char() function to make sure we do not cut a character in the middle. This assumes that the internal representation of the text is UTF-8. This needs to be extended in the future but the optimal direction has not been decided yet. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'diff.c')
-rw-r--r--diff.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/diff.c b/diff.c
index 2c78d74a42..b18c140e3d 100644
--- a/diff.c
+++ b/diff.c
@@ -10,6 +10,7 @@
#include "color.h"
#include "attr.h"
#include "run-command.h"
+#include "utf8.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -469,10 +470,13 @@ static void diff_words_show(struct diff_words_data *diff_words)
}
}
+typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
+
struct emit_callback {
struct xdiff_emit_state xm;
int nparents, color_diff;
unsigned ws_rule;
+ sane_truncate_fn truncate;
const char **label_path;
struct diff_words_data *diff_words;
int *found_changesp;
@@ -525,6 +529,24 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
}
}
+static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
+{
+ const char *cp;
+ unsigned long allot;
+ size_t l = len;
+
+ if (ecb->truncate)
+ return ecb->truncate(line, len);
+ cp = line;
+ allot = l;
+ while (0 < l) {
+ (void) utf8_width(&cp, &l);
+ if (!cp)
+ break; /* truncated in the middle? */
+ }
+ return allot - l;
+}
+
static void fn_out_consume(void *priv, char *line, unsigned long len)
{
int i;
@@ -555,8 +577,11 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
;
if (2 <= i && i < len && line[i] == ' ') {
ecbdata->nparents = i - 1;
+ len = sane_truncate_line(ecbdata, line, len);
emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
reset, line, len);
+ if (line[len-1] != '\n')
+ putchar('\n');
return;
}