]> granicus.if.org Git - neomutt/commitdiff
Make mutt_FormatString()'s string truncation multibyte aware
authorRocco Rutte <pdmef@gmx.net>
Fri, 28 Sep 2007 09:06:43 +0000 (11:06 +0200)
committerRocco Rutte <pdmef@gmx.net>
Fri, 28 Sep 2007 09:06:43 +0000 (11:06 +0200)
curs_lib.c
muttlib.c
protos.h

index 8fdb6816543d0c9b4720c509cc2255a3a93de3d0..cb1947ab60cd4331450446b9eaab0abe5cb2d21d 100644 (file)
@@ -822,6 +822,38 @@ void mutt_paddstr (int n, const char *s)
     addch (' ');
 }
 
+/* See how many bytes to copy from string so its at most maxlen bytes
+ * long and maxwid columns wide */
+int mutt_wstr_trunc (const char *src, size_t maxlen, size_t maxwid, size_t *width)
+{
+  wchar_t wc;
+  int w = 0, l = 0, cl;
+  size_t cw, n;
+  mbstate_t mbstate;
+
+  if (!src)
+    goto out;
+
+  n = mutt_strlen (src);
+
+  memset (&mbstate, 0, sizeof (mbstate));
+  for (w = 0; n && (cl = mbrtowc (&wc, src, n, &mbstate)); src += cl, n -= cl)
+  {
+    if (cl == (size_t)(-1) || cl == (size_t)(-2))
+      cw = cl = 1;
+    else
+      cw = wcwidth (wc);
+    if (cl + l > maxlen || cw + w > maxwid)
+      break;
+    l += cl;
+    w += cw;
+  }
+out:
+  if (width)
+    *width = w;
+  return l;
+}
+
 /*
  * returns the number of bytes the first (multibyte) character
  * of input consumes:
index ca06d27cfa5427237313b32ed3586df11ba1eba2..2b7be974a61b2bf9a31a3fbc2b69d1348f0254e8 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -1232,16 +1232,16 @@ void mutt_FormatString (char *dest,             /* output buffer */
          else if (soft && pad < 0)
          {
            /* set wptr and wlen back just enough bytes to make sure buf
-            * fits on screen, col needs no adjustments as we skip more input
-            * currently multibyte unaware */
+            * fits on screen, \0-terminate dest so mutt_wstr_trunc()
+            * can correctly compute string's length */
            if (pad < -wlen)
              pad = -wlen;
-           wlen += pad;
-           wptr += pad;
+           *wptr = 0;
+           wlen = mutt_wstr_trunc (dest, wlen + pad, col + pad, &col);
+           wptr = dest + wlen;
          }
          if (len + wlen > destlen)
-           len = destlen - wlen;
-         /* copy as much of buf as possible: multibyte unaware */
+           len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL);
          memcpy (wptr, buf, len);
          wptr += len;
          wlen += len;
@@ -1304,7 +1304,7 @@ void mutt_FormatString (char *dest,               /* output buffer */
        }
        
        if ((len = mutt_strlen (buf)) + wlen > destlen)
-         len = (destlen - wlen > 0) ? (destlen - wlen) : 0;
+         len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL);
 
        memcpy (wptr, buf, len);
        wptr += len;
index 210ef6e7416b4c9ed35b3156ea6ffb5feee8cf53..7a156b695246a1adf04233d27969dad3684d8e71 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -355,6 +355,7 @@ int mutt_search_command (int, int);
 int mutt_smtp_send (const ADDRESS *, const ADDRESS *, const ADDRESS *,
                     const ADDRESS *, const char *, int);
 #endif
+int mutt_wstr_trunc (const char *, size_t, size_t, size_t *);
 int mutt_charlen (const char *s, int *);
 int mutt_strwidth (const char *);
 int mutt_compose_menu (HEADER *, char *, size_t, HEADER *);