mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-10-31 22:26:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			232 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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@
 | 
