summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2019-11-25 20:11:19 +0000
committerJulian Andres Klode <jak@debian.org>2019-11-25 20:11:19 +0000
commit6e2500016c7a07725a05f70d084fd572cd628575 (patch)
tree3d8f6ece94bf89c4ed7aa57352fe98a9d4eb3ffb
parent83f2732b10498c4a3abdfbc072da63803557ce9b (diff)
parent2497198e9599a6a8d4d0ad08627bcfc7ea49c644 (diff)
downloadapt-6e2500016c7a07725a05f70d084fd572cd628575.tar.gz
Merge branch 'fix-progressbar-size' into 'master'
Fix progress bar width for multibyte charsets See merge request apt-team/apt!81
-rw-r--r--apt-pkg/contrib/strutl.cc48
-rw-r--r--apt-pkg/contrib/strutl.h2
-rw-r--r--apt-pkg/install-progress.cc2
3 files changed, 51 insertions, 1 deletions
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 860e3fe47..70befdc48 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -40,6 +40,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <wchar.h>
#include <apti18n.h>
/*}}}*/
@@ -96,6 +97,53 @@ std::string Join(std::vector<std::string> list, const std::string &sep)
return oss.str();
}
+// Returns string display length honoring multi-byte characters
+size_t DisplayLength(StringView str)
+{
+ size_t len = 0;
+
+ const char *p = str.data();
+ const char *const end = str.end();
+
+ mbstate_t state{};
+ while (p < end)
+ {
+ wchar_t wch;
+ size_t res = mbrtowc(&wch, p, end - p, &state);
+ switch (res)
+ {
+ case 0:
+ // Null wide character (i.e. L'\0') - stop
+ p = end;
+ break;
+
+ case static_cast<size_t>(-1):
+ // Byte sequence is invalid. Assume that it's
+ // a single-byte single-width character.
+ len += 1;
+ p += 1;
+
+ // state is undefined in this case - reset it
+ state = {};
+
+ break;
+
+ case static_cast<size_t>(-2):
+ // Byte sequence is too short. Assume that it's
+ // an incomplete single-width character and stop.
+ len += 1;
+ p = end;
+ break;
+
+ default:
+ len += wcwidth(wch);
+ p += res;
+ }
+ }
+
+ return len;
+}
+
}
}
/*}}}*/
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index fc02357a8..738480402 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -33,6 +33,8 @@ namespace APT {
bool Endswith(const std::string &s, const std::string &ending);
bool Startswith(const std::string &s, const std::string &starting);
std::string Join(std::vector<std::string> list, const std::string &sep);
+ // Returns string display length honoring multi-byte characters
+ size_t DisplayLength(StringView str);
}
}
diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc
index 2e8fac236..aadd28e51 100644
--- a/apt-pkg/install-progress.cc
+++ b/apt-pkg/install-progress.cc
@@ -382,7 +382,7 @@ bool PackageManagerFancy::DrawStatusLine()
if (_config->FindB("Dpkg::Progress-Fancy::Progress-Bar", true))
{
int padding = 4;
- auto const progressbar_size = size.columns - padding - progress_str.size();
+ auto const progressbar_size = size.columns - padding - String::DisplayLength(progress_str);
auto const current_percent = percentage / 100.0f;
std::cout << " "
<< GetTextProgressStr(current_percent, progressbar_size)