mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
ed: add unicode support for the l (list) command
Use mbrtowc()/iswprint()/wcwidth() in put_tty_line() so that the l command displays valid multibyte characters as-is instead of escaping each byte as octal. Column wrapping now correctly accounts for character display width (including double-width CJK characters). Invalid or incomplete UTF-8 sequences and non-printable characters are still escaped as octal. Differential Revision: https://reviews.freebsd.org/D55365
This commit is contained in:
1 parent
7c2c2c2a22
commit
5df6aca109
2 files changed
+55
-19
No files matched your search
@@ -36,6 +36,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#define ERR (-2)
|
||||
#define EMOD (-3)
|
||||
|
||||
+53
-19
@@ -298,13 +298,49 @@ put_tty_line(const char *s, int l, long n, int gflag)
|
||||
int col = 0;
|
||||
int lc = 0;
|
||||
char *cp;
|
||||
wchar_t wc;
|
||||
mbstate_t mbs;
|
||||
size_t clen;
|
||||
int w;
|
||||
|
||||
if (gflag & GNP) {
|
||||
printf("%ld\t", n);
|
||||
col = 8;
|
||||
}
|
||||
for (; l--; s++) {
|
||||
if ((gflag & GLS) && ++col > cols) {
|
||||
for (; l > 0;) {
|
||||
if (!(gflag & GLS)) {
|
||||
putchar(*s++);
|
||||
l--;
|
||||
continue;
|
||||
}
|
||||
/* GLS mode: try to decode a multibyte character */
|
||||
memset(&mbs, 0, sizeof(mbs));
|
||||
clen = mbrtowc(&wc, s, l, &mbs);
|
||||
if (clen != (size_t)-1 && clen != (size_t)-2 &&
|
||||
clen > 1 && iswprint(wc) && (w = wcwidth(wc)) >= 0) {
|
||||
/* printable multibyte character */
|
||||
if (col + w > cols) {
|
||||
fputs("\\\n", stdout);
|
||||
col = 0;
|
||||
#ifndef BACKWARDS
|
||||
if (!scripted && !isglobal && ++lc > rows) {
|
||||
lc = 0;
|
||||
fputs("Press <RETURN> to continue... ",
|
||||
stdout);
|
||||
fflush(stdout);
|
||||
if (get_tty_line() < 0)
|
||||
return ERR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
col += w;
|
||||
fwrite(s, 1, clen, stdout);
|
||||
s += clen;
|
||||
l -= clen;
|
||||
continue;
|
||||
}
|
||||
/* single byte: ASCII printable, escape sequence, or octal */
|
||||
if (++col > cols) {
|
||||
fputs("\\\n", stdout);
|
||||
col = 1;
|
||||
#ifndef BACKWARDS
|
||||
@@ -317,24 +353,22 @@ put_tty_line(const char *s, int l, long n, int gflag)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (gflag & GLS) {
|
||||
if (31 < *s && *s < 127 && *s != '\\')
|
||||
putchar(*s);
|
||||
else {
|
||||
putchar('\\');
|
||||
col++;
|
||||
if (*s && (cp = strchr(ESCAPES, *s)) != NULL)
|
||||
putchar(ESCCHARS[cp - ESCAPES]);
|
||||
else {
|
||||
putchar((((unsigned char) *s & 0300) >> 6) + '0');
|
||||
putchar((((unsigned char) *s & 070) >> 3) + '0');
|
||||
putchar(((unsigned char) *s & 07) + '0');
|
||||
col += 2;
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
if (31 < *s && *s < 127 && *s != '\\')
|
||||
putchar(*s);
|
||||
else {
|
||||
putchar('\\');
|
||||
col++;
|
||||
if (*s && (cp = strchr(ESCAPES, *s)) != NULL)
|
||||
putchar(ESCCHARS[cp - ESCAPES]);
|
||||
else {
|
||||
putchar((((unsigned char) *s & 0300) >> 6) + '0');
|
||||
putchar((((unsigned char) *s & 070) >> 3) + '0');
|
||||
putchar(((unsigned char) *s & 07) + '0');
|
||||
col += 2;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
l--;
|
||||
}
|
||||
#ifndef BACKWARDS
|
||||
if (gflag & GLS)
|
||||
|
||||
Reference in new issue
Block a user