Skip to content

Commit

Permalink
try to calculate character width
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Otterbein committed Dec 15, 2024
1 parent 6a23803 commit 5c98449
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 24 deletions.
3 changes: 3 additions & 0 deletions src/libutil/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ deps_private += cpuid
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json

cxx = meson.get_compiler('cpp')
cxx.has_header('widechar_width.h', required : true)

config_h = configure_file(
configuration : configdata,
output : 'config-util.hh',
Expand Down
18 changes: 18 additions & 0 deletions src/libutil/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@

let
inherit (lib) fileset;
widecharwidth = stdenv.mkDerivation {
name = "widecharwidth";
dontUnpack = true;
dontStrip = true;
installPhase = ''
mkdir -p $out/include
cp $src $out/include/widechar_width.h
'';
src = builtins.fetchurl {
url = "https://raw.githubusercontent.com/ridiculousfish/widecharwidth/533e50efb0b9b122a08f2273337dbf6b44b03cc7/widechar_width.h";
sha256 = "sha256:1kcqj74i788byz9gp4qz34j4q44jvgpkr9m3gnhvkalrz4cvv2jh";
};
};
in

mkMesonLibrary (finalAttrs: {
Expand All @@ -38,6 +51,10 @@ mkMesonLibrary (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];

nativeBuildInputs = [
widecharwidth
];

buildInputs = [
brotli
libsodium
Expand Down Expand Up @@ -65,6 +82,7 @@ mkMesonLibrary (finalAttrs: {
mesonFlags = [
(lib.mesonEnable "cpuid" stdenv.hostPlatform.isx86_64)
];
NIX_CFLAGS_COMPILE = "-I${widecharwidth}/include";

env = {
# Needed for Meson to find Boost.
Expand Down
83 changes: 59 additions & 24 deletions src/libutil/terminal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,58 @@
# include <sys/ioctl.h>
#endif
#include <unistd.h>
#include <widechar_width.h>

namespace {

inline std::pair<int, size_t> charWidthUTF8Helper(std::string_view s, bool printableASCII = false)
{
size_t bytes = 1;
uint32_t ch = 0;
uint32_t max = 1U << 7;
if ((s[0] & 0x80) == 0) {
if (printableASCII) {
return {bytes, bytes}; // assume printable ASCII character
} else {
ch = s[0];
}
} else if ((s[0] & 0xe0) == 0xc0) {
ch = s[0] & 0x1f;
bytes = 2;
max = 1U << 11;
} else if ((s[0] & 0xf0) == 0xe0) {
ch = s[0] & 0x0f;
bytes = 3;
max = 1U << 16;
} else if ((s[0] & 0xf8) == 0xf0) {
ch = s[0] & 0x07;
bytes = 4;
max = 0x110000U;
} else {
return {bytes, bytes}; // invalid UTF-8 start byte
}
size_t len = s.size();
for (size_t i = 1; i < bytes; i++) {
if (i < len && s[i] & 0x80) {
ch = (ch << 6) | (s[i] & 0x3f);
} else {
return {i, i}; // invalid UTF-8 encoding; assume one character per byte
}
}
int width = bytes; // in case of overlong encoding
if (ch < max) {
width = widechar_wcwidth(ch);
if (width == widechar_ambiguous) {
width = 1; // just a guess...
} else if (width == widechar_widened_in_9) {
width = 2;
}
width = std::max(width, 0);
}
return {width, bytes};
}

}

namespace nix {

Expand Down Expand Up @@ -72,35 +124,18 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w
i++;

else {
w++;
// Copy one UTF-8 character.
if ((*i & 0xe0) == 0xc0) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++;
} else if ((*i & 0xf0) == 0xe0) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++;
}
} else if ((*i & 0xf8) == 0xf0) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) {
t += *i++;
if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++;
}
}
} else
t += *i++;
auto [chWidth, bytes] = charWidthUTF8Helper({i, s.end()}, true);
w += chWidth;
auto n = i + bytes;
if (w <= (size_t) width) {
t += {i, n};
}
i = n;
}
}

return t;
}


//////////////////////////////////////////////////////////////////////

static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}};
Expand Down

0 comments on commit 5c98449

Please sign in to comment.