I managed to hack together a fix for the issue. It wasn't as
straightforward as I was expecting it to be. I've attached a
preliminary version of the patch here for a review.

Please review the patch and test it out to ensure that it works
correctly. I'll clean up the variable names and write the relevant
ChangeLog entries later and submit the final patch.

On Thu, Sep 4, 2014 at 10:34 PM, Giuseppe Scrivano <[email protected]> wrote:
> Darshit Shah <[email protected]> writes:
>
>> Yes, I guess I'm looking for UTF-8 strings, because other character
>> encodings wouldn't create this problem, (I think?)
>> I'll look at the Wiki page again and see of GNULib has anything, Right
>> now, I'm trying to implement a solution based on wide characters
>> through wchar.h but I don't like the code I've written. I's prefer
>> something more elegant and efficient.
>
> have you had a look at the mbiter module of gnulib?  Its documentation
> says that you can turn:
>
>       char *iter;
>       for (iter = buf; iter < buf + buflen; iter++)
>         {
>           do_something (*iter);
>         }
>
> into:
>
>       mbi_iterator_t iter;
>       for (mbi_init (iter, buf, buflen); mbi_avail (iter); mbi_advance
>       (iter))
>         {
>           do_something (mbi_cur_ptr (iter), mb_len (mbi_cur (iter)));
>         }
>
>
> and seems quite straightforward to me.
>
> Regards,
> Giuseppe



-- 
Thanking You,
Darshit Shah
From b6b65a05c03b34b4b7064b2153b6ddf851100044 Mon Sep 17 00:00:00 2001
From: Darshit Shah <[email protected]>
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  <[email protected]>
+
+	* bootstrap.conf: Add GNULib module mbiter
+
 2014-07-25  Darshit Shah  <[email protected]>
 
 	* .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 <unistd.h>
 #include <signal.h>
 #include <wchar.h>
+#include <mbiter.h>
 
 #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

Reply via email to