From b6b65a05c03b34b4b7064b2153b6ddf851100044 Mon Sep 17 00:00:00 2001 From: Darshit Shah Date: Fri, 12 Sep 2014 13:33:20 +0530 Subject: [PATCH] Handle multibyte characters in progressbar This commit fixes a bug in the progressbar implementation wherein filenames with multibyte characters were not handled correctly. --- ChangeLog | 4 ++++ bootstrap.conf | 1 + src/progress.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b693be..c4e7809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-09-12 Darshit Shah + + * bootstrap.conf: Add GNULib module mbiter + 2014-07-25 Darshit Shah * .gitignore: Add a gitignore file for the project. diff --git a/bootstrap.conf b/bootstrap.conf index 516bbb6..bbfb38f 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -49,6 +49,7 @@ iconv iconv-h listen maintainer-makefile +mbiter mbtowc mkdir mkstemp diff --git a/src/progress.c b/src/progress.c index e9182cc..86cdbce 100644 --- a/src/progress.c +++ b/src/progress.c @@ -37,6 +37,7 @@ as that of the covered work. */ #include #include #include +#include #include "progress.h" #include "utils.h" @@ -812,8 +813,37 @@ count_cols (const char *mbs) } return cols; } + +static int +cols_to_bytes (const char *mbs, const int cols, int *ncols) +{ + int p_cols = 0, bytes = 0; + mbchar_t mbc; + mbi_iterator_t iter; + mbi_init (iter, mbs, strlen(mbs)); + while (p_cols < cols && mbi_avail (iter)) + { + mbc = mbi_cur (iter); + p_cols += mb_width (mbc); + /* The multibyte character has exceeded the total number of columns we + * have available. The remaining bytes will be padded with a space. */ + if (p_cols > cols) + { + p_cols -= mb_width (mbc); + break; + } + bytes += mb_len (mbc); + mbi_advance (iter); + } + *ncols = p_cols; + return bytes; +} #else # define count_cols(mbs) ((int)(strlen(mbs))) +# define cols_to_bytes(mbs, cols, *ncols) do { \ + *ncols = cols; \ + bytes = cols; \ +}while (0) #endif static const char * @@ -885,6 +915,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) struct bar_progress_hist *hist = &bp->hist; int orig_filename_len = strlen (bp->f_download); + int orig_filename_cols = count_cols (bp->f_download); /* The progress bar should look like this: file xx% [=======> ] nnn.nnK 12.34KB/s eta 36m 51s @@ -935,13 +966,20 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) else { int offset; + int offset_bytes, offset_start, col; + int *cols_ret = &col; if (((orig_filename_len > MAX_FILENAME_LEN) && !opt.noscroll) && !done) - offset = ((int) bp->tick) % (orig_filename_len - MAX_FILENAME_LEN); + offset = ((int) bp->tick) % (orig_filename_cols - MAX_FILENAME_LEN); else offset = 0; - memcpy (p, bp->f_download + offset, MAX_FILENAME_LEN); - p += MAX_FILENAME_LEN; + offset_start = cols_to_bytes (bp->f_download, offset, cols_ret); + offset_bytes = cols_to_bytes (bp->f_download + offset_start, MAX_FILENAME_LEN, cols_ret); + memcpy (p, bp->f_download + offset_start, offset_bytes); + p += offset_bytes; + int padding = MAX_FILENAME_LEN - *cols_ret; + for (;padding;padding--) + *p++ = ' '; *p++ = ' '; } -- 2.1.0