grub/grub-core/gnulib-fix-width.diff

232 lines
6.7 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c
index 7aa317c..02406ff 100644
--- a/lib/argp-fmtstream.c
+++ b/lib/argp-fmtstream.c
@@ -29,9 +29,11 @@
#include <errno.h>
#include <stdarg.h>
#include <ctype.h>
+#include <wchar.h>
#include "argp-fmtstream.h"
#include "argp-namefrob.h"
+#include "mbswidth.h"
#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
@@ -116,6 +118,51 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
#endif
#endif
+
+/* Return the pointer to the first character that doesn't fit in l columns. */
+static inline const ptrdiff_t
+add_width (const char *ptr, const char *end, size_t l)
+{
+ mbstate_t ps;
+ const char *ptr0 = ptr;
+
+ memset (&ps, 0, sizeof (ps));
+
+ while (ptr < end)
+ {
+ wchar_t wc;
+ size_t s, k;
+
+ s = mbrtowc (&wc, ptr, end - ptr, &ps);
+ if (s == (size_t) -1)
+ break;
+ if (s == (size_t) -2)
+ {
+ if (1 >= l)
+ break;
+ l--;
+ ptr++;
+ continue;
+ }
+
+ if (wc == '\e' && ptr + 3 < end
+ && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1')
+ && ptr[3] == 'm')
+ {
+ ptr += 4;
+ continue;
+ }
+
+ k = wcwidth (wc);
+
+ if (k >= l)
+ break;
+ l -= k;
+ ptr += s;
+ }
+ return ptr - ptr0;
+}
+
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
void
@@ -168,14 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
if (!nl)
{
+ size_t display_width = mbsnwidth (buf, fs->p - buf, MBSW_STOP_AT_NUL);
/* The buffer ends in a partial line. */
- if (fs->point_col + len < fs->rmargin)
+ if (fs->point_col + display_width < fs->rmargin)
{
/* The remaining buffer text is a partial line and fits
within the maximum line width. Advance point for the
characters to be written and stop scanning. */
- fs->point_col += len;
+ fs->point_col += display_width;
break;
}
else
@@ -183,14 +231,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
the end of the buffer. */
nl = fs->p;
}
- else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
- {
- /* The buffer contains a full line that fits within the maximum
- line width. Reset point and scan the next line. */
- fs->point_col = 0;
- buf = nl + 1;
- continue;
- }
+ else
+ {
+ size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL);
+ if (display_width < (ssize_t) fs->rmargin)
+ {
+ /* The buffer contains a full line that fits within the maximum
+ line width. Reset point and scan the next line. */
+ fs->point_col = 0;
+ buf = nl + 1;
+ continue;
+ }
+ }
/* This line is too long. */
r = fs->rmargin - 1;
@@ -226,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
char *p, *nextline;
int i;
- p = buf + (r + 1 - fs->point_col);
+ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col));
while (p >= buf && !isblank ((unsigned char) *p))
--p;
nextline = p + 1; /* This will begin the next line. */
@@ -244,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
{
/* A single word that is greater than the maximum line width.
Oh well. Put it on an overlong line by itself. */
- p = buf + (r + 1 - fs->point_col);
+ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col));
/* Find the end of the long word. */
if (p < nl)
do
@@ -278,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
&& fs->p > nextline)
{
/* The margin needs more blanks than we removed. */
- if (fs->end - fs->p > fs->wmargin + 1)
+ if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL)
+ > fs->wmargin + 1)
/* Make some space for them. */
{
size_t mv = fs->p - nextline;
diff --git a/lib/argp-help.c b/lib/argp-help.c
index 354f1e2..2914f47 100644
--- a/lib/argp-help.c
+++ b/lib/argp-help.c
@@ -50,6 +50,7 @@
#include "argp.h"
#include "argp-fmtstream.h"
#include "argp-namefrob.h"
+#include "mbswidth.h"
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
@@ -1452,7 +1453,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
/* Manually do line wrapping so that it (probably) won't get wrapped at
any embedded spaces. */
- space (stream, 1 + nl - cp);
+ space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL));
__argp_fmtstream_write (stream, cp, nl - cp);
}
diff --git a/lib/mbswidth.c b/lib/mbswidth.c
index 7c2dfce..baa4f27 100644
--- a/lib/mbswidth.c
+++ b/lib/mbswidth.c
@@ -90,6 +90,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags)
p++;
width++;
break;
+ case '\0':
+ if (flags & MBSW_STOP_AT_NUL)
+ return width;
default:
/* If we have a multibyte sequence, scan it up to its end. */
{
@@ -168,6 +171,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags)
{
unsigned char c = (unsigned char) *p++;
+ if (c == 0 && (flags & MBSW_STOP_AT_NUL))
+ return width;
+
if (isprint (c))
{
if (width == INT_MAX)
diff --git a/lib/mbswidth.h b/lib/mbswidth.h
index e9c0b03..d7207c5 100644
--- a/lib/mbswidth.h
+++ b/lib/mbswidth.h
@@ -45,6 +45,9 @@ extern "C" {
control characters and 1 otherwise. */
#define MBSW_REJECT_UNPRINTABLE 2
+/* If this bit is set \0 is treated as the end of string.
+ Otherwise it's treated as a normal one column width character. */
+#define MBSW_STOP_AT_NUL 4
/* Returns the number of screen columns needed for STRING. */
#define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */
diff --git a/modules/argp b/modules/argp
index 125046a..6f14d10 100644
--- a/modules/argp
+++ b/modules/argp
@@ -40,6 +40,7 @@ stdalign
strerror
memchr
memmove
+mbswidth
configure.ac:
gl_ARGP
diff --git a/modules/argp-tests b/modules/argp-tests
index 8f92a4d..0463927 100644
--- a/modules/argp-tests
+++ b/modules/argp-tests
@@ -1,11 +1,13 @@
Files:
tests/test-argp.c
tests/test-argp-2.sh
+tests/test-argp-2-utf.sh
Depends-on:
progname
Makefile.am:
TESTS += test-argp test-argp-2.sh
-check_PROGRAMS += test-argp
+TESTS += test-argp test-argp-2.sh test-argp-2-utf.sh
+check_PROGRAMS += test-argp test-argp-utf8
test_argp_LDADD = $(LDADD) @LIBINTL@