]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len):
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 26 Feb 2012 18:07:59 +0000 (19:07 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 26 Feb 2012 18:07:59 +0000 (19:07 +0100)
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.

ChangeLog
grub-core/gnulib/argp-fmtstream.c
grub-core/gnulib/argp-fmtstream.h
grub-core/gnulib/argp-help.c

index 61e5b7c123ecfa0dd843ebc7be053675b08aa00d..542d9fd2a3554e1b370254103f49561f27099cf5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        $"..." support in scripts.
index 70bbebc21a22d52cfd6820875805aa7c18a265b2..f0ceade28e982d216b14c00da18c92bdf18590ff 100644 (file)
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <ctype.h>
+#include <wchar.h>
 
 #include "argp-fmtstream.h"
 #include "argp-namefrob.h"
@@ -116,6 +117,54 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
 #endif
 #endif
 \f
+
+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
    end of its buffer.  This code is mostly from glibc stdio/linewrap.c.  */
 void
@@ -168,14 +217,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
 
       if (!nl)
         {
+         size_t display_len = __argp_get_display_len (buf, fs->p);
           /* 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
                  within the maximum line width.  Advance point for the
                  characters to be written and stop scanning.  */
-              fs->point_col += len;
+              fs->point_col += display_len;
               break;
             }
           else
@@ -183,14 +233,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_len = __argp_get_display_len (buf, nl);
+         if (display_len < (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 +280,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
           char *p, *nextline;
           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))
             --p;
           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.
                  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.  */
               if (p < nl)
                 do
@@ -278,7 +332,7 @@ __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 (__argp_get_display_len (fs->p, fs->end) > fs->wmargin + 1)
                 /* Make some space for them.  */
                 {
                   size_t mv = fs->p - nextline;
index b913d1b254bb324b8a97c9e4004ca206460144c8..53ba3eeb36f8fbcd5655f9f6c4ba6724dd0c1914 100644 (file)
@@ -335,6 +335,9 @@ __argp_fmtstream_point (argp_fmtstream_t __fs)
   return __fs->point_col >= 0 ? __fs->point_col : 0;
 }
 
+size_t
+__argp_get_display_len (char *beg, char *end);
+
 #if !_LIBC
 #undef __argp_fmtstream_putc
 #undef __argp_fmtstream_puts
index 5b6d950beaabb34f90cd2b0d9dcd0c4978827222..c82e38e75117e2b39d0d180a1b7c292300b87621 100644 (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
          any embedded spaces.  */
-      space (stream, 1 + nl - cp);
+      space (stream, 1 + __argp_get_display_len (cp, nl));
 
       __argp_fmtstream_write (stream, cp, nl - cp);
     }