Discussion:
[PATCH] Use wcwidth(1) to calculate character width
Kohei Suzuki
2015-05-17 16:59:11 UTC
Permalink
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has width 1
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).


Kohei Suzuki
***@gmail.com
Nicholas Marriott
2015-05-17 17:08:49 UTC
Permalink
Hi

We can't do this because tmux must know the width of the UTF-8 character
but the locale may not be UTF-8.
Post by Kohei Suzuki
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has width 1
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).
Kohei Suzuki
References
Visible links
From 6324eb0bef76c9ec0d214cefa433efa1493f1845 Mon Sep 17 00:00:00 2001
Date: Mon, 18 May 2015 01:28:29 +0900
Subject: [PATCH] Use wcwidth(1) to calculate character width
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has width 1
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).
---
server.c | 1 -
tmux.h | 1 -
utf8.c | 239 ++-------------------------------------------------------------
3 files changed, 6 insertions(+), 235 deletions(-)
diff --git a/server.c b/server.c
index 738abe1..3c164ff 100644
--- a/server.c
+++ b/server.c
@@ -145,7 +145,6 @@ server_start(int lockfd, char *lockfile)
TAILQ_INIT(&session_groups);
mode_key_init_trees();
key_bindings_init();
- utf8_build();
start_time = time(NULL);
log_debug("socket path %s", socket_path);
diff --git a/tmux.h b/tmux.h
index 054a859..7a6265a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2286,7 +2286,6 @@ void session_group_synchronize1(struct session *, struct session *);
void session_renumber_windows(struct session *);
/* utf8.c */
-void utf8_build(void);
void utf8_set(struct utf8_data *, u_char);
int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char);
diff --git a/utf8.c b/utf8.c
index 76b4846..4a84f20 100644
--- a/utf8.c
+++ b/utf8.c
@@ -20,184 +20,10 @@
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "tmux.h"
-struct utf8_width_entry {
- u_int first;
- u_int last;
-
- int width;
-
- struct utf8_width_entry *left;
- struct utf8_width_entry *right;
-};
-
-/* Random order. Not optimal but it'll do for now... */
-struct utf8_width_entry utf8_width_table[] = {
- { 0x00951, 0x00954, 0, NULL, NULL },
- { 0x00ccc, 0x00ccd, 0, NULL, NULL },
- { 0x0fff9, 0x0fffb, 0, NULL, NULL },
- { 0x20000, 0x2fffd, 2, NULL, NULL },
- { 0x00ebb, 0x00ebc, 0, NULL, NULL },
- { 0x01932, 0x01932, 0, NULL, NULL },
- { 0x0070f, 0x0070f, 0, NULL, NULL },
- { 0x00a70, 0x00a71, 0, NULL, NULL },
- { 0x02329, 0x02329, 2, NULL, NULL },
- { 0x00acd, 0x00acd, 0, NULL, NULL },
- { 0x00ac7, 0x00ac8, 0, NULL, NULL },
- { 0x00a3c, 0x00a3c, 0, NULL, NULL },
- { 0x009cd, 0x009cd, 0, NULL, NULL },
- { 0x00591, 0x005bd, 0, NULL, NULL },
- { 0x01058, 0x01059, 0, NULL, NULL },
- { 0x0ffe0, 0x0ffe6, 2, NULL, NULL },
- { 0x01100, 0x0115f, 2, NULL, NULL },
- { 0x0fe20, 0x0fe23, 0, NULL, NULL },
- { 0x0302a, 0x0302f, 0, NULL, NULL },
- { 0x01772, 0x01773, 0, NULL, NULL },
- { 0x005bf, 0x005bf, 0, NULL, NULL },
- { 0x006ea, 0x006ed, 0, NULL, NULL },
- { 0x00bc0, 0x00bc0, 0, NULL, NULL },
- { 0x00962, 0x00963, 0, NULL, NULL },
- { 0x01732, 0x01734, 0, NULL, NULL },
- { 0x00d41, 0x00d43, 0, NULL, NULL },
- { 0x01b42, 0x01b42, 0, NULL, NULL },
- { 0x00a41, 0x00a42, 0, NULL, NULL },
- { 0x00eb4, 0x00eb9, 0, NULL, NULL },
- { 0x00b01, 0x00b01, 0, NULL, NULL },
- { 0x00e34, 0x00e3a, 0, NULL, NULL },
- { 0x03040, 0x03098, 2, NULL, NULL },
- { 0x0093c, 0x0093c, 0, NULL, NULL },
- { 0x00c4a, 0x00c4d, 0, NULL, NULL },
- { 0x01032, 0x01032, 0, NULL, NULL },
- { 0x00f37, 0x00f37, 0, NULL, NULL },
- { 0x00901, 0x00902, 0, NULL, NULL },
- { 0x00cbf, 0x00cbf, 0, NULL, NULL },
- { 0x0a806, 0x0a806, 0, NULL, NULL },
- { 0x00dd2, 0x00dd4, 0, NULL, NULL },
- { 0x00f71, 0x00f7e, 0, NULL, NULL },
- { 0x01752, 0x01753, 0, NULL, NULL },
- { 0x1d242, 0x1d244, 0, NULL, NULL },
- { 0x005c1, 0x005c2, 0, NULL, NULL },
- { 0x0309b, 0x0a4cf, 2, NULL, NULL },
- { 0xe0100, 0xe01ef, 0, NULL, NULL },
- { 0x017dd, 0x017dd, 0, NULL, NULL },
- { 0x00600, 0x00603, 0, NULL, NULL },
- { 0x009e2, 0x009e3, 0, NULL, NULL },
- { 0x00cc6, 0x00cc6, 0, NULL, NULL },
- { 0x0a80b, 0x0a80b, 0, NULL, NULL },
- { 0x01712, 0x01714, 0, NULL, NULL },
- { 0x00b3c, 0x00b3c, 0, NULL, NULL },
- { 0x01b00, 0x01b03, 0, NULL, NULL },
- { 0x007eb, 0x007f3, 0, NULL, NULL },
- { 0xe0001, 0xe0001, 0, NULL, NULL },
- { 0x1d185, 0x1d18b, 0, NULL, NULL },
- { 0x0feff, 0x0feff, 0, NULL, NULL },
- { 0x01b36, 0x01b3a, 0, NULL, NULL },
- { 0x01920, 0x01922, 0, NULL, NULL },
- { 0x00670, 0x00670, 0, NULL, NULL },
- { 0x00f90, 0x00f97, 0, NULL, NULL },
- { 0x01927, 0x01928, 0, NULL, NULL },
- { 0x0200b, 0x0200f, 0, NULL, NULL },
- { 0x0ff00, 0x0ff60, 2, NULL, NULL },
- { 0x0f900, 0x0faff, 2, NULL, NULL },
- { 0x0fb1e, 0x0fb1e, 0, NULL, NULL },
- { 0x00cbc, 0x00cbc, 0, NULL, NULL },
- { 0x00eb1, 0x00eb1, 0, NULL, NULL },
- { 0x10a38, 0x10a3a, 0, NULL, NULL },
- { 0x007a6, 0x007b0, 0, NULL, NULL },
- { 0x00f80, 0x00f84, 0, NULL, NULL },
- { 0x005c4, 0x005c5, 0, NULL, NULL },
- { 0x0ac00, 0x0d7a3, 2, NULL, NULL },
- { 0x017c9, 0x017d3, 0, NULL, NULL },
- { 0x00d4d, 0x00d4d, 0, NULL, NULL },
- { 0x1d167, 0x1d169, 0, NULL, NULL },
- { 0x01036, 0x01037, 0, NULL, NULL },
- { 0xe0020, 0xe007f, 0, NULL, NULL },
- { 0x00f35, 0x00f35, 0, NULL, NULL },
- { 0x017b4, 0x017b5, 0, NULL, NULL },
- { 0x0206a, 0x0206f, 0, NULL, NULL },
- { 0x00c46, 0x00c48, 0, NULL, NULL },
- { 0x01939, 0x0193b, 0, NULL, NULL },
- { 0x01dc0, 0x01dca, 0, NULL, NULL },
- { 0x10a0c, 0x10a0f, 0, NULL, NULL },
- { 0x0102d, 0x01030, 0, NULL, NULL },
- { 0x017c6, 0x017c6, 0, NULL, NULL },
- { 0x00ec8, 0x00ecd, 0, NULL, NULL },
- { 0x00b41, 0x00b43, 0, NULL, NULL },
- { 0x017b7, 0x017bd, 0, NULL, NULL },
- { 0x1d173, 0x1d182, 0, NULL, NULL },
- { 0x00a47, 0x00a48, 0, NULL, NULL },
- { 0x0232a, 0x0232a, 2, NULL, NULL },
- { 0x01b3c, 0x01b3c, 0, NULL, NULL },
- { 0x10a01, 0x10a03, 0, NULL, NULL },
- { 0x00ae2, 0x00ae3, 0, NULL, NULL },
- { 0x00483, 0x00486, 0, NULL, NULL },
- { 0x0135f, 0x0135f, 0, NULL, NULL },
- { 0x01a17, 0x01a18, 0, NULL, NULL },
- { 0x006e7, 0x006e8, 0, NULL, NULL },
-#ifndef __APPLE__
- { 0x03099, 0x0309a, 0, NULL, NULL },
-#endif
- { 0x00b4d, 0x00b4d, 0, NULL, NULL },
- { 0x00ce2, 0x00ce3, 0, NULL, NULL },
- { 0x00bcd, 0x00bcd, 0, NULL, NULL },
- { 0x00610, 0x00615, 0, NULL, NULL },
- { 0x00f99, 0x00fbc, 0, NULL, NULL },
- { 0x009c1, 0x009c4, 0, NULL, NULL },
- { 0x00730, 0x0074a, 0, NULL, NULL },
- { 0x00300, 0x0036f, 0, NULL, NULL },
- { 0x03030, 0x0303e, 2, NULL, NULL },
- { 0x01b34, 0x01b34, 0, NULL, NULL },
- { 0x1d1aa, 0x1d1ad, 0, NULL, NULL },
- { 0x00dca, 0x00dca, 0, NULL, NULL },
- { 0x006d6, 0x006e4, 0, NULL, NULL },
- { 0x00f86, 0x00f87, 0, NULL, NULL },
- { 0x00b3f, 0x00b3f, 0, NULL, NULL },
- { 0x0fe30, 0x0fe6f, 2, NULL, NULL },
- { 0x01039, 0x01039, 0, NULL, NULL },
- { 0x0094d, 0x0094d, 0, NULL, NULL },
- { 0x00c55, 0x00c56, 0, NULL, NULL },
- { 0x00488, 0x00489, 0, NULL, NULL },
- { 0x00e47, 0x00e4e, 0, NULL, NULL },
- { 0x00a81, 0x00a82, 0, NULL, NULL },
- { 0x00ac1, 0x00ac5, 0, NULL, NULL },
- { 0x0202a, 0x0202e, 0, NULL, NULL },
- { 0x00dd6, 0x00dd6, 0, NULL, NULL },
- { 0x018a9, 0x018a9, 0, NULL, NULL },
- { 0x0064b, 0x0065e, 0, NULL, NULL },
- { 0x00abc, 0x00abc, 0, NULL, NULL },
- { 0x00b82, 0x00b82, 0, NULL, NULL },
- { 0x00f39, 0x00f39, 0, NULL, NULL },
- { 0x020d0, 0x020ef, 0, NULL, NULL },
- { 0x01dfe, 0x01dff, 0, NULL, NULL },
- { 0x30000, 0x3fffd, 2, NULL, NULL },
- { 0x00711, 0x00711, 0, NULL, NULL },
- { 0x0fe00, 0x0fe0f, 0, NULL, NULL },
- { 0x0180b, 0x0180d, 0, NULL, NULL },
- { 0x10a3f, 0x10a3f, 0, NULL, NULL },
- { 0x00981, 0x00981, 0, NULL, NULL },
- { 0x0a825, 0x0a826, 0, NULL, NULL },
- { 0x00941, 0x00948, 0, NULL, NULL },
- { 0x01b6b, 0x01b73, 0, NULL, NULL },
- { 0x00e31, 0x00e31, 0, NULL, NULL },
- { 0x0fe10, 0x0fe19, 2, NULL, NULL },
- { 0x00a01, 0x00a02, 0, NULL, NULL },
- { 0x00a4b, 0x00a4d, 0, NULL, NULL },
- { 0x00f18, 0x00f19, 0, NULL, NULL },
- { 0x00fc6, 0x00fc6, 0, NULL, NULL },
- { 0x02e80, 0x03029, 2, NULL, NULL },
- { 0x00b56, 0x00b56, 0, NULL, NULL },
- { 0x009bc, 0x009bc, 0, NULL, NULL },
- { 0x005c7, 0x005c7, 0, NULL, NULL },
- { 0x02060, 0x02063, 0, NULL, NULL },
- { 0x00c3e, 0x00c40, 0, NULL, NULL },
- { 0x10a05, 0x10a06, 0, NULL, NULL },
-};
-
-struct utf8_width_entry *utf8_width_root = NULL;
-
-int utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry *);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_width(const struct utf8_data *);
@@ -257,48 +83,6 @@ utf8_append(struct utf8_data *utf8data, u_char ch)
return (0);
}
-/* Check if two width tree entries overlap. */
-int
-utf8_overlap(struct utf8_width_entry *item1, struct utf8_width_entry *item2)
-{
- if (item1->first >= item2->first && item1->first <= item2->last)
- return (1);
- if (item1->last >= item2->first && item1->last <= item2->last)
- return (1);
- if (item2->first >= item1->first && item2->first <= item1->last)
- return (1);
- if (item2->last >= item1->first && item2->last <= item1->last)
- return (1);
- return (0);
-}
-
-/* Build UTF-8 width tree. */
-void
-utf8_build(void)
-{
- struct utf8_width_entry **ptr, *item, *node;
- u_int i, j;
-
- for (i = 0; i < nitems(utf8_width_table); i++) {
- item = &utf8_width_table[i];
-
- for (j = 0; j < nitems(utf8_width_table); j++) {
- if (i != j && utf8_overlap(item, &utf8_width_table[j]))
- log_fatalx("utf8 overlap: %u %u", i, j);
- }
-
- ptr = &utf8_width_root;
- while (*ptr != NULL) {
- node = *ptr;
- if (item->last < node->first)
- ptr = &node->left;
- else if (item->first > node->last)
- ptr = &node->right;
- }
- *ptr = item;
- }
-}
-
/* Combine UTF-8 into 32-bit Unicode. */
u_int
utf8_combine(const struct utf8_data *utf8data)
@@ -342,25 +126,14 @@ utf8_split2(u_int uc, u_char *ptr)
return (1);
}
-/* Lookup width of UTF-8 data in tree. */
u_int
utf8_width(const struct utf8_data *utf8data)
{
- struct utf8_width_entry *item;
- u_int value;
-
- value = utf8_combine(utf8data);
-
- item = utf8_width_root;
- while (item != NULL) {
- if (value < item->first)
- item = item->left;
- else if (value > item->last)
- item = item->right;
- else
- return (item->width);
- }
- return (1);
+ int width;
+
+ width = wcwidth(utf8_combine(utf8data));
+
+ return (width <= -1 ? 1 : width);
}
/*
--
2.4.1
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
tmux-users mailing list
https://lists.sourceforge.net/lists/listinfo/tmux-users
Kohei Suzuki
2015-05-18 12:24:37 UTC
Permalink
Thank you for reviewing.
Okey, then how about adding a new option "ambiguous-width" which controls
the width of East Asian ambiguous width characters?
It is set to 1 by default, and users can set it to 2 by `set-option
ambiguous-width 2` .
Is it acceptable?

Kohei Suzuki
Post by Nicholas Marriott
Hi
We can't do this because tmux must know the width of the UTF-8 character
but the locale may not be UTF-8.
Post by Kohei Suzuki
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has
width 1
Post by Kohei Suzuki
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).
Kohei Suzuki
References
Visible links
From 6324eb0bef76c9ec0d214cefa433efa1493f1845 Mon Sep 17 00:00:00 2001
Date: Mon, 18 May 2015 01:28:29 +0900
Subject: [PATCH] Use wcwidth(1) to calculate character width
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has width 1
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).
---
server.c | 1 -
tmux.h | 1 -
utf8.c | 239
++-------------------------------------------------------------
Post by Kohei Suzuki
3 files changed, 6 insertions(+), 235 deletions(-)
diff --git a/server.c b/server.c
index 738abe1..3c164ff 100644
--- a/server.c
+++ b/server.c
@@ -145,7 +145,6 @@ server_start(int lockfd, char *lockfile)
TAILQ_INIT(&session_groups);
mode_key_init_trees();
key_bindings_init();
- utf8_build();
start_time = time(NULL);
log_debug("socket path %s", socket_path);
diff --git a/tmux.h b/tmux.h
index 054a859..7a6265a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2286,7 +2286,6 @@ void session_group_synchronize1(struct
session *, struct session *);
Post by Kohei Suzuki
void session_renumber_windows(struct session *);
/* utf8.c */
-void utf8_build(void);
void utf8_set(struct utf8_data *, u_char);
int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char);
diff --git a/utf8.c b/utf8.c
index 76b4846..4a84f20 100644
--- a/utf8.c
+++ b/utf8.c
@@ -20,184 +20,10 @@
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "tmux.h"
-struct utf8_width_entry {
- u_int first;
- u_int last;
-
- int width;
-
- struct utf8_width_entry *left;
- struct utf8_width_entry *right;
-};
-
-/* Random order. Not optimal but it'll do for now... */
-struct utf8_width_entry utf8_width_table[] = {
- { 0x00951, 0x00954, 0, NULL, NULL },
- { 0x00ccc, 0x00ccd, 0, NULL, NULL },
- { 0x0fff9, 0x0fffb, 0, NULL, NULL },
- { 0x20000, 0x2fffd, 2, NULL, NULL },
- { 0x00ebb, 0x00ebc, 0, NULL, NULL },
- { 0x01932, 0x01932, 0, NULL, NULL },
- { 0x0070f, 0x0070f, 0, NULL, NULL },
- { 0x00a70, 0x00a71, 0, NULL, NULL },
- { 0x02329, 0x02329, 2, NULL, NULL },
- { 0x00acd, 0x00acd, 0, NULL, NULL },
- { 0x00ac7, 0x00ac8, 0, NULL, NULL },
- { 0x00a3c, 0x00a3c, 0, NULL, NULL },
- { 0x009cd, 0x009cd, 0, NULL, NULL },
- { 0x00591, 0x005bd, 0, NULL, NULL },
- { 0x01058, 0x01059, 0, NULL, NULL },
- { 0x0ffe0, 0x0ffe6, 2, NULL, NULL },
- { 0x01100, 0x0115f, 2, NULL, NULL },
- { 0x0fe20, 0x0fe23, 0, NULL, NULL },
- { 0x0302a, 0x0302f, 0, NULL, NULL },
- { 0x01772, 0x01773, 0, NULL, NULL },
- { 0x005bf, 0x005bf, 0, NULL, NULL },
- { 0x006ea, 0x006ed, 0, NULL, NULL },
- { 0x00bc0, 0x00bc0, 0, NULL, NULL },
- { 0x00962, 0x00963, 0, NULL, NULL },
- { 0x01732, 0x01734, 0, NULL, NULL },
- { 0x00d41, 0x00d43, 0, NULL, NULL },
- { 0x01b42, 0x01b42, 0, NULL, NULL },
- { 0x00a41, 0x00a42, 0, NULL, NULL },
- { 0x00eb4, 0x00eb9, 0, NULL, NULL },
- { 0x00b01, 0x00b01, 0, NULL, NULL },
- { 0x00e34, 0x00e3a, 0, NULL, NULL },
- { 0x03040, 0x03098, 2, NULL, NULL },
- { 0x0093c, 0x0093c, 0, NULL, NULL },
- { 0x00c4a, 0x00c4d, 0, NULL, NULL },
- { 0x01032, 0x01032, 0, NULL, NULL },
- { 0x00f37, 0x00f37, 0, NULL, NULL },
- { 0x00901, 0x00902, 0, NULL, NULL },
- { 0x00cbf, 0x00cbf, 0, NULL, NULL },
- { 0x0a806, 0x0a806, 0, NULL, NULL },
- { 0x00dd2, 0x00dd4, 0, NULL, NULL },
- { 0x00f71, 0x00f7e, 0, NULL, NULL },
- { 0x01752, 0x01753, 0, NULL, NULL },
- { 0x1d242, 0x1d244, 0, NULL, NULL },
- { 0x005c1, 0x005c2, 0, NULL, NULL },
- { 0x0309b, 0x0a4cf, 2, NULL, NULL },
- { 0xe0100, 0xe01ef, 0, NULL, NULL },
- { 0x017dd, 0x017dd, 0, NULL, NULL },
- { 0x00600, 0x00603, 0, NULL, NULL },
- { 0x009e2, 0x009e3, 0, NULL, NULL },
- { 0x00cc6, 0x00cc6, 0, NULL, NULL },
- { 0x0a80b, 0x0a80b, 0, NULL, NULL },
- { 0x01712, 0x01714, 0, NULL, NULL },
- { 0x00b3c, 0x00b3c, 0, NULL, NULL },
- { 0x01b00, 0x01b03, 0, NULL, NULL },
- { 0x007eb, 0x007f3, 0, NULL, NULL },
- { 0xe0001, 0xe0001, 0, NULL, NULL },
- { 0x1d185, 0x1d18b, 0, NULL, NULL },
- { 0x0feff, 0x0feff, 0, NULL, NULL },
- { 0x01b36, 0x01b3a, 0, NULL, NULL },
- { 0x01920, 0x01922, 0, NULL, NULL },
- { 0x00670, 0x00670, 0, NULL, NULL },
- { 0x00f90, 0x00f97, 0, NULL, NULL },
- { 0x01927, 0x01928, 0, NULL, NULL },
- { 0x0200b, 0x0200f, 0, NULL, NULL },
- { 0x0ff00, 0x0ff60, 2, NULL, NULL },
- { 0x0f900, 0x0faff, 2, NULL, NULL },
- { 0x0fb1e, 0x0fb1e, 0, NULL, NULL },
- { 0x00cbc, 0x00cbc, 0, NULL, NULL },
- { 0x00eb1, 0x00eb1, 0, NULL, NULL },
- { 0x10a38, 0x10a3a, 0, NULL, NULL },
- { 0x007a6, 0x007b0, 0, NULL, NULL },
- { 0x00f80, 0x00f84, 0, NULL, NULL },
- { 0x005c4, 0x005c5, 0, NULL, NULL },
- { 0x0ac00, 0x0d7a3, 2, NULL, NULL },
- { 0x017c9, 0x017d3, 0, NULL, NULL },
- { 0x00d4d, 0x00d4d, 0, NULL, NULL },
- { 0x1d167, 0x1d169, 0, NULL, NULL },
- { 0x01036, 0x01037, 0, NULL, NULL },
- { 0xe0020, 0xe007f, 0, NULL, NULL },
- { 0x00f35, 0x00f35, 0, NULL, NULL },
- { 0x017b4, 0x017b5, 0, NULL, NULL },
- { 0x0206a, 0x0206f, 0, NULL, NULL },
- { 0x00c46, 0x00c48, 0, NULL, NULL },
- { 0x01939, 0x0193b, 0, NULL, NULL },
- { 0x01dc0, 0x01dca, 0, NULL, NULL },
- { 0x10a0c, 0x10a0f, 0, NULL, NULL },
- { 0x0102d, 0x01030, 0, NULL, NULL },
- { 0x017c6, 0x017c6, 0, NULL, NULL },
- { 0x00ec8, 0x00ecd, 0, NULL, NULL },
- { 0x00b41, 0x00b43, 0, NULL, NULL },
- { 0x017b7, 0x017bd, 0, NULL, NULL },
- { 0x1d173, 0x1d182, 0, NULL, NULL },
- { 0x00a47, 0x00a48, 0, NULL, NULL },
- { 0x0232a, 0x0232a, 2, NULL, NULL },
- { 0x01b3c, 0x01b3c, 0, NULL, NULL },
- { 0x10a01, 0x10a03, 0, NULL, NULL },
- { 0x00ae2, 0x00ae3, 0, NULL, NULL },
- { 0x00483, 0x00486, 0, NULL, NULL },
- { 0x0135f, 0x0135f, 0, NULL, NULL },
- { 0x01a17, 0x01a18, 0, NULL, NULL },
- { 0x006e7, 0x006e8, 0, NULL, NULL },
-#ifndef __APPLE__
- { 0x03099, 0x0309a, 0, NULL, NULL },
-#endif
- { 0x00b4d, 0x00b4d, 0, NULL, NULL },
- { 0x00ce2, 0x00ce3, 0, NULL, NULL },
- { 0x00bcd, 0x00bcd, 0, NULL, NULL },
- { 0x00610, 0x00615, 0, NULL, NULL },
- { 0x00f99, 0x00fbc, 0, NULL, NULL },
- { 0x009c1, 0x009c4, 0, NULL, NULL },
- { 0x00730, 0x0074a, 0, NULL, NULL },
- { 0x00300, 0x0036f, 0, NULL, NULL },
- { 0x03030, 0x0303e, 2, NULL, NULL },
- { 0x01b34, 0x01b34, 0, NULL, NULL },
- { 0x1d1aa, 0x1d1ad, 0, NULL, NULL },
- { 0x00dca, 0x00dca, 0, NULL, NULL },
- { 0x006d6, 0x006e4, 0, NULL, NULL },
- { 0x00f86, 0x00f87, 0, NULL, NULL },
- { 0x00b3f, 0x00b3f, 0, NULL, NULL },
- { 0x0fe30, 0x0fe6f, 2, NULL, NULL },
- { 0x01039, 0x01039, 0, NULL, NULL },
- { 0x0094d, 0x0094d, 0, NULL, NULL },
- { 0x00c55, 0x00c56, 0, NULL, NULL },
- { 0x00488, 0x00489, 0, NULL, NULL },
- { 0x00e47, 0x00e4e, 0, NULL, NULL },
- { 0x00a81, 0x00a82, 0, NULL, NULL },
- { 0x00ac1, 0x00ac5, 0, NULL, NULL },
- { 0x0202a, 0x0202e, 0, NULL, NULL },
- { 0x00dd6, 0x00dd6, 0, NULL, NULL },
- { 0x018a9, 0x018a9, 0, NULL, NULL },
- { 0x0064b, 0x0065e, 0, NULL, NULL },
- { 0x00abc, 0x00abc, 0, NULL, NULL },
- { 0x00b82, 0x00b82, 0, NULL, NULL },
- { 0x00f39, 0x00f39, 0, NULL, NULL },
- { 0x020d0, 0x020ef, 0, NULL, NULL },
- { 0x01dfe, 0x01dff, 0, NULL, NULL },
- { 0x30000, 0x3fffd, 2, NULL, NULL },
- { 0x00711, 0x00711, 0, NULL, NULL },
- { 0x0fe00, 0x0fe0f, 0, NULL, NULL },
- { 0x0180b, 0x0180d, 0, NULL, NULL },
- { 0x10a3f, 0x10a3f, 0, NULL, NULL },
- { 0x00981, 0x00981, 0, NULL, NULL },
- { 0x0a825, 0x0a826, 0, NULL, NULL },
- { 0x00941, 0x00948, 0, NULL, NULL },
- { 0x01b6b, 0x01b73, 0, NULL, NULL },
- { 0x00e31, 0x00e31, 0, NULL, NULL },
- { 0x0fe10, 0x0fe19, 2, NULL, NULL },
- { 0x00a01, 0x00a02, 0, NULL, NULL },
- { 0x00a4b, 0x00a4d, 0, NULL, NULL },
- { 0x00f18, 0x00f19, 0, NULL, NULL },
- { 0x00fc6, 0x00fc6, 0, NULL, NULL },
- { 0x02e80, 0x03029, 2, NULL, NULL },
- { 0x00b56, 0x00b56, 0, NULL, NULL },
- { 0x009bc, 0x009bc, 0, NULL, NULL },
- { 0x005c7, 0x005c7, 0, NULL, NULL },
- { 0x02060, 0x02063, 0, NULL, NULL },
- { 0x00c3e, 0x00c40, 0, NULL, NULL },
- { 0x10a05, 0x10a06, 0, NULL, NULL },
-};
-
-struct utf8_width_entry *utf8_width_root = NULL;
-
-int utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry *);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_width(const struct utf8_data *);
@@ -257,48 +83,6 @@ utf8_append(struct utf8_data *utf8data, u_char ch)
return (0);
}
-/* Check if two width tree entries overlap. */
-int
-utf8_overlap(struct utf8_width_entry *item1, struct utf8_width_entry
*item2)
Post by Kohei Suzuki
-{
- if (item1->first >= item2->first && item1->first <= item2->last)
- return (1);
- if (item1->last >= item2->first && item1->last <= item2->last)
- return (1);
- if (item2->first >= item1->first && item2->first <= item1->last)
- return (1);
- if (item2->last >= item1->first && item2->last <= item1->last)
- return (1);
- return (0);
-}
-
-/* Build UTF-8 width tree. */
-void
-utf8_build(void)
-{
- struct utf8_width_entry **ptr, *item, *node;
- u_int i, j;
-
- for (i = 0; i < nitems(utf8_width_table); i++) {
- item = &utf8_width_table[i];
-
- for (j = 0; j < nitems(utf8_width_table); j++) {
- if (i != j && utf8_overlap(item,
&utf8_width_table[j]))
Post by Kohei Suzuki
- log_fatalx("utf8 overlap: %u %u", i, j);
- }
-
- ptr = &utf8_width_root;
- while (*ptr != NULL) {
- node = *ptr;
- if (item->last < node->first)
- ptr = &node->left;
- else if (item->first > node->last)
- ptr = &node->right;
- }
- *ptr = item;
- }
-}
-
/* Combine UTF-8 into 32-bit Unicode. */
u_int
utf8_combine(const struct utf8_data *utf8data)
@@ -342,25 +126,14 @@ utf8_split2(u_int uc, u_char *ptr)
return (1);
}
-/* Lookup width of UTF-8 data in tree. */
u_int
utf8_width(const struct utf8_data *utf8data)
{
- struct utf8_width_entry *item;
- u_int value;
-
- value = utf8_combine(utf8data);
-
- item = utf8_width_root;
- while (item != NULL) {
- if (value < item->first)
- item = item->left;
- else if (value > item->last)
- item = item->right;
- else
- return (item->width);
- }
- return (1);
+ int width;
+
+ width = wcwidth(utf8_combine(utf8data));
+
+ return (width <= -1 ? 1 : width);
}
/*
--
2.4.1
------------------------------------------------------------------------------
Post by Kohei Suzuki
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
tmux-users mailing list
https://lists.sourceforge.net/lists/listinfo/tmux-users
Nicholas Marriott
2015-05-18 14:16:58 UTC
Permalink
Hi

How does wcwidth figure this out? What are the character ranges?
Post by Kohei Suzuki
Thank you for reviewing.
Okey, then how about adding a new option "ambiguous-width" which controls
the width of East Asian ambiguous width characters?
It is set to 1 by default, and users can set it to 2 by `set-option
ambiguous-width 2` .
Is it acceptable?
Kohei Suzuki
2015-05-18 2:08 GMT+09:00 Nicholas Marriott
Hi
We can't do this because tmux must know the width of the UTF-8 character
but the locale may not be UTF-8.
** ** Several characters' width are depending on locale. They're called
East
** ** Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has
width 1
** ** in most locales, but it has width 2 in some East Asian locales
(e.g.
** ** Japanese).
** ** Kohei Suzuki
References
** ** Visible links
From 6324eb0bef76c9ec0d214cefa433efa1493f1845 Mon Sep 17 00:00:00 2001
Date: Mon, 18 May 2015 01:28:29 +0900
Subject: [PATCH] Use wcwidth(1) to calculate character width
Several characters' width are depending on locale. They're called East
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has width
1
in most locales, but it has width 2 in some East Asian locales (e.g.
Japanese).
---
** server.c |** **1 -
** tmux.h** **|** **1 -
** utf8.c** **| 239
++-------------------------------------------------------------
** 3 files changed, 6 insertions(+), 235 deletions(-)
diff --git a/server.c b/server.c
index 738abe1..3c164ff 100644
--- a/server.c
+++ b/server.c
@@ -145,7 +145,6 @@ server_start(int lockfd, char *lockfile)
** ** ** **TAILQ_INIT(&session_groups);
** ** ** **mode_key_init_trees();
** ** ** **key_bindings_init();
-** ** **utf8_build();
** ** ** **start_time = time(NULL);
** ** ** **log_debug("socket path %s", socket_path);
diff --git a/tmux.h b/tmux.h
index 054a859..7a6265a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2286,7 +2286,6 @@ void** ** ** ** ** **
**session_group_synchronize1(struct session *, struct session *);
** void** ** ** ** ** session_renumber_windows(struct session *);
** /* utf8.c */
-void** ** ** ** ** utf8_build(void);
** void** ** ** ** ** utf8_set(struct utf8_data *, u_char);
** int** ** ** ** ** **utf8_open(struct utf8_data *, u_char);
** int** ** ** ** ** **utf8_append(struct utf8_data *, u_char);
diff --git a/utf8.c b/utf8.c
index 76b4846..4a84f20 100644
--- a/utf8.c
+++ b/utf8.c
@@ -20,184 +20,10 @@
** #include <stdlib.h>
** #include <string.h>
+#include <wchar.h>
** #include "tmux.h"
-struct utf8_width_entry {
-** ** **u_int** **first;
-** ** **u_int** **last;
-
-** ** **int** ** **width;
-
-** ** **struct utf8_width_entry *left;
-** ** **struct utf8_width_entry *right;
-};
-
-/* Random order. Not optimal but it'll do for now... */
-struct utf8_width_entry utf8_width_table[] = {
-** ** **{ 0x00951, 0x00954, 0, NULL, NULL },
-** ** **{ 0x00ccc, 0x00ccd, 0, NULL, NULL },
-** ** **{ 0x0fff9, 0x0fffb, 0, NULL, NULL },
-** ** **{ 0x20000, 0x2fffd, 2, NULL, NULL },
-** ** **{ 0x00ebb, 0x00ebc, 0, NULL, NULL },
-** ** **{ 0x01932, 0x01932, 0, NULL, NULL },
-** ** **{ 0x0070f, 0x0070f, 0, NULL, NULL },
-** ** **{ 0x00a70, 0x00a71, 0, NULL, NULL },
-** ** **{ 0x02329, 0x02329, 2, NULL, NULL },
-** ** **{ 0x00acd, 0x00acd, 0, NULL, NULL },
-** ** **{ 0x00ac7, 0x00ac8, 0, NULL, NULL },
-** ** **{ 0x00a3c, 0x00a3c, 0, NULL, NULL },
-** ** **{ 0x009cd, 0x009cd, 0, NULL, NULL },
-** ** **{ 0x00591, 0x005bd, 0, NULL, NULL },
-** ** **{ 0x01058, 0x01059, 0, NULL, NULL },
-** ** **{ 0x0ffe0, 0x0ffe6, 2, NULL, NULL },
-** ** **{ 0x01100, 0x0115f, 2, NULL, NULL },
-** ** **{ 0x0fe20, 0x0fe23, 0, NULL, NULL },
-** ** **{ 0x0302a, 0x0302f, 0, NULL, NULL },
-** ** **{ 0x01772, 0x01773, 0, NULL, NULL },
-** ** **{ 0x005bf, 0x005bf, 0, NULL, NULL },
-** ** **{ 0x006ea, 0x006ed, 0, NULL, NULL },
-** ** **{ 0x00bc0, 0x00bc0, 0, NULL, NULL },
-** ** **{ 0x00962, 0x00963, 0, NULL, NULL },
-** ** **{ 0x01732, 0x01734, 0, NULL, NULL },
-** ** **{ 0x00d41, 0x00d43, 0, NULL, NULL },
-** ** **{ 0x01b42, 0x01b42, 0, NULL, NULL },
-** ** **{ 0x00a41, 0x00a42, 0, NULL, NULL },
-** ** **{ 0x00eb4, 0x00eb9, 0, NULL, NULL },
-** ** **{ 0x00b01, 0x00b01, 0, NULL, NULL },
-** ** **{ 0x00e34, 0x00e3a, 0, NULL, NULL },
-** ** **{ 0x03040, 0x03098, 2, NULL, NULL },
-** ** **{ 0x0093c, 0x0093c, 0, NULL, NULL },
-** ** **{ 0x00c4a, 0x00c4d, 0, NULL, NULL },
-** ** **{ 0x01032, 0x01032, 0, NULL, NULL },
-** ** **{ 0x00f37, 0x00f37, 0, NULL, NULL },
-** ** **{ 0x00901, 0x00902, 0, NULL, NULL },
-** ** **{ 0x00cbf, 0x00cbf, 0, NULL, NULL },
-** ** **{ 0x0a806, 0x0a806, 0, NULL, NULL },
-** ** **{ 0x00dd2, 0x00dd4, 0, NULL, NULL },
-** ** **{ 0x00f71, 0x00f7e, 0, NULL, NULL },
-** ** **{ 0x01752, 0x01753, 0, NULL, NULL },
-** ** **{ 0x1d242, 0x1d244, 0, NULL, NULL },
-** ** **{ 0x005c1, 0x005c2, 0, NULL, NULL },
-** ** **{ 0x0309b, 0x0a4cf, 2, NULL, NULL },
-** ** **{ 0xe0100, 0xe01ef, 0, NULL, NULL },
-** ** **{ 0x017dd, 0x017dd, 0, NULL, NULL },
-** ** **{ 0x00600, 0x00603, 0, NULL, NULL },
-** ** **{ 0x009e2, 0x009e3, 0, NULL, NULL },
-** ** **{ 0x00cc6, 0x00cc6, 0, NULL, NULL },
-** ** **{ 0x0a80b, 0x0a80b, 0, NULL, NULL },
-** ** **{ 0x01712, 0x01714, 0, NULL, NULL },
-** ** **{ 0x00b3c, 0x00b3c, 0, NULL, NULL },
-** ** **{ 0x01b00, 0x01b03, 0, NULL, NULL },
-** ** **{ 0x007eb, 0x007f3, 0, NULL, NULL },
-** ** **{ 0xe0001, 0xe0001, 0, NULL, NULL },
-** ** **{ 0x1d185, 0x1d18b, 0, NULL, NULL },
-** ** **{ 0x0feff, 0x0feff, 0, NULL, NULL },
-** ** **{ 0x01b36, 0x01b3a, 0, NULL, NULL },
-** ** **{ 0x01920, 0x01922, 0, NULL, NULL },
-** ** **{ 0x00670, 0x00670, 0, NULL, NULL },
-** ** **{ 0x00f90, 0x00f97, 0, NULL, NULL },
-** ** **{ 0x01927, 0x01928, 0, NULL, NULL },
-** ** **{ 0x0200b, 0x0200f, 0, NULL, NULL },
-** ** **{ 0x0ff00, 0x0ff60, 2, NULL, NULL },
-** ** **{ 0x0f900, 0x0faff, 2, NULL, NULL },
-** ** **{ 0x0fb1e, 0x0fb1e, 0, NULL, NULL },
-** ** **{ 0x00cbc, 0x00cbc, 0, NULL, NULL },
-** ** **{ 0x00eb1, 0x00eb1, 0, NULL, NULL },
-** ** **{ 0x10a38, 0x10a3a, 0, NULL, NULL },
-** ** **{ 0x007a6, 0x007b0, 0, NULL, NULL },
-** ** **{ 0x00f80, 0x00f84, 0, NULL, NULL },
-** ** **{ 0x005c4, 0x005c5, 0, NULL, NULL },
-** ** **{ 0x0ac00, 0x0d7a3, 2, NULL, NULL },
-** ** **{ 0x017c9, 0x017d3, 0, NULL, NULL },
-** ** **{ 0x00d4d, 0x00d4d, 0, NULL, NULL },
-** ** **{ 0x1d167, 0x1d169, 0, NULL, NULL },
-** ** **{ 0x01036, 0x01037, 0, NULL, NULL },
-** ** **{ 0xe0020, 0xe007f, 0, NULL, NULL },
-** ** **{ 0x00f35, 0x00f35, 0, NULL, NULL },
-** ** **{ 0x017b4, 0x017b5, 0, NULL, NULL },
-** ** **{ 0x0206a, 0x0206f, 0, NULL, NULL },
-** ** **{ 0x00c46, 0x00c48, 0, NULL, NULL },
-** ** **{ 0x01939, 0x0193b, 0, NULL, NULL },
-** ** **{ 0x01dc0, 0x01dca, 0, NULL, NULL },
-** ** **{ 0x10a0c, 0x10a0f, 0, NULL, NULL },
-** ** **{ 0x0102d, 0x01030, 0, NULL, NULL },
-** ** **{ 0x017c6, 0x017c6, 0, NULL, NULL },
-** ** **{ 0x00ec8, 0x00ecd, 0, NULL, NULL },
-** ** **{ 0x00b41, 0x00b43, 0, NULL, NULL },
-** ** **{ 0x017b7, 0x017bd, 0, NULL, NULL },
-** ** **{ 0x1d173, 0x1d182, 0, NULL, NULL },
-** ** **{ 0x00a47, 0x00a48, 0, NULL, NULL },
-** ** **{ 0x0232a, 0x0232a, 2, NULL, NULL },
-** ** **{ 0x01b3c, 0x01b3c, 0, NULL, NULL },
-** ** **{ 0x10a01, 0x10a03, 0, NULL, NULL },
-** ** **{ 0x00ae2, 0x00ae3, 0, NULL, NULL },
-** ** **{ 0x00483, 0x00486, 0, NULL, NULL },
-** ** **{ 0x0135f, 0x0135f, 0, NULL, NULL },
-** ** **{ 0x01a17, 0x01a18, 0, NULL, NULL },
-** ** **{ 0x006e7, 0x006e8, 0, NULL, NULL },
-#ifndef __APPLE__
-** ** **{ 0x03099, 0x0309a, 0, NULL, NULL },
-#endif
-** ** **{ 0x00b4d, 0x00b4d, 0, NULL, NULL },
-** ** **{ 0x00ce2, 0x00ce3, 0, NULL, NULL },
-** ** **{ 0x00bcd, 0x00bcd, 0, NULL, NULL },
-** ** **{ 0x00610, 0x00615, 0, NULL, NULL },
-** ** **{ 0x00f99, 0x00fbc, 0, NULL, NULL },
-** ** **{ 0x009c1, 0x009c4, 0, NULL, NULL },
-** ** **{ 0x00730, 0x0074a, 0, NULL, NULL },
-** ** **{ 0x00300, 0x0036f, 0, NULL, NULL },
-** ** **{ 0x03030, 0x0303e, 2, NULL, NULL },
-** ** **{ 0x01b34, 0x01b34, 0, NULL, NULL },
-** ** **{ 0x1d1aa, 0x1d1ad, 0, NULL, NULL },
-** ** **{ 0x00dca, 0x00dca, 0, NULL, NULL },
-** ** **{ 0x006d6, 0x006e4, 0, NULL, NULL },
-** ** **{ 0x00f86, 0x00f87, 0, NULL, NULL },
-** ** **{ 0x00b3f, 0x00b3f, 0, NULL, NULL },
-** ** **{ 0x0fe30, 0x0fe6f, 2, NULL, NULL },
-** ** **{ 0x01039, 0x01039, 0, NULL, NULL },
-** ** **{ 0x0094d, 0x0094d, 0, NULL, NULL },
-** ** **{ 0x00c55, 0x00c56, 0, NULL, NULL },
-** ** **{ 0x00488, 0x00489, 0, NULL, NULL },
-** ** **{ 0x00e47, 0x00e4e, 0, NULL, NULL },
-** ** **{ 0x00a81, 0x00a82, 0, NULL, NULL },
-** ** **{ 0x00ac1, 0x00ac5, 0, NULL, NULL },
-** ** **{ 0x0202a, 0x0202e, 0, NULL, NULL },
-** ** **{ 0x00dd6, 0x00dd6, 0, NULL, NULL },
-** ** **{ 0x018a9, 0x018a9, 0, NULL, NULL },
-** ** **{ 0x0064b, 0x0065e, 0, NULL, NULL },
-** ** **{ 0x00abc, 0x00abc, 0, NULL, NULL },
-** ** **{ 0x00b82, 0x00b82, 0, NULL, NULL },
-** ** **{ 0x00f39, 0x00f39, 0, NULL, NULL },
-** ** **{ 0x020d0, 0x020ef, 0, NULL, NULL },
-** ** **{ 0x01dfe, 0x01dff, 0, NULL, NULL },
-** ** **{ 0x30000, 0x3fffd, 2, NULL, NULL },
-** ** **{ 0x00711, 0x00711, 0, NULL, NULL },
-** ** **{ 0x0fe00, 0x0fe0f, 0, NULL, NULL },
-** ** **{ 0x0180b, 0x0180d, 0, NULL, NULL },
-** ** **{ 0x10a3f, 0x10a3f, 0, NULL, NULL },
-** ** **{ 0x00981, 0x00981, 0, NULL, NULL },
-** ** **{ 0x0a825, 0x0a826, 0, NULL, NULL },
-** ** **{ 0x00941, 0x00948, 0, NULL, NULL },
-** ** **{ 0x01b6b, 0x01b73, 0, NULL, NULL },
-** ** **{ 0x00e31, 0x00e31, 0, NULL, NULL },
-** ** **{ 0x0fe10, 0x0fe19, 2, NULL, NULL },
-** ** **{ 0x00a01, 0x00a02, 0, NULL, NULL },
-** ** **{ 0x00a4b, 0x00a4d, 0, NULL, NULL },
-** ** **{ 0x00f18, 0x00f19, 0, NULL, NULL },
-** ** **{ 0x00fc6, 0x00fc6, 0, NULL, NULL },
-** ** **{ 0x02e80, 0x03029, 2, NULL, NULL },
-** ** **{ 0x00b56, 0x00b56, 0, NULL, NULL },
-** ** **{ 0x009bc, 0x009bc, 0, NULL, NULL },
-** ** **{ 0x005c7, 0x005c7, 0, NULL, NULL },
-** ** **{ 0x02060, 0x02063, 0, NULL, NULL },
-** ** **{ 0x00c3e, 0x00c40, 0, NULL, NULL },
-** ** **{ 0x10a05, 0x10a06, 0, NULL, NULL },
-};
-
-struct utf8_width_entry** ** ** *utf8_width_root = NULL;
-
-int** utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry
*);
** u_int** ** ** ** utf8_combine(const struct utf8_data *);
** u_int** ** ** ** utf8_width(const struct utf8_data *);
@@ -257,48 +83,6 @@ utf8_append(struct utf8_data *utf8data, u_char ch)
** ** ** **return (0);
** }
-/* Check if two width tree entries overlap. */
-int
-utf8_overlap(struct utf8_width_entry *item1, struct utf8_width_entry
*item2)
-{
-** ** **if (item1->first >= item2->first && item1->first <=
item2->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item1->last >= item2->first && item1->last <=
item2->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item2->first >= item1->first && item2->first <=
item1->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item2->last >= item1->first && item2->last <=
item1->last)
-** ** ** ** ** ** **return (1);
-** ** **return (0);
-}
-
-/* Build UTF-8 width tree. */
-void
-utf8_build(void)
-{
-** ** **struct utf8_width_entry **ptr, *item, *node;
-** ** **u_int** ** ** ** ** ** ** ** ** ** **i, j;
-
-** ** **for (i = 0; i < nitems(utf8_width_table); i++) {
-** ** ** ** ** ** **item = &utf8_width_table[i];
-
-** ** ** ** ** ** **for (j = 0; j < nitems(utf8_width_table); j++) {
-** ** ** ** ** ** ** ** ** ** **if (i != j && utf8_overlap(item,
&utf8_width_table[j]))
%u %u", i, j);
-** ** ** ** ** ** **}
-
-** ** ** ** ** ** **ptr = &utf8_width_root;
-** ** ** ** ** ** **while (*ptr != NULL) {
-** ** ** ** ** ** ** ** ** ** **node = *ptr;
-** ** ** ** ** ** ** ** ** ** **if (item->last < node->first)
-** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr = &node->left;
-** ** ** ** ** ** ** ** ** ** **else if (item->first > node->last)
-** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr = &node->right;
-** ** ** ** ** ** **}
-** ** ** ** ** ** ***ptr = item;
-** ** **}
-}
-
** /* Combine UTF-8 into 32-bit Unicode. */
** u_int
** utf8_combine(const struct utf8_data *utf8data)
@@ -342,25 +126,14 @@ utf8_split2(u_int uc, u_char *ptr)
** ** ** **return (1);
** }
-/* Lookup width of UTF-8 data in tree. */
** u_int
** utf8_width(const struct utf8_data *utf8data)
** {
-** ** **struct utf8_width_entry *item;
-** ** **u_int** ** ** ** ** ** ** ** ** ** value;
-
-** ** **value = utf8_combine(utf8data);
-
-** ** **item = utf8_width_root;
-** ** **while (item != NULL) {
-** ** ** ** ** ** **if (value < item->first)
-** ** ** ** ** ** ** ** ** ** **item = item->left;
-** ** ** ** ** ** **else if (value > item->last)
-** ** ** ** ** ** ** ** ** ** **item = item->right;
-** ** ** ** ** ** **else
-** ** ** ** ** ** ** ** ** ** **return (item->width);
-** ** **}
-** ** **return (1);
+** ** **int width;
+
+** ** **width = wcwidth(utf8_combine(utf8data));
+
+** ** **return (width <= -1 ? 1 : width);
** }
** /*
--
2.4.1
------------------------------------------------------------------------------
One dashboard for servers and applications across
Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable
Insights
Deep dive visibility with transaction tracing using APM Insight.
[6]http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
tmux-users mailing list
[8]https://lists.sourceforge.net/lists/listinfo/tmux-users
References
Visible links
6. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
8. https://lists.sourceforge.net/lists/listinfo/tmux-users
Kohei Suzuki
2015-05-18 14:23:27 UTC
Permalink
The character ranges are listed in
http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt .
"A" means ambiguous width as described in
http://www.unicode.org/reports/tr11/#Definitions .

Kohei Suzuki
Post by Nicholas Marriott
Hi
How does wcwidth figure this out? What are the character ranges?
Post by Kohei Suzuki
Thank you for reviewing.
Okey, then how about adding a new option "ambiguous-width" which
controls
Post by Kohei Suzuki
the width of East Asian ambiguous width characters?
It is set to 1 by default, and users can set it to 2 by `set-option
ambiguous-width 2` .
Is it acceptable?
Kohei Suzuki
2015-05-18 2:08 GMT+09:00 Nicholas Marriott
Hi
We can't do this because tmux must know the width of the UTF-8
character
Post by Kohei Suzuki
but the locale may not be UTF-8.
** ** Several characters' width are depending on locale. They're
called
Post by Kohei Suzuki
East
** ** Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA)
has
Post by Kohei Suzuki
width 1
** ** in most locales, but it has width 2 in some East Asian
locales
Post by Kohei Suzuki
(e.g.
** ** Japanese).
** ** Kohei Suzuki
References
** ** Visible links
From 6324eb0bef76c9ec0d214cefa433efa1493f1845 Mon Sep 17 00:00:00
2001
Post by Kohei Suzuki
Date: Mon, 18 May 2015 01:28:29 +0900
Subject: [PATCH] Use wcwidth(1) to calculate character width
Several characters' width are depending on locale. They're called
East
Post by Kohei Suzuki
Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA) has
width
Post by Kohei Suzuki
1
in most locales, but it has width 2 in some East Asian locales
(e.g.
Post by Kohei Suzuki
Japanese).
---
** server.c |** **1 -
** tmux.h** **|** **1 -
** utf8.c** **| 239
++-------------------------------------------------------------
** 3 files changed, 6 insertions(+), 235 deletions(-)
diff --git a/server.c b/server.c
index 738abe1..3c164ff 100644
--- a/server.c
+++ b/server.c
@@ -145,7 +145,6 @@ server_start(int lockfd, char *lockfile)
** ** ** **TAILQ_INIT(&session_groups);
** ** ** **mode_key_init_trees();
** ** ** **key_bindings_init();
-** ** **utf8_build();
** ** ** **start_time = time(NULL);
** ** ** **log_debug("socket path %s", socket_path);
diff --git a/tmux.h b/tmux.h
index 054a859..7a6265a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2286,7 +2286,6 @@ void** ** ** ** ** **
**session_group_synchronize1(struct session *, struct session *);
** void** ** ** ** ** session_renumber_windows(struct session *);
** /* utf8.c */
-void** ** ** ** ** utf8_build(void);
** void** ** ** ** ** utf8_set(struct utf8_data *, u_char);
** int** ** ** ** ** **utf8_open(struct utf8_data *, u_char);
** int** ** ** ** ** **utf8_append(struct utf8_data *, u_char);
diff --git a/utf8.c b/utf8.c
index 76b4846..4a84f20 100644
--- a/utf8.c
+++ b/utf8.c
@@ -20,184 +20,10 @@
** #include <stdlib.h>
** #include <string.h>
+#include <wchar.h>
** #include "tmux.h"
-struct utf8_width_entry {
-** ** **u_int** **first;
-** ** **u_int** **last;
-
-** ** **int** ** **width;
-
-** ** **struct utf8_width_entry *left;
-** ** **struct utf8_width_entry *right;
-};
-
-/* Random order. Not optimal but it'll do for now... */
-struct utf8_width_entry utf8_width_table[] = {
-** ** **{ 0x00951, 0x00954, 0, NULL, NULL },
-** ** **{ 0x00ccc, 0x00ccd, 0, NULL, NULL },
-** ** **{ 0x0fff9, 0x0fffb, 0, NULL, NULL },
-** ** **{ 0x20000, 0x2fffd, 2, NULL, NULL },
-** ** **{ 0x00ebb, 0x00ebc, 0, NULL, NULL },
-** ** **{ 0x01932, 0x01932, 0, NULL, NULL },
-** ** **{ 0x0070f, 0x0070f, 0, NULL, NULL },
-** ** **{ 0x00a70, 0x00a71, 0, NULL, NULL },
-** ** **{ 0x02329, 0x02329, 2, NULL, NULL },
-** ** **{ 0x00acd, 0x00acd, 0, NULL, NULL },
-** ** **{ 0x00ac7, 0x00ac8, 0, NULL, NULL },
-** ** **{ 0x00a3c, 0x00a3c, 0, NULL, NULL },
-** ** **{ 0x009cd, 0x009cd, 0, NULL, NULL },
-** ** **{ 0x00591, 0x005bd, 0, NULL, NULL },
-** ** **{ 0x01058, 0x01059, 0, NULL, NULL },
-** ** **{ 0x0ffe0, 0x0ffe6, 2, NULL, NULL },
-** ** **{ 0x01100, 0x0115f, 2, NULL, NULL },
-** ** **{ 0x0fe20, 0x0fe23, 0, NULL, NULL },
-** ** **{ 0x0302a, 0x0302f, 0, NULL, NULL },
-** ** **{ 0x01772, 0x01773, 0, NULL, NULL },
-** ** **{ 0x005bf, 0x005bf, 0, NULL, NULL },
-** ** **{ 0x006ea, 0x006ed, 0, NULL, NULL },
-** ** **{ 0x00bc0, 0x00bc0, 0, NULL, NULL },
-** ** **{ 0x00962, 0x00963, 0, NULL, NULL },
-** ** **{ 0x01732, 0x01734, 0, NULL, NULL },
-** ** **{ 0x00d41, 0x00d43, 0, NULL, NULL },
-** ** **{ 0x01b42, 0x01b42, 0, NULL, NULL },
-** ** **{ 0x00a41, 0x00a42, 0, NULL, NULL },
-** ** **{ 0x00eb4, 0x00eb9, 0, NULL, NULL },
-** ** **{ 0x00b01, 0x00b01, 0, NULL, NULL },
-** ** **{ 0x00e34, 0x00e3a, 0, NULL, NULL },
-** ** **{ 0x03040, 0x03098, 2, NULL, NULL },
-** ** **{ 0x0093c, 0x0093c, 0, NULL, NULL },
-** ** **{ 0x00c4a, 0x00c4d, 0, NULL, NULL },
-** ** **{ 0x01032, 0x01032, 0, NULL, NULL },
-** ** **{ 0x00f37, 0x00f37, 0, NULL, NULL },
-** ** **{ 0x00901, 0x00902, 0, NULL, NULL },
-** ** **{ 0x00cbf, 0x00cbf, 0, NULL, NULL },
-** ** **{ 0x0a806, 0x0a806, 0, NULL, NULL },
-** ** **{ 0x00dd2, 0x00dd4, 0, NULL, NULL },
-** ** **{ 0x00f71, 0x00f7e, 0, NULL, NULL },
-** ** **{ 0x01752, 0x01753, 0, NULL, NULL },
-** ** **{ 0x1d242, 0x1d244, 0, NULL, NULL },
-** ** **{ 0x005c1, 0x005c2, 0, NULL, NULL },
-** ** **{ 0x0309b, 0x0a4cf, 2, NULL, NULL },
-** ** **{ 0xe0100, 0xe01ef, 0, NULL, NULL },
-** ** **{ 0x017dd, 0x017dd, 0, NULL, NULL },
-** ** **{ 0x00600, 0x00603, 0, NULL, NULL },
-** ** **{ 0x009e2, 0x009e3, 0, NULL, NULL },
-** ** **{ 0x00cc6, 0x00cc6, 0, NULL, NULL },
-** ** **{ 0x0a80b, 0x0a80b, 0, NULL, NULL },
-** ** **{ 0x01712, 0x01714, 0, NULL, NULL },
-** ** **{ 0x00b3c, 0x00b3c, 0, NULL, NULL },
-** ** **{ 0x01b00, 0x01b03, 0, NULL, NULL },
-** ** **{ 0x007eb, 0x007f3, 0, NULL, NULL },
-** ** **{ 0xe0001, 0xe0001, 0, NULL, NULL },
-** ** **{ 0x1d185, 0x1d18b, 0, NULL, NULL },
-** ** **{ 0x0feff, 0x0feff, 0, NULL, NULL },
-** ** **{ 0x01b36, 0x01b3a, 0, NULL, NULL },
-** ** **{ 0x01920, 0x01922, 0, NULL, NULL },
-** ** **{ 0x00670, 0x00670, 0, NULL, NULL },
-** ** **{ 0x00f90, 0x00f97, 0, NULL, NULL },
-** ** **{ 0x01927, 0x01928, 0, NULL, NULL },
-** ** **{ 0x0200b, 0x0200f, 0, NULL, NULL },
-** ** **{ 0x0ff00, 0x0ff60, 2, NULL, NULL },
-** ** **{ 0x0f900, 0x0faff, 2, NULL, NULL },
-** ** **{ 0x0fb1e, 0x0fb1e, 0, NULL, NULL },
-** ** **{ 0x00cbc, 0x00cbc, 0, NULL, NULL },
-** ** **{ 0x00eb1, 0x00eb1, 0, NULL, NULL },
-** ** **{ 0x10a38, 0x10a3a, 0, NULL, NULL },
-** ** **{ 0x007a6, 0x007b0, 0, NULL, NULL },
-** ** **{ 0x00f80, 0x00f84, 0, NULL, NULL },
-** ** **{ 0x005c4, 0x005c5, 0, NULL, NULL },
-** ** **{ 0x0ac00, 0x0d7a3, 2, NULL, NULL },
-** ** **{ 0x017c9, 0x017d3, 0, NULL, NULL },
-** ** **{ 0x00d4d, 0x00d4d, 0, NULL, NULL },
-** ** **{ 0x1d167, 0x1d169, 0, NULL, NULL },
-** ** **{ 0x01036, 0x01037, 0, NULL, NULL },
-** ** **{ 0xe0020, 0xe007f, 0, NULL, NULL },
-** ** **{ 0x00f35, 0x00f35, 0, NULL, NULL },
-** ** **{ 0x017b4, 0x017b5, 0, NULL, NULL },
-** ** **{ 0x0206a, 0x0206f, 0, NULL, NULL },
-** ** **{ 0x00c46, 0x00c48, 0, NULL, NULL },
-** ** **{ 0x01939, 0x0193b, 0, NULL, NULL },
-** ** **{ 0x01dc0, 0x01dca, 0, NULL, NULL },
-** ** **{ 0x10a0c, 0x10a0f, 0, NULL, NULL },
-** ** **{ 0x0102d, 0x01030, 0, NULL, NULL },
-** ** **{ 0x017c6, 0x017c6, 0, NULL, NULL },
-** ** **{ 0x00ec8, 0x00ecd, 0, NULL, NULL },
-** ** **{ 0x00b41, 0x00b43, 0, NULL, NULL },
-** ** **{ 0x017b7, 0x017bd, 0, NULL, NULL },
-** ** **{ 0x1d173, 0x1d182, 0, NULL, NULL },
-** ** **{ 0x00a47, 0x00a48, 0, NULL, NULL },
-** ** **{ 0x0232a, 0x0232a, 2, NULL, NULL },
-** ** **{ 0x01b3c, 0x01b3c, 0, NULL, NULL },
-** ** **{ 0x10a01, 0x10a03, 0, NULL, NULL },
-** ** **{ 0x00ae2, 0x00ae3, 0, NULL, NULL },
-** ** **{ 0x00483, 0x00486, 0, NULL, NULL },
-** ** **{ 0x0135f, 0x0135f, 0, NULL, NULL },
-** ** **{ 0x01a17, 0x01a18, 0, NULL, NULL },
-** ** **{ 0x006e7, 0x006e8, 0, NULL, NULL },
-#ifndef __APPLE__
-** ** **{ 0x03099, 0x0309a, 0, NULL, NULL },
-#endif
-** ** **{ 0x00b4d, 0x00b4d, 0, NULL, NULL },
-** ** **{ 0x00ce2, 0x00ce3, 0, NULL, NULL },
-** ** **{ 0x00bcd, 0x00bcd, 0, NULL, NULL },
-** ** **{ 0x00610, 0x00615, 0, NULL, NULL },
-** ** **{ 0x00f99, 0x00fbc, 0, NULL, NULL },
-** ** **{ 0x009c1, 0x009c4, 0, NULL, NULL },
-** ** **{ 0x00730, 0x0074a, 0, NULL, NULL },
-** ** **{ 0x00300, 0x0036f, 0, NULL, NULL },
-** ** **{ 0x03030, 0x0303e, 2, NULL, NULL },
-** ** **{ 0x01b34, 0x01b34, 0, NULL, NULL },
-** ** **{ 0x1d1aa, 0x1d1ad, 0, NULL, NULL },
-** ** **{ 0x00dca, 0x00dca, 0, NULL, NULL },
-** ** **{ 0x006d6, 0x006e4, 0, NULL, NULL },
-** ** **{ 0x00f86, 0x00f87, 0, NULL, NULL },
-** ** **{ 0x00b3f, 0x00b3f, 0, NULL, NULL },
-** ** **{ 0x0fe30, 0x0fe6f, 2, NULL, NULL },
-** ** **{ 0x01039, 0x01039, 0, NULL, NULL },
-** ** **{ 0x0094d, 0x0094d, 0, NULL, NULL },
-** ** **{ 0x00c55, 0x00c56, 0, NULL, NULL },
-** ** **{ 0x00488, 0x00489, 0, NULL, NULL },
-** ** **{ 0x00e47, 0x00e4e, 0, NULL, NULL },
-** ** **{ 0x00a81, 0x00a82, 0, NULL, NULL },
-** ** **{ 0x00ac1, 0x00ac5, 0, NULL, NULL },
-** ** **{ 0x0202a, 0x0202e, 0, NULL, NULL },
-** ** **{ 0x00dd6, 0x00dd6, 0, NULL, NULL },
-** ** **{ 0x018a9, 0x018a9, 0, NULL, NULL },
-** ** **{ 0x0064b, 0x0065e, 0, NULL, NULL },
-** ** **{ 0x00abc, 0x00abc, 0, NULL, NULL },
-** ** **{ 0x00b82, 0x00b82, 0, NULL, NULL },
-** ** **{ 0x00f39, 0x00f39, 0, NULL, NULL },
-** ** **{ 0x020d0, 0x020ef, 0, NULL, NULL },
-** ** **{ 0x01dfe, 0x01dff, 0, NULL, NULL },
-** ** **{ 0x30000, 0x3fffd, 2, NULL, NULL },
-** ** **{ 0x00711, 0x00711, 0, NULL, NULL },
-** ** **{ 0x0fe00, 0x0fe0f, 0, NULL, NULL },
-** ** **{ 0x0180b, 0x0180d, 0, NULL, NULL },
-** ** **{ 0x10a3f, 0x10a3f, 0, NULL, NULL },
-** ** **{ 0x00981, 0x00981, 0, NULL, NULL },
-** ** **{ 0x0a825, 0x0a826, 0, NULL, NULL },
-** ** **{ 0x00941, 0x00948, 0, NULL, NULL },
-** ** **{ 0x01b6b, 0x01b73, 0, NULL, NULL },
-** ** **{ 0x00e31, 0x00e31, 0, NULL, NULL },
-** ** **{ 0x0fe10, 0x0fe19, 2, NULL, NULL },
-** ** **{ 0x00a01, 0x00a02, 0, NULL, NULL },
-** ** **{ 0x00a4b, 0x00a4d, 0, NULL, NULL },
-** ** **{ 0x00f18, 0x00f19, 0, NULL, NULL },
-** ** **{ 0x00fc6, 0x00fc6, 0, NULL, NULL },
-** ** **{ 0x02e80, 0x03029, 2, NULL, NULL },
-** ** **{ 0x00b56, 0x00b56, 0, NULL, NULL },
-** ** **{ 0x009bc, 0x009bc, 0, NULL, NULL },
-** ** **{ 0x005c7, 0x005c7, 0, NULL, NULL },
-** ** **{ 0x02060, 0x02063, 0, NULL, NULL },
-** ** **{ 0x00c3e, 0x00c40, 0, NULL, NULL },
-** ** **{ 0x10a05, 0x10a06, 0, NULL, NULL },
-};
-
-struct utf8_width_entry** ** ** *utf8_width_root = NULL;
-
-int** utf8_overlap(struct utf8_width_entry *, struct
utf8_width_entry
Post by Kohei Suzuki
*);
** u_int** ** ** ** utf8_combine(const struct utf8_data *);
** u_int** ** ** ** utf8_width(const struct utf8_data *);
@@ -257,48 +83,6 @@ utf8_append(struct utf8_data *utf8data,
u_char ch)
Post by Kohei Suzuki
** ** ** **return (0);
** }
-/* Check if two width tree entries overlap. */
-int
-utf8_overlap(struct utf8_width_entry *item1, struct
utf8_width_entry
Post by Kohei Suzuki
*item2)
-{
-** ** **if (item1->first >= item2->first && item1->first <=
item2->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item1->last >= item2->first && item1->last <=
item2->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item2->first >= item1->first && item2->first <=
item1->last)
-** ** ** ** ** ** **return (1);
-** ** **if (item2->last >= item1->first && item2->last <=
item1->last)
-** ** ** ** ** ** **return (1);
-** ** **return (0);
-}
-
-/* Build UTF-8 width tree. */
-void
-utf8_build(void)
-{
-** ** **struct utf8_width_entry **ptr, *item, *node;
-** ** **u_int** ** ** ** ** ** ** ** ** ** **i, j;
-
-** ** **for (i = 0; i < nitems(utf8_width_table); i++) {
-** ** ** ** ** ** **item = &utf8_width_table[i];
-
-** ** ** ** ** ** **for (j = 0; j < nitems(utf8_width_table);
j++) {
Post by Kohei Suzuki
-** ** ** ** ** ** ** ** ** ** **if (i != j && utf8_overlap(item,
&utf8_width_table[j]))
-** ** ** ** ** ** ** ** ** ** ** ** ** ** **log_fatalx("utf8
%u %u", i, j);
-** ** ** ** ** ** **}
-
-** ** ** ** ** ** **ptr = &utf8_width_root;
-** ** ** ** ** ** **while (*ptr != NULL) {
-** ** ** ** ** ** ** ** ** ** **node = *ptr;
-** ** ** ** ** ** ** ** ** ** **if (item->last < node->first)
-** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr = &node->left;
-** ** ** ** ** ** ** ** ** ** **else if (item->first >
node->last)
Post by Kohei Suzuki
-** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr = &node->right;
-** ** ** ** ** ** **}
-** ** ** ** ** ** ***ptr = item;
-** ** **}
-}
-
** /* Combine UTF-8 into 32-bit Unicode. */
** u_int
** utf8_combine(const struct utf8_data *utf8data)
@@ -342,25 +126,14 @@ utf8_split2(u_int uc, u_char *ptr)
** ** ** **return (1);
** }
-/* Lookup width of UTF-8 data in tree. */
** u_int
** utf8_width(const struct utf8_data *utf8data)
** {
-** ** **struct utf8_width_entry *item;
-** ** **u_int** ** ** ** ** ** ** ** ** ** value;
-
-** ** **value = utf8_combine(utf8data);
-
-** ** **item = utf8_width_root;
-** ** **while (item != NULL) {
-** ** ** ** ** ** **if (value < item->first)
-** ** ** ** ** ** ** ** ** ** **item = item->left;
-** ** ** ** ** ** **else if (value > item->last)
-** ** ** ** ** ** ** ** ** ** **item = item->right;
-** ** ** ** ** ** **else
-** ** ** ** ** ** ** ** ** ** **return (item->width);
-** ** **}
-** ** **return (1);
+** ** **int width;
+
+** ** **width = wcwidth(utf8_combine(utf8data));
+
+** ** **return (width <= -1 ? 1 : width);
** }
** /*
--
2.4.1
------------------------------------------------------------------------------
Post by Kohei Suzuki
One dashboard for servers and applications across
Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable
Insights
Deep dive visibility with transaction tracing using APM Insight.
[6]http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
tmux-users mailing list
[8]https://lists.sourceforge.net/lists/listinfo/tmux-users
References
Visible links
6. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
8. https://lists.sourceforge.net/lists/listinfo/tmux-users
Nicholas Marriott
2015-05-18 14:26:49 UTC
Permalink
Hi

I think you will have another table of ambiguous width characters in
utf8.c which it can check (maybe depending on LOCALE, I guess that is
how wcwidth does it).
Post by Kohei Suzuki
The character ranges are listed in
[1]http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt .
"A" means ambiguous width as described in
[2]http://www.unicode.org/reports/tr11/#Definitions .
Kohei Suzuki
2015-05-18 23:16 GMT+09:00 Nicholas Marriott
Hi
How does wcwidth figure this out? What are the character ranges?
** ** Thank you for reviewing.
** ** Okey, then how about adding a new option "ambiguous-width" which
controls
** ** the width of East Asian ambiguous width characters?
** ** It is set to 1 by default, and users can set it to 2 by
`set-option
** ** ambiguous-width 2` .
** ** Is it acceptable?
** ** Kohei Suzuki
** ** 2015-05-18 2:08 GMT+09:00 Nicholas Marriott
** ** ** Hi
** ** ** We can't do this because tmux must know the width of the UTF-8
character
** ** ** but the locale may not be UTF-8.
** ** ** >** ** Several characters' width are depending on locale.
They're called
** ** ** East
** ** ** >** ** Asian Width. For instance, U+03B1 (GREEK SMALL LETTER
ALPHA) has
** ** ** width 1
** ** ** >** ** in most locales, but it has width 2 in some East Asian
locales
** ** ** (e.g.
** ** ** >** ** Japanese).
** ** ** >
** ** ** >** ** Kohei Suzuki
** ** ** >
** ** ** > References
** ** ** >
** ** ** >** ** Visible links
** ** ** > From 6324eb0bef76c9ec0d214cefa433efa1493f1845 Mon Sep 17
00:00:00 2001
** ** ** > Date: Mon, 18 May 2015 01:28:29 +0900
** ** ** > Subject: [PATCH] Use wcwidth(1) to calculate character width
** ** ** >
** ** ** > Several characters' width are depending on locale. They're
called East
** ** ** > Asian Width. For instance, U+03B1 (GREEK SMALL LETTER ALPHA)
has width
** ** ** 1
** ** ** > in most locales, but it has width 2 in some East Asian
locales (e.g.
** ** ** > Japanese).
** ** ** > ---
** ** ** >** server.c |** **1 -
** ** ** >** tmux.h** **|** **1 -
** ** ** >** utf8.c** **| 239
** ** **
++-------------------------------------------------------------
** ** ** >** 3 files changed, 6 insertions(+), 235 deletions(-)
** ** ** >
** ** ** > diff --git a/server.c b/server.c
** ** ** > index 738abe1..3c164ff 100644
** ** ** > --- a/server.c
** ** ** > +++ b/server.c
** ** ** >** ** ** **TAILQ_INIT(&session_groups);
** ** ** >** ** ** **mode_key_init_trees();
** ** ** >** ** ** **key_bindings_init();
** ** ** > -** ** **utf8_build();
** ** ** >
** ** ** >** ** ** **start_time = time(NULL);
** ** ** >** ** ** **log_debug("socket path %s", socket_path);
** ** ** > diff --git a/tmux.h b/tmux.h
** ** ** > index 054a859..7a6265a 100644
** ** ** > --- a/tmux.h
** ** ** > +++ b/tmux.h
** ** ** **session_group_synchronize1(struct session *, struct session
*);
** ** ** >** void** ** ** ** ** session_renumber_windows(struct session
*);
** ** ** >
** ** ** >** /* utf8.c */
** ** ** > -void** ** ** ** ** utf8_build(void);
** ** ** >** void** ** ** ** ** utf8_set(struct utf8_data *, u_char);
** ** ** >** int** ** ** ** ** **utf8_open(struct utf8_data *, u_char);
** ** ** >** int** ** ** ** ** **utf8_append(struct utf8_data *,
u_char);
** ** ** > diff --git a/utf8.c b/utf8.c
** ** ** > index 76b4846..4a84f20 100644
** ** ** > --- a/utf8.c
** ** ** > +++ b/utf8.c
** ** ** >
** ** ** >** #include <stdlib.h>
** ** ** >** #include <string.h>
** ** ** > +#include <wchar.h>
** ** ** >
** ** ** >** #include "tmux.h"
** ** ** >
** ** ** > -struct utf8_width_entry {
** ** ** > -** ** **u_int** **first;
** ** ** > -** ** **u_int** **last;
** ** ** > -
** ** ** > -** ** **int** ** **width;
** ** ** > -
** ** ** > -** ** **struct utf8_width_entry *left;
** ** ** > -** ** **struct utf8_width_entry *right;
** ** ** > -};
** ** ** > -
** ** ** > -/* Random order. Not optimal but it'll do for now... */
** ** ** > -struct utf8_width_entry utf8_width_table[] = {
** ** ** > -** ** **{ 0x00951, 0x00954, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ccc, 0x00ccd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0fff9, 0x0fffb, 0, NULL, NULL },
** ** ** > -** ** **{ 0x20000, 0x2fffd, 2, NULL, NULL },
** ** ** > -** ** **{ 0x00ebb, 0x00ebc, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01932, 0x01932, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0070f, 0x0070f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a70, 0x00a71, 0, NULL, NULL },
** ** ** > -** ** **{ 0x02329, 0x02329, 2, NULL, NULL },
** ** ** > -** ** **{ 0x00acd, 0x00acd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ac7, 0x00ac8, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a3c, 0x00a3c, 0, NULL, NULL },
** ** ** > -** ** **{ 0x009cd, 0x009cd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00591, 0x005bd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01058, 0x01059, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0ffe0, 0x0ffe6, 2, NULL, NULL },
** ** ** > -** ** **{ 0x01100, 0x0115f, 2, NULL, NULL },
** ** ** > -** ** **{ 0x0fe20, 0x0fe23, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0302a, 0x0302f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01772, 0x01773, 0, NULL, NULL },
** ** ** > -** ** **{ 0x005bf, 0x005bf, 0, NULL, NULL },
** ** ** > -** ** **{ 0x006ea, 0x006ed, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00bc0, 0x00bc0, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00962, 0x00963, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01732, 0x01734, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00d41, 0x00d43, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01b42, 0x01b42, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a41, 0x00a42, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00eb4, 0x00eb9, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00b01, 0x00b01, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00e34, 0x00e3a, 0, NULL, NULL },
** ** ** > -** ** **{ 0x03040, 0x03098, 2, NULL, NULL },
** ** ** > -** ** **{ 0x0093c, 0x0093c, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00c4a, 0x00c4d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01032, 0x01032, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f37, 0x00f37, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00901, 0x00902, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00cbf, 0x00cbf, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0a806, 0x0a806, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00dd2, 0x00dd4, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f71, 0x00f7e, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01752, 0x01753, 0, NULL, NULL },
** ** ** > -** ** **{ 0x1d242, 0x1d244, 0, NULL, NULL },
** ** ** > -** ** **{ 0x005c1, 0x005c2, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0309b, 0x0a4cf, 2, NULL, NULL },
** ** ** > -** ** **{ 0xe0100, 0xe01ef, 0, NULL, NULL },
** ** ** > -** ** **{ 0x017dd, 0x017dd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00600, 0x00603, 0, NULL, NULL },
** ** ** > -** ** **{ 0x009e2, 0x009e3, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00cc6, 0x00cc6, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0a80b, 0x0a80b, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01712, 0x01714, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00b3c, 0x00b3c, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01b00, 0x01b03, 0, NULL, NULL },
** ** ** > -** ** **{ 0x007eb, 0x007f3, 0, NULL, NULL },
** ** ** > -** ** **{ 0xe0001, 0xe0001, 0, NULL, NULL },
** ** ** > -** ** **{ 0x1d185, 0x1d18b, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0feff, 0x0feff, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01b36, 0x01b3a, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01920, 0x01922, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00670, 0x00670, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f90, 0x00f97, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01927, 0x01928, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0200b, 0x0200f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0ff00, 0x0ff60, 2, NULL, NULL },
** ** ** > -** ** **{ 0x0f900, 0x0faff, 2, NULL, NULL },
** ** ** > -** ** **{ 0x0fb1e, 0x0fb1e, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00cbc, 0x00cbc, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00eb1, 0x00eb1, 0, NULL, NULL },
** ** ** > -** ** **{ 0x10a38, 0x10a3a, 0, NULL, NULL },
** ** ** > -** ** **{ 0x007a6, 0x007b0, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f80, 0x00f84, 0, NULL, NULL },
** ** ** > -** ** **{ 0x005c4, 0x005c5, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0ac00, 0x0d7a3, 2, NULL, NULL },
** ** ** > -** ** **{ 0x017c9, 0x017d3, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00d4d, 0x00d4d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x1d167, 0x1d169, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01036, 0x01037, 0, NULL, NULL },
** ** ** > -** ** **{ 0xe0020, 0xe007f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f35, 0x00f35, 0, NULL, NULL },
** ** ** > -** ** **{ 0x017b4, 0x017b5, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0206a, 0x0206f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00c46, 0x00c48, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01939, 0x0193b, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01dc0, 0x01dca, 0, NULL, NULL },
** ** ** > -** ** **{ 0x10a0c, 0x10a0f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0102d, 0x01030, 0, NULL, NULL },
** ** ** > -** ** **{ 0x017c6, 0x017c6, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ec8, 0x00ecd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00b41, 0x00b43, 0, NULL, NULL },
** ** ** > -** ** **{ 0x017b7, 0x017bd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x1d173, 0x1d182, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a47, 0x00a48, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0232a, 0x0232a, 2, NULL, NULL },
** ** ** > -** ** **{ 0x01b3c, 0x01b3c, 0, NULL, NULL },
** ** ** > -** ** **{ 0x10a01, 0x10a03, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ae2, 0x00ae3, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00483, 0x00486, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0135f, 0x0135f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01a17, 0x01a18, 0, NULL, NULL },
** ** ** > -** ** **{ 0x006e7, 0x006e8, 0, NULL, NULL },
** ** ** > -#ifndef __APPLE__
** ** ** > -** ** **{ 0x03099, 0x0309a, 0, NULL, NULL },
** ** ** > -#endif
** ** ** > -** ** **{ 0x00b4d, 0x00b4d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ce2, 0x00ce3, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00bcd, 0x00bcd, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00610, 0x00615, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f99, 0x00fbc, 0, NULL, NULL },
** ** ** > -** ** **{ 0x009c1, 0x009c4, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00730, 0x0074a, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00300, 0x0036f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x03030, 0x0303e, 2, NULL, NULL },
** ** ** > -** ** **{ 0x01b34, 0x01b34, 0, NULL, NULL },
** ** ** > -** ** **{ 0x1d1aa, 0x1d1ad, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00dca, 0x00dca, 0, NULL, NULL },
** ** ** > -** ** **{ 0x006d6, 0x006e4, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f86, 0x00f87, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00b3f, 0x00b3f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0fe30, 0x0fe6f, 2, NULL, NULL },
** ** ** > -** ** **{ 0x01039, 0x01039, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0094d, 0x0094d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00c55, 0x00c56, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00488, 0x00489, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00e47, 0x00e4e, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a81, 0x00a82, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00ac1, 0x00ac5, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0202a, 0x0202e, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00dd6, 0x00dd6, 0, NULL, NULL },
** ** ** > -** ** **{ 0x018a9, 0x018a9, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0064b, 0x0065e, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00abc, 0x00abc, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00b82, 0x00b82, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f39, 0x00f39, 0, NULL, NULL },
** ** ** > -** ** **{ 0x020d0, 0x020ef, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01dfe, 0x01dff, 0, NULL, NULL },
** ** ** > -** ** **{ 0x30000, 0x3fffd, 2, NULL, NULL },
** ** ** > -** ** **{ 0x00711, 0x00711, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0fe00, 0x0fe0f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0180b, 0x0180d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x10a3f, 0x10a3f, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00981, 0x00981, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0a825, 0x0a826, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00941, 0x00948, 0, NULL, NULL },
** ** ** > -** ** **{ 0x01b6b, 0x01b73, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00e31, 0x00e31, 0, NULL, NULL },
** ** ** > -** ** **{ 0x0fe10, 0x0fe19, 2, NULL, NULL },
** ** ** > -** ** **{ 0x00a01, 0x00a02, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00a4b, 0x00a4d, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00f18, 0x00f19, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00fc6, 0x00fc6, 0, NULL, NULL },
** ** ** > -** ** **{ 0x02e80, 0x03029, 2, NULL, NULL },
** ** ** > -** ** **{ 0x00b56, 0x00b56, 0, NULL, NULL },
** ** ** > -** ** **{ 0x009bc, 0x009bc, 0, NULL, NULL },
** ** ** > -** ** **{ 0x005c7, 0x005c7, 0, NULL, NULL },
** ** ** > -** ** **{ 0x02060, 0x02063, 0, NULL, NULL },
** ** ** > -** ** **{ 0x00c3e, 0x00c40, 0, NULL, NULL },
** ** ** > -** ** **{ 0x10a05, 0x10a06, 0, NULL, NULL },
** ** ** > -};
** ** ** > -
** ** ** > -struct utf8_width_entry** ** ** *utf8_width_root = NULL;
** ** ** > -
** ** ** > -int** utf8_overlap(struct utf8_width_entry *, struct
utf8_width_entry
** ** ** *);
** ** ** >** u_int** ** ** ** utf8_combine(const struct utf8_data *);
** ** ** >** u_int** ** ** ** utf8_width(const struct utf8_data *);
** ** ** >
u_char ch)
** ** ** >** ** ** **return (0);
** ** ** >** }
** ** ** >
** ** ** > -/* Check if two width tree entries overlap. */
** ** ** > -int
** ** ** > -utf8_overlap(struct utf8_width_entry *item1, struct
utf8_width_entry
** ** ** *item2)
** ** ** > -{
** ** ** > -** ** **if (item1->first >= item2->first && item1->first <=
** ** ** item2->last)
** ** ** > -** ** ** ** ** ** **return (1);
** ** ** > -** ** **if (item1->last >= item2->first && item1->last <=
** ** ** item2->last)
** ** ** > -** ** ** ** ** ** **return (1);
** ** ** > -** ** **if (item2->first >= item1->first && item2->first <=
** ** ** item1->last)
** ** ** > -** ** ** ** ** ** **return (1);
** ** ** > -** ** **if (item2->last >= item1->first && item2->last <=
** ** ** item1->last)
** ** ** > -** ** ** ** ** ** **return (1);
** ** ** > -** ** **return (0);
** ** ** > -}
** ** ** > -
** ** ** > -/* Build UTF-8 width tree. */
** ** ** > -void
** ** ** > -utf8_build(void)
** ** ** > -{
** ** ** > -** ** **struct utf8_width_entry **ptr, *item, *node;
** ** ** > -** ** **u_int** ** ** ** ** ** ** ** ** ** **i, j;
** ** ** > -
** ** ** > -** ** **for (i = 0; i < nitems(utf8_width_table); i++) {
** ** ** > -** ** ** ** ** ** **item = &utf8_width_table[i];
** ** ** > -
** ** ** > -** ** ** ** ** ** **for (j = 0; j <
nitems(utf8_width_table); j++) {
** ** ** > -** ** ** ** ** ** ** ** ** ** **if (i != j &&
utf8_overlap(item,
** ** ** &utf8_width_table[j]))
** ** ** > -** ** ** ** ** ** ** ** ** ** ** ** ** **
** ** ** %u %u", i, j);
** ** ** > -** ** ** ** ** ** **}
** ** ** > -
** ** ** > -** ** ** ** ** ** **ptr = &utf8_width_root;
** ** ** > -** ** ** ** ** ** **while (*ptr != NULL) {
** ** ** > -** ** ** ** ** ** ** ** ** ** **node = *ptr;
** ** ** > -** ** ** ** ** ** ** ** ** ** **if (item->last <
node->first)
** ** ** > -** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr =
&node->left;
** ** ** > -** ** ** ** ** ** ** ** ** ** **else if (item->first >
node->last)
** ** ** > -** ** ** ** ** ** ** ** ** ** ** ** ** ** **ptr =
&node->right;
** ** ** > -** ** ** ** ** ** **}
** ** ** > -** ** ** ** ** ** ***ptr = item;
** ** ** > -** ** **}
** ** ** > -}
** ** ** > -
** ** ** >** /* Combine UTF-8 into 32-bit Unicode. */
** ** ** >** u_int
** ** ** >** utf8_combine(const struct utf8_data *utf8data)
** ** ** >** ** ** **return (1);
** ** ** >** }
** ** ** >
** ** ** > -/* Lookup width of UTF-8 data in tree. */
** ** ** >** u_int
** ** ** >** utf8_width(const struct utf8_data *utf8data)
** ** ** >** {
** ** ** > -** ** **struct utf8_width_entry *item;
** ** ** > -** ** **u_int** ** ** ** ** ** ** ** ** ** value;
** ** ** > -
** ** ** > -** ** **value = utf8_combine(utf8data);
** ** ** > -
** ** ** > -** ** **item = utf8_width_root;
** ** ** > -** ** **while (item != NULL) {
** ** ** > -** ** ** ** ** ** **if (value < item->first)
** ** ** > -** ** ** ** ** ** ** ** ** ** **item = item->left;
** ** ** > -** ** ** ** ** ** **else if (value > item->last)
** ** ** > -** ** ** ** ** ** ** ** ** ** **item = item->right;
** ** ** > -** ** ** ** ** ** **else
** ** ** > -** ** ** ** ** ** ** ** ** ** **return (item->width);
** ** ** > -** ** **}
** ** ** > -** ** **return (1);
** ** ** > +** ** **int width;
** ** ** > +
** ** ** > +** ** **width = wcwidth(utf8_combine(utf8data));
** ** ** > +
** ** ** > +** ** **return (width <= -1 ? 1 : width);
** ** ** >** }
** ** ** >
** ** ** >** /*
** ** ** > --
** ** ** > 2.4.1
** ** ** >
** ** ** >
** ** **
------------------------------------------------------------------------------
** ** ** > One dashboard for servers and applications across
** ** ** Physical-Virtual-Cloud
** ** ** > Widest out-of-the-box monitoring support with 50+
applications
** ** ** > Performance metrics, stats and reports that give you
Actionable
** ** ** Insights
** ** ** > Deep dive visibility with transaction tracing using APM
Insight.
** ** ** >
[6][10]http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
** ** ** > _______________________________________________
** ** ** > tmux-users mailing list
** ** ** >
[8][12]https://lists.sourceforge.net/lists/listinfo/tmux-users
References
** ** Visible links
** ** 6. [18]http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
** ** 8. [20]https://lists.sourceforge.net/lists/listinfo/tmux-users
References
Visible links
1. http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt
2. http://www.unicode.org/reports/tr11/#Definitions
10. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
12. https://lists.sourceforge.net/lists/listinfo/tmux-users
18. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
20. https://lists.sourceforge.net/lists/listinfo/tmux-users
Loading...