* grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len):

New function.
	(add_length): Likewise.
	(__argp_fmtstream_update): Handle strings with non-ASCII chars.
	* grub-core/gnulib/argp-fmtstream.h (__argp_get_display_len): New
	proto.
	* grub-core/gnulib/argp-help.c (argp_args_usage): Use
	__argp_get_display_len.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-02-26 19:07:59 +01:00
parent 7e8fac16ad
commit 585031cb92
4 changed files with 82 additions and 14 deletions

View file

@ -1,3 +1,14 @@
2012-02-25 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len):
New function.
(add_length): Likewise.
(__argp_fmtstream_update): Handle strings with non-ASCII chars.
* grub-core/gnulib/argp-fmtstream.h (__argp_get_display_len): New
proto.
* grub-core/gnulib/argp-help.c (argp_args_usage): Use
__argp_get_display_len.
2012-02-25 Vladimir Serbinenko <phcoder@gmail.com> 2012-02-25 Vladimir Serbinenko <phcoder@gmail.com>
$"..." support in scripts. $"..." support in scripts.

View file

@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <wchar.h>
#include "argp-fmtstream.h" #include "argp-fmtstream.h"
#include "argp-namefrob.h" #include "argp-namefrob.h"
@ -116,6 +117,54 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
#endif #endif
#endif #endif
size_t
__argp_get_display_len (char *beg, char *end)
{
char *ptr;
size_t r = 0;
mbstate_t ps;
memset (&ps, 0, sizeof (ps));
for (ptr = beg; ptr < end; )
{
wchar_t wc;
size_t s;
s = mbrtowc (&wc, ptr, end - ptr, &ps);
if (s == (size_t) -1)
break;
r += wcwidth (wc);
ptr += s;
}
return r;
}
static inline char *
add_length (char *ptr, char *end, size_t l)
{
mbstate_t ps;
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;
k = wcwidth (wc);
if (k >= l)
break;
l -= k;
ptr += s;
}
return ptr;
}
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the /* 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. */ end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
void void
@ -168,14 +217,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
if (!nl) if (!nl)
{ {
size_t display_len = __argp_get_display_len (buf, fs->p);
/* The buffer ends in a partial line. */ /* The buffer ends in a partial line. */
if (fs->point_col + len < fs->rmargin) if (fs->point_col + display_len < fs->rmargin)
{ {
/* The remaining buffer text is a partial line and fits /* The remaining buffer text is a partial line and fits
within the maximum line width. Advance point for the within the maximum line width. Advance point for the
characters to be written and stop scanning. */ characters to be written and stop scanning. */
fs->point_col += len; fs->point_col += display_len;
break; break;
} }
else else
@ -183,14 +233,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
the end of the buffer. */ the end of the buffer. */
nl = fs->p; nl = fs->p;
} }
else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) else
{ {
/* The buffer contains a full line that fits within the maximum size_t display_len = __argp_get_display_len (buf, nl);
line width. Reset point and scan the next line. */ if (display_len < (ssize_t) fs->rmargin)
fs->point_col = 0; {
buf = nl + 1; /* The buffer contains a full line that fits within the maximum
continue; line width. Reset point and scan the next line. */
} fs->point_col = 0;
buf = nl + 1;
continue;
}
}
/* This line is too long. */ /* This line is too long. */
r = fs->rmargin - 1; r = fs->rmargin - 1;
@ -226,7 +280,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
char *p, *nextline; char *p, *nextline;
int i; int i;
p = buf + (r + 1 - fs->point_col); p = add_length (buf, fs->p, (r + 1 - fs->point_col));
while (p >= buf && !isblank ((unsigned char) *p)) while (p >= buf && !isblank ((unsigned char) *p))
--p; --p;
nextline = p + 1; /* This will begin the next line. */ nextline = p + 1; /* This will begin the next line. */
@ -244,7 +298,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
{ {
/* A single word that is greater than the maximum line width. /* A single word that is greater than the maximum line width.
Oh well. Put it on an overlong line by itself. */ Oh well. Put it on an overlong line by itself. */
p = buf + (r + 1 - fs->point_col); p = add_length (buf, fs->p, (r + 1 - fs->point_col));
/* Find the end of the long word. */ /* Find the end of the long word. */
if (p < nl) if (p < nl)
do do
@ -278,7 +332,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
&& fs->p > nextline) && fs->p > nextline)
{ {
/* The margin needs more blanks than we removed. */ /* The margin needs more blanks than we removed. */
if (fs->end - fs->p > fs->wmargin + 1) if (__argp_get_display_len (fs->p, fs->end) > fs->wmargin + 1)
/* Make some space for them. */ /* Make some space for them. */
{ {
size_t mv = fs->p - nextline; size_t mv = fs->p - nextline;

View file

@ -335,6 +335,9 @@ __argp_fmtstream_point (argp_fmtstream_t __fs)
return __fs->point_col >= 0 ? __fs->point_col : 0; return __fs->point_col >= 0 ? __fs->point_col : 0;
} }
size_t
__argp_get_display_len (char *beg, char *end);
#if !_LIBC #if !_LIBC
#undef __argp_fmtstream_putc #undef __argp_fmtstream_putc
#undef __argp_fmtstream_puts #undef __argp_fmtstream_puts

View file

@ -1448,7 +1448,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 /* Manually do line wrapping so that it (probably) won't get wrapped at
any embedded spaces. */ any embedded spaces. */
space (stream, 1 + nl - cp); space (stream, 1 + __argp_get_display_len (cp, nl));
__argp_fmtstream_write (stream, cp, nl - cp); __argp_fmtstream_write (stream, cp, nl - cp);
} }