@@ -2624,7 +2624,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2624
2624
continue ;
2625
2625
}
2626
2626
fill_print_name (file );
2627
- len = strlen (file -> print_name );
2627
+ len = utf8_strwidth (file -> print_name );
2628
2628
if (max_len < len )
2629
2629
max_len = len ;
2630
2630
@@ -2677,6 +2677,11 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2677
2677
* making the line longer than the maximum width.
2678
2678
*/
2679
2679
2680
+ /*
2681
+ * NEEDSWORK: line_prefix is often used for "log --graph" output
2682
+ * and contains ANSI-colored string. utf8_strnwidth() should be
2683
+ * used to correctly count the display width instead of strlen().
2684
+ */
2680
2685
if (options -> stat_width == -1 )
2681
2686
width = term_columns () - strlen (line_prefix );
2682
2687
else
@@ -2738,7 +2743,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2738
2743
char * name = file -> print_name ;
2739
2744
uintmax_t added = file -> added ;
2740
2745
uintmax_t deleted = file -> deleted ;
2741
- int name_len ;
2746
+ int name_len , padding ;
2742
2747
2743
2748
if (!file -> is_interesting && (added + deleted == 0 ))
2744
2749
continue ;
@@ -2747,20 +2752,34 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2747
2752
* "scale" the filename
2748
2753
*/
2749
2754
len = name_width ;
2750
- name_len = strlen (name );
2755
+ name_len = utf8_strwidth (name );
2751
2756
if (name_width < name_len ) {
2752
2757
char * slash ;
2753
2758
prefix = "..." ;
2754
2759
len -= 3 ;
2760
+ /*
2761
+ * NEEDSWORK: (name_len - len) counts the display
2762
+ * width, which would be shorter than the byte
2763
+ * length of the corresponding substring.
2764
+ * Advancing "name" by that number of bytes does
2765
+ * *NOT* skip over that many columns, so it is
2766
+ * very likely that chomping the pathname at the
2767
+ * slash we will find starting from "name" will
2768
+ * leave the resulting string still too long.
2769
+ */
2755
2770
name += name_len - len ;
2756
2771
slash = strchr (name , '/' );
2757
2772
if (slash )
2758
2773
name = slash ;
2759
2774
}
2775
+ padding = len - utf8_strwidth (name );
2776
+ if (padding < 0 )
2777
+ padding = 0 ;
2760
2778
2761
2779
if (file -> is_binary ) {
2762
- strbuf_addf (& out , " %s%-*s |" , prefix , len , name );
2763
- strbuf_addf (& out , " %*s" , number_width , "Bin" );
2780
+ strbuf_addf (& out , " %s%s%*s | %*s" ,
2781
+ prefix , name , padding , "" ,
2782
+ number_width , "Bin" );
2764
2783
if (!added && !deleted ) {
2765
2784
strbuf_addch (& out , '\n' );
2766
2785
emit_diff_symbol (options , DIFF_SYMBOL_STATS_LINE ,
@@ -2780,8 +2799,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2780
2799
continue ;
2781
2800
}
2782
2801
else if (file -> is_unmerged ) {
2783
- strbuf_addf (& out , " %s%-*s |" , prefix , len , name );
2784
- strbuf_addstr (& out , " Unmerged\n" );
2802
+ strbuf_addf (& out , " %s%s%*s | %*s" ,
2803
+ prefix , name , padding , "" ,
2804
+ number_width , "Unmerged" );
2785
2805
emit_diff_symbol (options , DIFF_SYMBOL_STATS_LINE ,
2786
2806
out .buf , out .len , 0 );
2787
2807
strbuf_reset (& out );
@@ -2807,10 +2827,10 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
2807
2827
add = total - del ;
2808
2828
}
2809
2829
}
2810
- strbuf_addf (& out , " %s%- *s |" , prefix , len , name );
2811
- strbuf_addf ( & out , " %*" PRIuMAX "%s " ,
2812
- number_width , added + deleted ,
2813
- added + deleted ? " " : "" );
2830
+ strbuf_addf (& out , " %s%s% *s | %*" PRIuMAX "%s" ,
2831
+ prefix , name , padding , " " ,
2832
+ number_width , added + deleted ,
2833
+ added + deleted ? " " : "" );
2814
2834
show_graph (& out , '+' , add , add_c , reset );
2815
2835
show_graph (& out , '-' , del , del_c , reset );
2816
2836
strbuf_addch (& out , '\n' );
0 commit comments