commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-773-g2a28ab5


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-773-g2a28ab5
Date: Sat, 15 Oct 2016 07:21:33 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=2a28ab58762f9ae9cd00ca3e467ee6f90f241201

The branch, master has been updated
       via  2a28ab58762f9ae9cd00ca3e467ee6f90f241201 (commit)
       via  06c13b3498a236a518df76bdb1b9895540c1df3b (commit)
      from  d4a938f6d533981a77ddd55972e4c98b016d03d3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2a28ab58762f9ae9cd00ca3e467ee6f90f241201
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Oct 15 10:11:23 2016 +0300

    Rewrite parseopt help routines using wordwrap streams
    
    * include/mailutils/stream.h (MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN)
    (MU_IOCTL_WORDWRAP_GET_OFFSET): New opcodes.
    * libmailutils/stream/wordwrap.c (_wordwrap_flush_line): Replace
    whitespace-only lines with single newline on output.
    (_wordwrap_flush): Fix condition.
    (set_margin): Bugfix.
    (_wordwrap_ctl): Handle new opcodes.
    
    * include/mailutils/cli.h (mu_version_func): Change signature.
    * include/mailutils/opt.h (mu_parseopt) <po_help_hook>
    <po_version_hook>: Change signature.
    (mu_parseopt_fmt_text): Remove.
    (mu_option_describe_options, mu_program_help)
    (mu_program_usage): Change signature.
    (mu_program_version): New prototype.
    * libmailutils/cli/cli.c (mu_version_func): Take mu_stream_t as
    2nd argument.  Use mu_stream_printf for output.
    (extra_help_hook): Likewise.
    * libmailutils/opt/help.c: Rewrite using wordwrap streams.
    * libmailutils/opt/opt.c (fn_help, fn_usage, fn_version): Update.
    * libmailutils/tests/parseopt.c (version_hook): Write to mu_stream_t.
    
    * libmailutils/tests/parseopt_help00.at: Fix expected output.
    * libmailutils/tests/parseopt_help01.at: Likewise.
    * libmailutils/tests/parseopt_help02.at: Likewise.
    * libmailutils/tests/parseopt_help03.at: Likewise.
    * libmailutils/tests/parseopt_help04.at: Likewise.
    * libmailutils/tests/parseopt_help05.at: Likewise.
    * libmailutils/tests/parseopt_help06.at: Likewise.
    * libmailutils/tests/parseopt_help07.at: Likewise.
    * libmailutils/tests/parseopt_help08.at: Likewise.
    * libmailutils/tests/parseopt_help09.at: Likewise.
    * libmailutils/tests/parseopt_help10.at: Likewise.
    * libmailutils/tests/parseopt_help11.at: Likewise.

commit 06c13b3498a236a518df76bdb1b9895540c1df3b
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Oct 14 23:15:16 2016 +0300

    Implement simple word-wrapping stream
    
    * include/mailutils/stream.h (MU_IOCTL_WORDWRAPSTREAM): New ioctl.
    (mu_wordwrap_stream_create): New proto.
    * libmailutils/stream/Makefile.am: add wordwrap.c
    * libmailutils/stream/wordwrap.c: New file.
    * libmailutils/tests/Makefile.am: Add new testcases.
    * libmailutils/tests/testsuite.at: Include new testcases.
    * libmailutils/tests/wordwrap.c: New file.
    * libmailutils/tests/wordwrap00.at: New file.
    * libmailutils/tests/wordwrap01.at: New file.
    * libmailutils/tests/wordwrap02.at: New file.
    * libmailutils/tests/wordwrap03.at: New file.

-----------------------------------------------------------------------

Summary of changes:
 include/mailutils/cli.h                            |    2 +-
 include/mailutils/opt.h                            |   14 +-
 include/mailutils/stream.h                         |   13 +-
 libmailutils/cli/cli.c                             |   25 +-
 libmailutils/opt/help.c                            |  325 ++++++++----------
 libmailutils/opt/opt.c                             |    7 +-
 libmailutils/stream/Makefile.am                    |    1 +
 libmailutils/stream/wordwrap.c                     |  354 ++++++++++++++++++++
 libmailutils/tests/Makefile.am                     |    7 +-
 libmailutils/tests/parseopt.c                      |    4 +-
 libmailutils/tests/parseopt_help00.at              |    2 +-
 libmailutils/tests/parseopt_help01.at              |    4 +-
 libmailutils/tests/parseopt_help02.at              |    2 +-
 libmailutils/tests/parseopt_help03.at              |    2 +-
 libmailutils/tests/parseopt_help04.at              |    2 +-
 libmailutils/tests/parseopt_help05.at              |    2 +-
 libmailutils/tests/parseopt_help06.at              |    2 +-
 libmailutils/tests/parseopt_help07.at              |    2 +-
 libmailutils/tests/parseopt_help08.at              |    2 +-
 libmailutils/tests/parseopt_help09.at              |    4 +-
 libmailutils/tests/parseopt_help10.at              |    4 +-
 libmailutils/tests/parseopt_help11.at              |    2 +-
 libmailutils/tests/testsuite.at                    |    6 +
 libmailutils/tests/wordwrap.c                      |  162 +++++++++
 libmailutils/tests/wordwrap00.at                   |   45 +++
 libmailutils/tests/wordwrap01.at                   |   37 ++
 libmailutils/tests/wordwrap02.at                   |   33 ++
 .../tests/{parseopt25.at => wordwrap03.at}         |   15 +-
 28 files changed, 849 insertions(+), 231 deletions(-)
 create mode 100644 libmailutils/stream/wordwrap.c
 create mode 100644 libmailutils/tests/wordwrap.c
 create mode 100644 libmailutils/tests/wordwrap00.at
 create mode 100644 libmailutils/tests/wordwrap01.at
 create mode 100644 libmailutils/tests/wordwrap02.at
 copy libmailutils/tests/{parseopt25.at => wordwrap03.at} (77%)

diff --git a/include/mailutils/cli.h b/include/mailutils/cli.h
index 8f31f7b..097759e 100644
--- a/include/mailutils/cli.h
+++ b/include/mailutils/cli.h
@@ -50,7 +50,7 @@ struct mu_cli_setup
                                  errors */
 };
 
-void mu_version_func (struct mu_parseopt *po, FILE *stream);
+void mu_version_func (struct mu_parseopt *po, mu_stream_t stream);
 void mu_cli (int argc, char **argv, struct mu_cli_setup *setup,
             char **capa, void *data,
             int *ret_argc, char ***ret_argv);
diff --git a/include/mailutils/opt.h b/include/mailutils/opt.h
index 68204b9..7752117 100644
--- a/include/mailutils/opt.h
+++ b/include/mailutils/opt.h
@@ -131,9 +131,8 @@ struct mu_parseopt
   char const *po_package_url;
   char const *po_extra_info;
 
-  /* FIXME: should these take mu_stream_t ?*/
-  void (*po_help_hook) (struct mu_parseopt *po, FILE *stream); 
-  void (*po_version_hook) (struct mu_parseopt *po, FILE *stream);
+  void (*po_help_hook) (struct mu_parseopt *po, mu_stream_t stream); 
+  void (*po_version_hook) (struct mu_parseopt *po, mu_stream_t stream);
   
   /* Output data */
   int po_ind;                      /* Index of the next option */
@@ -169,11 +168,12 @@ int mu_parseopt_apply (struct mu_parseopt *p);
 void mu_parseopt_free (struct mu_parseopt *p);
 
 unsigned mu_parseopt_getcolumn (const char *name);
-void mu_parseopt_fmt_text (const char *text, size_t col);
 
-void mu_option_describe_options (struct mu_option **optbuf, size_t optcnt);
-void mu_program_help (struct mu_parseopt *p);
-void mu_program_usage (struct mu_parseopt *p);
+void mu_option_describe_options (mu_stream_t str,
+                                struct mu_option **optbuf, size_t optcnt);
+void mu_program_help (struct mu_parseopt *p, mu_stream_t str);
+void mu_program_usage (struct mu_parseopt *p, mu_stream_t str);
+void mu_program_version (struct mu_parseopt *po, mu_stream_t str);
 
 void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
                          char const *arg);
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index d870306..4f0ef69 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -78,7 +78,8 @@ enum mu_buffer_type
                                       always returns the topmost substream.
                                    */
 #define MU_IOCTL_TLSSTREAM       13 /* TLS stream */
-
+#define MU_IOCTL_WORDWRAPSTREAM  14 /* Word-wrapper stream */
+  
   /* Opcodes common for various families */
 #define MU_IOCTL_OP_GET 0
 #define MU_IOCTL_OP_SET 1  
@@ -206,6 +207,13 @@ enum mu_buffer_type
 #define MU_TRANSPORT_VALID_TYPE(n) \
   ((n) == MU_TRANSPORT_INPUT || (n) == MU_TRANSPORT_OUTPUT)
 
+/* Word wrapper streams */
+#define MU_IOCTL_WORDWRAP_GET_MARGIN      0
+#define MU_IOCTL_WORDWRAP_SET_MARGIN      1  
+#define MU_IOCTL_WORDWRAP_MOVE_MARGIN     2
+#define MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN 3
+#define MU_IOCTL_WORDWRAP_GET_OFFSET      4
+
 struct mu_nullstream_pattern
 {
   char *pattern;
@@ -360,6 +368,9 @@ int mu_rdcache_stream_create (mu_stream_t *pstream, 
mu_stream_t transport,
                              int flags);
 
 int mu_nullstream_create (mu_stream_t *pref, int flags);
+
+int mu_wordwrap_stream_create (mu_stream_t *pstream, mu_stream_t transport,
+                              size_t left_margin, size_t right_margin);
   
 #ifdef __cplusplus
 }
diff --git a/libmailutils/cli/cli.c b/libmailutils/cli/cli.c
index a75a684..5b8507a 100644
--- a/libmailutils/cli/cli.c
+++ b/libmailutils/cli/cli.c
@@ -53,40 +53,37 @@ const char mu_version_copyright[] =
   "Copyright %s 2007-2016 Free Software Foundation, inc.";
 
 void
-mu_version_func (struct mu_parseopt *po, FILE *stream)
+mu_version_func (struct mu_parseopt *po, mu_stream_t stream)
 {
 #ifdef GIT_DESCRIBE
-  fprintf (stream, "%s (%s) %s [%s]\n",
-          mu_program_name, PACKAGE_NAME, PACKAGE_VERSION, GIT_DESCRIBE);
+  mu_stream_printf (stream, "%s (%s) %s [%s]\n",
+                   mu_program_name, PACKAGE_NAME, PACKAGE_VERSION,
+                   GIT_DESCRIBE);
 #else
-  fprintf (stream, "%s (%s) %s\n", mu_program_name,
-          PACKAGE_NAME, PACKAGE_VERSION);
+  mu_stream_printf (stream, "%s (%s) %s\n", mu_program_name,
+                   PACKAGE_NAME, PACKAGE_VERSION);
 #endif
   /* TRANSLATORS: Translate "(C)" to the copyright symbol
      (C-in-a-circle), if this symbol is available in the user's
      locale.  Otherwise, do not translate "(C)"; leave it as-is.  */
-  fprintf (stream, mu_version_copyright, _("(C)"));
-  fputs (_("\
+  mu_stream_printf (stream, mu_version_copyright, _("(C)"));
+  mu_stream_printf (stream, _("\
 \n\
 License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to 
change and redistribute it.\n\
 There is NO WARRANTY, to the extent permitted by law.\n\
 \n\
-"),
-        stream);
+"));
 }
 
 static char gnu_general_help_url[] =
   N_("General help using GNU software: <http://www.gnu.org/gethelp/>");
 
 static void
-extra_help_hook (struct mu_parseopt *po, FILE *stream)
+extra_help_hook (struct mu_parseopt *po, mu_stream_t stream)
 {
   struct mu_cfg_parse_hints *hints = po->po_data;
   struct mu_cli_setup *setup = hints->data;
-  char *extra_doc = _(setup->prog_extra_doc);
-  /* FIXME: mu_parseopt help output should get FILE * argument */
-  mu_parseopt_fmt_text (extra_doc, 0);
-  fputc ('\n', stdout);
+  mu_stream_printf (stream, "%s\n", _(setup->prog_extra_doc));
 }
 
 static void
diff --git a/libmailutils/opt/help.c b/libmailutils/opt/help.c
index 96ab1dc..c4ef8d3 100644
--- a/libmailutils/opt/help.c
+++ b/libmailutils/opt/help.c
@@ -27,6 +27,7 @@
 #include <mailutils/cctype.h>
 #include <mailutils/nls.h>
 #include <mailutils/wordsplit.h>
+#include <mailutils/stream.h>
 
 unsigned short_opt_col = 2;
 unsigned long_opt_col = 6;
@@ -184,91 +185,69 @@ init_usage_vars (struct mu_parseopt *po)
 
   mu_wordsplit_free (&ws);
 }
-
-static int
-indent (int start, int col)
+
+static void
+set_margin (mu_stream_t str, unsigned margin)
 {
-  for (; start < col; start++)
-    putchar (' ');
-  return start;
+  mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                  MU_IOCTL_WORDWRAP_SET_MARGIN,
+                  &margin);
 }
-
 static void
-print_option_descr (const char *descr, size_t lmargin, size_t rmargin)
+set_next_margin (mu_stream_t str, unsigned margin)
 {
-  while (*descr)
-    {
-      size_t s = 0;
-      size_t i;
-      size_t width = rmargin - lmargin;
-      
-      for (i = 0; ; i++)
-       {
-         if (descr[i] == 0 || descr[i] == ' ' || descr[i] == '\t')
-           {
-             if (i > width)
-               break;
-             s = i;
-             if (descr[i] == 0)
-               break;
-           }
-         else if (descr[i] == '\n')
-           {
-             s = i;
-             break;
-           }
-       }
-      fwrite (descr, 1, s, stdout);
-      fputc ('\n', stdout);
-      descr += s;
-      if (*descr)
-       {
-         indent (0, lmargin);
-         descr++;
-       }
-    }
+  mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                  MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN,
+                  &margin);
 }
-
-void
-mu_parseopt_fmt_text (const char *text, size_t col)
+static void
+get_offset (mu_stream_t str, unsigned *offset)
 {
-  print_option_descr (text, col, rmargin);
+  mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                  MU_IOCTL_WORDWRAP_GET_OFFSET,
+                  offset);
+}
+static void
+move_margin (mu_stream_t str, int margin)
+{
+  mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                  MU_IOCTL_WORDWRAP_MOVE_MARGIN,
+                  &margin);
 }
-
 
-static size_t
-print_opt_arg (struct mu_option *opt, int delim)
+static void
+print_opt_arg (mu_stream_t str, struct mu_option *opt, int delim)
 {
-  int w = 0;
   if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
     {
       if (delim == '=')
-       w = printf ("[=%s]", gettext (opt->opt_arg));
+       mu_stream_printf (str, "[=%s]", gettext (opt->opt_arg));
       else
-       w = printf ("[%s]", gettext (opt->opt_arg));
+       mu_stream_printf (str, "[%s]", gettext (opt->opt_arg));
     }
   else
-    w = printf ("%c%s", delim, gettext (opt->opt_arg));
-  return w;
+    mu_stream_printf (str, "%c%s", delim, gettext (opt->opt_arg));
 }
 
 static size_t
-print_option (struct mu_option **optbuf, size_t optcnt, size_t num,
+print_option (mu_stream_t str,
+             struct mu_option **optbuf, size_t optcnt, size_t num,
              int *argsused)
 {
   struct mu_option *opt = optbuf[num];
   size_t next, i;
   int delim;
-  int w;
+  int first_option = 1;
+  int first_long_option = 1;
   
   if (MU_OPTION_IS_GROUP_HEADER (opt))
     {
       if (num)
-       putchar ('\n');
+       mu_stream_printf (str, "\n");
       if (opt->opt_doc[0])
        {
-         indent (0, header_col);
-         print_option_descr (gettext (opt->opt_doc), header_col, rmargin);
+         set_margin (str, header_col);
+         mu_stream_printf (str, "%s", gettext (opt->opt_doc));
        }
       return num + 1;
     }
@@ -281,22 +260,19 @@ print_option (struct mu_option **optbuf, size_t optcnt, 
size_t num,
   if (opt->opt_flags & MU_OPTION_HIDDEN)
     return next;
 
-  w = 0;
+  set_margin (str, short_opt_col); 
   for (i = num; i < next; i++)
     {
       if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]))
        {
-         if (w == 0)
-           {
-             indent (0, short_opt_col);
-             w = short_opt_col;
-           }
+         if (first_option)
+           first_option = 0;
          else
-           w += printf (", ");
-         w += printf ("-%c", optbuf[i]->opt_short);
+           mu_stream_printf (str, ", ");
+         mu_stream_printf (str, "-%c", optbuf[i]->opt_short);
          delim = ' ';
          if (opt->opt_arg && dup_args)
-           w += print_opt_arg (opt, delim);
+           print_opt_arg (str, opt, delim);
        }
     }
 
@@ -304,19 +280,24 @@ print_option (struct mu_option **optbuf, size_t optcnt, 
size_t num,
     {
       if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i]))
        {
-         if (w == 0)
+         if (first_option)
+           first_option = 0;
+         else
+           mu_stream_printf (str, ", ");
+
+         if (first_long_option)
            {
-             indent (0, short_opt_col);
-             w = short_opt_col;
+             unsigned off;
+             get_offset (str, &off);
+             if (off < long_opt_col)
+               set_margin (str, long_opt_col);
+             first_long_option = 0;
            }
-         else
-           w += printf (", ");
-         if (i == num)
-           w = indent (w, long_opt_col);
-         w += printf ("--%s", optbuf[i]->opt_long);
+         
+         mu_stream_printf (str, "--%s", optbuf[i]->opt_long);
          delim = '=';
          if (opt->opt_arg && dup_args)
-           w += print_opt_arg (opt, delim);
+           print_opt_arg (str, opt, delim);
        }
     }
   
@@ -324,70 +305,87 @@ print_option (struct mu_option **optbuf, size_t optcnt, 
size_t num,
     {
       *argsused = 1;
       if (!dup_args)
-       w += print_opt_arg (opt, delim);
-    }
-  if (w >= opt_doc_col)
-    {
-      putchar ('\n');
-      w = 0;
+       print_opt_arg (str, opt, delim);
     }
-  indent (w, opt_doc_col);
-  print_option_descr (gettext (opt->opt_doc), opt_doc_col, rmargin);
+
+  set_margin (str, opt_doc_col);
+  mu_stream_printf (str, "%s\n", gettext (opt->opt_doc));
 
   return next;
 }
 
 void
-mu_option_describe_options (struct mu_option **optbuf, size_t optcnt)
+mu_option_describe_options (mu_stream_t str,
+                           struct mu_option **optbuf, size_t optcnt)
 {
   unsigned i;
   int argsused = 0;
 
   for (i = 0; i < optcnt; )
-    i = print_option (optbuf, optcnt, i, &argsused);
-  putchar ('\n');
+    i = print_option (str, optbuf, optcnt, i, &argsused);
+  mu_stream_printf (str, "\n");
 
   if (argsused && dup_args_note)
     {
-      print_option_descr (_("Mandatory or optional arguments to long options 
are also mandatory or optional for any corresponding short options."), 0, 
rmargin);
-      putchar ('\n');
+      set_margin (str, 0);
+      mu_stream_printf (str, "%s\n\n",
+                       _("Mandatory or optional arguments to long options are 
also mandatory or optional for any corresponding short options."));
     }
 }
 
 void
-mu_program_help (struct mu_parseopt *po)
+mu_program_help (struct mu_parseopt *po, mu_stream_t outstr)
 {
+  mu_stream_t str;
+  int rc;
+  
   init_usage_vars (po);
 
-  printf ("%s", _("Usage:"));
+  rc = mu_wordwrap_stream_create (&str, outstr, 0, rmargin);
+  if (rc)
+    {
+      abort ();//FIXME
+    }
+  
+  mu_stream_printf (str, "%s", _("Usage:"));
   if (po->po_prog_name)
-    printf (" %s", po->po_prog_name);
-  printf (" [%s]...", _("OPTION"));
+    mu_stream_printf (str, " %s ", po->po_prog_name);
+  move_margin (str, 0);
+  mu_stream_printf (str, "[%s]...", _("OPTION"));
   if (po->po_prog_args)
-    printf (" %s", gettext (po->po_prog_args));
-  putchar ('\n');
+    mu_stream_printf (str, " %s", gettext (po->po_prog_args));
+  mu_stream_printf (str, "\n");
   
   if (po->po_prog_doc)
-    print_option_descr (gettext (po->po_prog_doc), 0, rmargin);
-  putchar ('\n');
-
-  mu_option_describe_options (po->po_optv, po->po_optc);
+    {
+      set_margin (str, 0);
+      mu_stream_printf (str, "%s\n", gettext (po->po_prog_doc));
+    }
+  mu_stream_printf (str, "\n");
+  
+  mu_option_describe_options (str, po->po_optv, po->po_optc);
 
   if (po->po_help_hook)
-    po->po_help_hook (po, stdout);
-
+    {
+      po->po_help_hook (po, str);
+      mu_stream_printf (str, "\n");
+    }
+  
+  set_margin (str, 0);
   if (po->po_bug_address)
     /* TRANSLATORS: The placeholder indicates the bug-reporting address
        for this package.  Please add _another line_ saying
        "Report translation bugs to <...>\n" with the address for translation
        bugs (typically your translation team's web or email address).  */
-    printf (_("Report bugs to <%s>.\n"), po->po_bug_address);
+    mu_stream_printf (str, _("Report bugs to <%s>.\n"), po->po_bug_address);
 
   if (po->po_package_name && po->po_package_url)
-    printf (_("%s home page: <%s>\n"),
-           po->po_package_name, po->po_package_url);
+    mu_stream_printf (str, _("%s home page: <%s>\n"),
+                     po->po_package_name, po->po_package_url);
   if (po->po_flags & MU_PARSEOPT_EXTRA_INFO)
-    print_option_descr (_(po->po_extra_info), 0, rmargin);
+    mu_stream_printf (str, "%s\n", _(po->po_extra_info));
+
+  mu_stream_destroy (&str);
 }
 
 static struct mu_option **option_tab;
@@ -426,41 +424,32 @@ cmpidx_long (const void *a, const void *b)
 }
 
 void
-mu_program_usage (struct mu_parseopt *po)
+mu_program_usage (struct mu_parseopt *po, mu_stream_t outstr)
 {
+  int rc;
   unsigned i;
-  unsigned n;
-  char buf[rmargin+1];
   unsigned *idxbuf;
   unsigned nidx;
 
   struct mu_option **optbuf = po->po_optv;
   size_t optcnt = po->po_optc;
-  
-#define FLUSH                                                          \
-  do                                                                   \
-    {                                                                  \
-      buf[n] = 0;                                                      \
-      printf ("%s\n", buf);                                            \
-      n = usage_indent;                                                \
-      if (n) memset (buf, ' ', n);                                     \
-    }                                                                  \
-  while (0)
-#define ADDC(c)                                                                
\
-  do                                                                   \
-    {                                                                  \
-      if (n == rmargin) FLUSH;                                         \
-      buf[n++] = c;                                                    \
-    }                                                                  \
-  while (0)
+
+  mu_stream_t str;
 
   init_usage_vars (po);
 
+  rc = mu_wordwrap_stream_create (&str, outstr, 0, rmargin);
+  if (rc)
+    {
+      abort ();//FIXME
+    }  
+  
   option_tab = optbuf;
   
   idxbuf = mu_calloc (optcnt, sizeof (idxbuf[0]));
 
-  n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"),        
po->po_prog_name);
+  mu_stream_printf (str, "%s %s ", _("Usage:"),        po->po_prog_name);
+  set_next_margin (str, usage_indent);
   
   /* Print a list of short options without arguments. */
   for (i = nidx = 0; i < optcnt; i++)
@@ -470,14 +459,12 @@ mu_program_usage (struct mu_parseopt *po)
   if (nidx)
     {
       qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
-
-      ADDC ('[');
-      ADDC ('-');
+      mu_stream_printf (str, "[-");
       for (i = 0; i < nidx; i++)
        {
-         ADDC (optbuf[idxbuf[i]]->opt_short);
+         mu_stream_printf (str, "%c", optbuf[idxbuf[i]]->opt_short);
        }
-      ADDC (']');
+      mu_stream_printf (str, "%c", ']');
     }
 
   /* Print a list of short options with arguments. */
@@ -495,19 +482,10 @@ mu_program_usage (struct mu_parseopt *po)
        {
          struct mu_option *opt = optbuf[idxbuf[i]];
          const char *arg = gettext (opt->opt_arg);
-         size_t len = 5 + strlen (arg) + 1;
-         
-         if (n + len >= rmargin)
-           FLUSH;
+         if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
+           mu_stream_printf (str, " [-%c[%s]]", opt->opt_short, arg);
          else
-           buf[n++] = ' ';
-         buf[n++] = '[';
-         buf[n++] = '-';
-         buf[n++] = opt->opt_short;
-         buf[n++] = ' ';
-         strcpy (&buf[n], arg);
-         n += strlen (arg);
-         buf[n++] = ']';
+           mu_stream_printf (str, " [-%c %s]", opt->opt_short, arg);
        }
     }
   
@@ -526,52 +504,41 @@ mu_program_usage (struct mu_parseopt *po)
        {
          struct mu_option *opt = optbuf[idxbuf[i]];
          const char *arg = opt->opt_arg ? gettext (opt->opt_arg) : NULL;
-         size_t len = 5 + strlen (opt->opt_long)
-                        + (arg ? 1 + strlen (arg) : 0);
-         if (n + len >= rmargin)
-           FLUSH;
-         else
-           buf[n++] = ' ';
-         buf[n++] = '[';
-         buf[n++] = '-';
-         buf[n++] = '-';
-         strcpy (&buf[n], opt->opt_long);
-         n += strlen (opt->opt_long);
+
+         mu_stream_printf (str, " [--%s", opt->opt_long);
          if (opt->opt_arg)
            {
-             buf[n++] = '=';
-             strcpy (&buf[n], arg);
-             n += strlen (arg);
+             if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
+               mu_stream_printf (str, "[=%s]", arg);
+             else
+               mu_stream_printf (str, "=%s", arg);
            }
-         buf[n++] = ']';
+         mu_stream_printf (str, "%c", ']');
        }
     }
 
   if (po->po_flags & MU_PARSEOPT_PROG_ARGS)
-    {
-      char const *p = po->po_prog_args;
-
-      if (n + 1 >= rmargin)
-       FLUSH;
-      buf[n++] = ' ';
-      
-      while (*p)
-       {
-         size_t len = strcspn (p, "  \t\n");
-         if (len == 0)
-           len = 1;
-         if (n + len >= rmargin)
-           FLUSH;
-         else
-           {
-             memcpy (buf + n, p, len);
-             p += len;
-             n += len;
-           }
-       }
-    }
+    mu_stream_printf (str, " %s", _(po->po_prog_args));
 
-  FLUSH;
+  mu_stream_destroy (&str);
+  
   free (idxbuf);
 }
 
+void
+mu_program_version (struct mu_parseopt *po, mu_stream_t outstr)
+{
+  int rc;
+  mu_stream_t str;
+  
+  init_usage_vars (po);
+
+  rc = mu_wordwrap_stream_create (&str, outstr, 0, rmargin);
+  if (rc)
+    {
+      abort ();//FIXME
+    }  
+  po->po_version_hook (po, str);
+
+  mu_stream_destroy (&str);
+}
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
index 0e31a47..bf3d4cd 100644
--- a/libmailutils/opt/opt.c
+++ b/libmailutils/opt/opt.c
@@ -24,6 +24,7 @@
 #include <mailutils/opt.h>
 #include <mailutils/nls.h>
 #include <mailutils/errno.h>
+#include <mailutils/stdstream.h>
 
 #define EXIT_SUCCESS 0
 #define EXIT_ERROR   1
@@ -78,7 +79,7 @@ sort_group (struct mu_option **optbuf, size_t start)
 static void
 fn_help (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
 {
-  mu_program_help (po);
+  mu_program_help (po, mu_strout);
   exit (EXIT_SUCCESS);
 }
 
@@ -86,14 +87,14 @@ fn_help (struct mu_parseopt *po, struct mu_option *opt, 
char const *unused)
 static void
 fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
 {
-  mu_program_usage (po);
+  mu_program_usage (po, mu_strout);
   exit (EXIT_SUCCESS);
 }
 
 static void
 fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
 {
-  po->po_version_hook (po, stdout);
+  mu_program_version (po, mu_strout);
   exit (EXIT_SUCCESS);
 }
 
diff --git a/libmailutils/stream/Makefile.am b/libmailutils/stream/Makefile.am
index df76fd8..d64a45e 100644
--- a/libmailutils/stream/Makefile.am
+++ b/libmailutils/stream/Makefile.am
@@ -38,6 +38,7 @@ libstream_la_SOURCES = \
  syslogstream.c\
  tcp.c\
  temp_file_stream.c\
+ wordwrap.c\
  xscript-stream.c
 
 AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/stream/wordwrap.c b/libmailutils/stream/wordwrap.c
new file mode 100644
index 0000000..b91a36e
--- /dev/null
+++ b/libmailutils/stream/wordwrap.c
@@ -0,0 +1,354 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <mailutils/types.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/stream.h>
+#include <mailutils/alloc.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/nls.h>
+#include <mailutils/cctype.h>
+
+struct mu_wordwrap_stream
+{
+  struct _mu_stream stream;
+  unsigned left_margin;
+  unsigned right_margin;
+  char *buffer;
+  unsigned offset;
+  mu_stream_t transport;
+};
+
+static int
+is_word (int c)
+{
+  return !mu_isspace (c);
+}
+
+static int
+full_write (struct mu_wordwrap_stream *str, size_t length)
+{
+  size_t n, rdsize;
+  for (n = 0; n < length; )
+    {
+      int rc = mu_stream_write (str->transport,
+                               str->buffer + n, length - n,
+                               &rdsize);
+      if (rc)
+       return rc;
+      n += rdsize;
+    }
+  return 0;
+}
+
+static int
+_wordwrap_flush_line (struct mu_wordwrap_stream *str, int lookahead)
+{
+  size_t length, word_start, word_len = 0;
+  int nl = 0;
+  char savech;
+  int rc;
+  
+  length = word_start = str->offset;
+  if (str->offset > 0 && lookahead)
+    {
+      if (is_word (str->buffer[str->offset - 1]) && is_word (lookahead))
+       {
+         /* Find the nearest word boundary */
+         for (length = str->offset; length > str->left_margin; length--)
+           {
+             if (!is_word (str->buffer[length - 1]))
+               break;
+           }
+         if (length == str->left_margin)
+           {
+             rc = full_write (str, str->offset);
+             if (rc == 0)
+               str->offset = 0;
+             return rc;
+           }
+         word_start = length;
+       }
+    }
+
+  while (length > 0 && mu_isspace (str->buffer[length - 1]))
+    length--;
+  
+  if (length == 0 || str->buffer[length - 1] != '\n')
+    {
+      savech = str->buffer[length];
+      str->buffer[length] = '\n';
+      nl = 1;
+    }
+  else
+    nl = 0;
+  
+  /* Flush the line buffer content */
+  rc = full_write (str, length + nl);
+  if (rc)
+    /* FIXME: Inconsistent state after error */
+    return rc;
+
+  if (nl)
+    str->buffer[length] = savech;
+  
+  /* Adjust the buffer */
+  memset (str->buffer, ' ', str->left_margin);
+  if (word_start > str->left_margin)
+    {
+      word_len = str->offset - word_start;
+      if (word_len)
+       memmove (str->buffer + str->left_margin, str->buffer + word_start,
+                word_len);
+    }
+  str->offset = str->left_margin + word_len;
+  return 0;
+}
+  
+static int
+_wordwrap_write (mu_stream_t stream, const char *iptr, size_t isize,
+                size_t *nbytes)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *) stream;
+  size_t n;
+
+  for (n = 0; n < isize; n++)
+    {
+      if (str->offset == str->right_margin
+         || (str->offset > 0 && str->buffer[str->offset - 1] == '\n'))
+       _wordwrap_flush_line (str, iptr[n]);
+      if (str->offset == str->left_margin && mu_isblank (iptr[n]))
+       continue;
+      str->buffer[str->offset++] = iptr[n];
+    }
+  if (nbytes)
+    *nbytes = isize;
+  return 0;
+}
+
+static int
+_wordwrap_flush (mu_stream_t stream)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
+  if (str->offset > str->left_margin)
+    _wordwrap_flush_line (str, 0);
+  return mu_stream_flush (str->transport);
+}
+
+static void
+_wordwrap_done (mu_stream_t stream)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
+  mu_stream_destroy (&str->transport);
+}
+
+static int
+_wordwrap_close (mu_stream_t stream)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
+  return mu_stream_close (str->transport);
+}
+
+static int
+set_margin (mu_stream_t stream, unsigned lmargin, int off)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
+
+  if (off < 0 && -off > str->left_margin)
+    return EINVAL;
+  lmargin += off;
+  
+  if (lmargin >= str->right_margin)
+    return EINVAL;
+
+  str->left_margin = lmargin;
+  if (lmargin < str->offset ||
+      (str->offset > 0 && str->buffer[str->offset - 1] == '\n'))
+    {
+      _wordwrap_flush (stream);
+    }
+  else if (lmargin > str->offset)
+    {
+      memset (str->buffer + str->offset, ' ', lmargin - str->offset);
+      str->offset = lmargin;
+    }
+      
+  return 0;
+}
+
+static int
+_wordwrap_ctl (mu_stream_t stream, int code, int opcode, void *arg)
+{
+  struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
+  int status;
+
+  switch (code)
+    {
+    case MU_IOCTL_WORDWRAPSTREAM:
+      switch (opcode)
+       {
+       case MU_IOCTL_WORDWRAP_GET_MARGIN:
+         /* Get left margin */
+         if (!arg)
+           return MU_ERR_OUT_PTR_NULL;
+         *(unsigned *)arg = str->left_margin;
+         break;
+           
+       case MU_IOCTL_WORDWRAP_SET_MARGIN:
+         /* Set left margin */
+         if (!arg)
+           return EINVAL;
+         else
+           return set_margin (stream, *(unsigned*)arg, 0);
+
+       case MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN:
+         if (!arg)
+           return EINVAL;
+         else
+           {
+             unsigned marg = *(unsigned*)arg;
+             if (marg >= str->right_margin)
+               return EINVAL;
+             str->left_margin = marg;
+           }
+         break;
+         
+       case MU_IOCTL_WORDWRAP_MOVE_MARGIN:
+         if (!arg)
+           return EINVAL;
+         else
+           return set_margin (stream, str->offset, *(int*)arg);
+
+       case MU_IOCTL_WORDWRAP_GET_OFFSET:
+         if (!arg)
+           return EINVAL;
+         *(unsigned*)arg = str->offset;
+         break;
+
+       default:
+         return EINVAL;
+       }
+      break;
+      
+    case MU_IOCTL_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      else
+       {
+         mu_transport_t *ptrans = arg;
+         switch (opcode)
+           {
+           case MU_IOCTL_OP_GET:
+             ptrans[0] = (mu_transport_t) str->transport;
+             ptrans[1] = NULL;
+             break;
+
+           case MU_IOCTL_OP_SET:
+             ptrans = arg;
+             if (ptrans[0])
+               str->transport = (mu_stream_t) ptrans[0];
+             break;
+
+           default:
+             return EINVAL;
+           }
+       }
+      break;
+
+    case MU_IOCTL_SUBSTREAM:
+      if (str->transport &&
+          ((status = mu_stream_ioctl (str->transport, code, opcode, arg)) == 0 
||
+           status != ENOSYS))
+        return status;
+      /* fall through */
+
+    case MU_IOCTL_TOPSTREAM:
+      if (!arg)
+       return EINVAL;
+      else
+       {
+         mu_stream_t *pstr = arg;
+         switch (opcode)
+           {
+           case MU_IOCTL_OP_GET:
+             pstr[0] = str->transport;
+             mu_stream_ref (pstr[0]);
+             pstr[1] = NULL;
+             break;
+
+           case MU_IOCTL_OP_SET:
+             mu_stream_unref (str->transport);
+             str->transport = pstr[0];
+             mu_stream_ref (str->transport);
+             break;
+
+           default:
+             return EINVAL;
+           }
+       }
+      break;
+
+    case MU_IOCTL_FILTER:
+      return mu_stream_ioctl (str->transport, code, opcode, arg);
+      
+    default:
+      return ENOSYS;
+    }
+  return 0;
+}
+  
+int
+mu_wordwrap_stream_create (mu_stream_t *pstream, mu_stream_t transport,
+                          size_t left_margin, size_t right_margin)
+{
+  int rc;
+  mu_stream_t stream;
+  struct mu_wordwrap_stream *str;
+
+  if (right_margin == 0 || left_margin >= right_margin)
+    return EINVAL;
+  
+  str = (struct mu_wordwrap_stream *)
+             _mu_stream_create (sizeof (*str), MU_STREAM_APPEND);
+  if (!str)
+    return ENOMEM;
+  str->stream.close = _wordwrap_close;
+  str->stream.write = _wordwrap_write;
+  //  str->stream.size = _wordwrap_size;
+  str->stream.done = _wordwrap_done;
+  str->stream.flush = _wordwrap_flush;
+  str->stream.ctl = _wordwrap_ctl;
+  
+  str->transport = transport;
+  mu_stream_ref (transport);
+  str->left_margin = left_margin;
+  str->right_margin = right_margin;
+  str->buffer = mu_alloc (str->right_margin+1);
+  memset (str->buffer, ' ', str->left_margin);
+  str->offset = str->left_margin;
+  
+  stream = (mu_stream_t) str;
+  rc = mu_stream_open (stream);
+  if (rc)
+    mu_stream_destroy (&stream);
+  else
+    *pstream = stream;
+  return rc;
+}
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 728eaec..bdd4b20 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -68,6 +68,7 @@ noinst_PROGRAMS = \
  url-comp\
  url-parse\
  wicket\
+ wordwrap\
  wsp
 
 LDADD = ${MU_LIB_MAILUTILS}
@@ -155,7 +156,11 @@ TESTSUITE_AT = \
  url-comp.at\
  xml.at\
  wicket.at\
- wordsplit.at
+ wordsplit.at\
+ wordwrap00.at\
+ wordwrap01.at\
+ wordwrap02.at\
+ wordwrap03.at
 
 TESTSUITE = $(srcdir)/testsuite
 M4=m4
diff --git a/libmailutils/tests/parseopt.c b/libmailutils/tests/parseopt.c
index f25aabf..214a93d 100644
--- a/libmailutils/tests/parseopt.c
+++ b/libmailutils/tests/parseopt.c
@@ -64,9 +64,9 @@ struct mu_option group_b[] = {
 struct mu_option *optv[] = { group_a, group_b, NULL };
 
 static void
-version_hook (struct mu_parseopt *po, FILE *fp)
+version_hook (struct mu_parseopt *po, mu_stream_t str)
 {
-  fputs ("version hook called\n", fp);
+  mu_stream_printf (str, "version hook called\n");
 }
 
 #define S(s) ((s)?(s):"(null)")
diff --git a/libmailutils/tests/parseopt_help00.at 
b/libmailutils/tests/parseopt_help00.at
index c3751ac..894d524 100644
--- a/libmailutils/tests/parseopt_help00.at
+++ b/libmailutils/tests/parseopt_help00.at
@@ -30,8 +30,8 @@ parseopt --help
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help01.at 
b/libmailutils/tests/parseopt_help01.at
index 63ecf56..cacfb7c 100644
--- a/libmailutils/tests/parseopt_help01.at
+++ b/libmailutils/tests/parseopt_help01.at
@@ -21,8 +21,8 @@ PARSEOPT_DEFAULT
 parseopt --usage
 ],
 [0],
-[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N] [-o FILE] [--all]
+[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
             [--debug] [--file=FILE] [--find=VALUE] [--help] [--jobs=N]
-            [--optional=FILE] [--usage] [--verbose]
+            [--optional[=FILE]] [--usage] [--verbose]
 ]])
 AT_CLEANUP
diff --git a/libmailutils/tests/parseopt_help02.at 
b/libmailutils/tests/parseopt_help02.at
index 79aef4d..61dbac3 100644
--- a/libmailutils/tests/parseopt_help02.at
+++ b/libmailutils/tests/parseopt_help02.at
@@ -30,8 +30,8 @@ MU_PARSEOPT_PROG_NAME=newname parseopt --help
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help03.at 
b/libmailutils/tests/parseopt_help03.at
index f004bcf..8435a9c 100644
--- a/libmailutils/tests/parseopt_help03.at
+++ b/libmailutils/tests/parseopt_help03.at
@@ -31,8 +31,8 @@ Tests option parsing
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help04.at 
b/libmailutils/tests/parseopt_help04.at
index 1c6de2e..bcce1e1 100644
--- a/libmailutils/tests/parseopt_help04.at
+++ b/libmailutils/tests/parseopt_help04.at
@@ -30,8 +30,8 @@ MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS" parseopt --help
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help05.at 
b/libmailutils/tests/parseopt_help05.at
index 4fe6960..2856e61 100644
--- a/libmailutils/tests/parseopt_help05.at
+++ b/libmailutils/tests/parseopt_help05.at
@@ -30,8 +30,8 @@ MU_PARSEOPT_BUG_ADDRESS='address@hidden' parseopt --help
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help06.at 
b/libmailutils/tests/parseopt_help06.at
index 5ba784f..4562a21 100644
--- a/libmailutils/tests/parseopt_help06.at
+++ b/libmailutils/tests/parseopt_help06.at
@@ -30,8 +30,8 @@ MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils' 
MU_PARSEOPT_PACKAGE_URL='http://mailuti
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help07.at 
b/libmailutils/tests/parseopt_help07.at
index 91c3c19..1b2e388 100644
--- a/libmailutils/tests/parseopt_help07.at
+++ b/libmailutils/tests/parseopt_help07.at
@@ -37,8 +37,8 @@ Tests option parsing
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/parseopt_help08.at 
b/libmailutils/tests/parseopt_help08.at
index c9f1029..becc899 100644
--- a/libmailutils/tests/parseopt_help08.at
+++ b/libmailutils/tests/parseopt_help08.at
@@ -31,8 +31,8 @@ 
ARGP_HELP_FMT=dup-args,no-dup-args-note,short-opt-col=1,opt-doc-col=32,header-co
  -x                             short-only option
 
           Group B
- -F VALUE, --find=VALUE         find VALUE
  -d, -v, --debug, --verbose     another option
+ -F VALUE, --find=VALUE         find VALUE
  -j N, --jobs=N                 sets numeric value
 
  -?,  --help                    give this help list
diff --git a/libmailutils/tests/parseopt_help09.at 
b/libmailutils/tests/parseopt_help09.at
index d727bdf..bd4ccc2 100644
--- a/libmailutils/tests/parseopt_help09.at
+++ b/libmailutils/tests/parseopt_help09.at
@@ -23,7 +23,7 @@ ARGP_HELP_FMT=rmargin=62,usage-indent=1\
 ],
 [0],
 [[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N]
- [-o FILE] [--all] [--debug] [--file=FILE] [--find=VALUE]
- [--help] [--jobs=N] [--optional=FILE] [--usage] [--verbose]
+ [-o[FILE]] [--all] [--debug] [--file=FILE] [--find=VALUE]
+ [--help] [--jobs=N] [--optional[=FILE]] [--usage] [--verbose]
 ]])
 AT_CLEANUP
diff --git a/libmailutils/tests/parseopt_help10.at 
b/libmailutils/tests/parseopt_help10.at
index 3f70616..3deb4f7 100644
--- a/libmailutils/tests/parseopt_help10.at
+++ b/libmailutils/tests/parseopt_help10.at
@@ -21,8 +21,8 @@ PARSEOPT_DEFAULT
 MU_PARSEOPT_VERSION_HOOK=1 parseopt --usage
 ],
 [0],
-[[Usage: parseopt [-advVx?] [-f FILE] [-F VALUE] [-j N] [-o FILE] [--all]
+[[Usage: parseopt [-advVx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
             [--debug] [--file=FILE] [--find=VALUE] [--help] [--jobs=N]
-            [--optional=FILE] [--usage] [--verbose] [--version]
+            [--optional[=FILE]] [--usage] [--verbose] [--version]
 ]])
 AT_CLEANUP
diff --git a/libmailutils/tests/parseopt_help11.at 
b/libmailutils/tests/parseopt_help11.at
index a8bda93..9b7dc2b 100644
--- a/libmailutils/tests/parseopt_help11.at
+++ b/libmailutils/tests/parseopt_help11.at
@@ -30,8 +30,8 @@ MU_PARSEOPT_VERSION_HOOK=1 parseopt --help
   -x                         short-only option
 
  Group B
-  -F, --find=VALUE           find VALUE
   -d, -v, --debug, --verbose another option
+  -F, --find=VALUE           find VALUE
   -j, --jobs=N               sets numeric value
 
   -?, --help                 give this help list
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 12043f9..f9b1bcc 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -56,6 +56,12 @@ AT_INIT
 AT_BANNER([Conversions])
 m4_include([strtoc.at])
 
+AT_BANNER([Word wrapper])
+m4_include([wordwrap00.at])
+m4_include([wordwrap01.at])
+m4_include([wordwrap02.at])
+m4_include([wordwrap03.at])
+
 AT_BANNER([Command line parser])
 m4_define([PARSEOPT_DEFAULT],[
 unset ARGP_HELP_FMT
diff --git a/libmailutils/tests/wordwrap.c b/libmailutils/tests/wordwrap.c
new file mode 100644
index 0000000..781f9a1
--- /dev/null
+++ b/libmailutils/tests/wordwrap.c
@@ -0,0 +1,162 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif 
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/diag.h>
+#include <mailutils/debug.h>
+#include <mailutils/errno.h>
+
+static void
+usage (FILE *fp)
+{
+  fprintf (fp,
+          "usage: %s [-r N] [-l [+-]N] FILE [[-l [+-]N] FILE...]\n",
+          mu_program_name);
+  fprintf (fp, "\n");
+  fprintf (fp, "  -l N       set left margin\n");
+  fprintf (fp, "  -l +N      move left margin N chars to the right from the 
current position\n");
+  fprintf (fp, "  -l -N      move left margin N chars to the left from the 
current position\n");
+  fprintf (fp, "  -r N       set right margin\n");
+  fprintf (fp, "  -h, -?     display this help\n");
+}
+
+int
+main (int argc, char **argv)
+{
+  unsigned left = 0, right = 80;
+  mu_stream_t str;
+  int i;
+  
+  mu_set_program_name (argv[0]);
+ 
+  for (i = 1; i < argc; i++)
+    {
+      char *arg = argv[i];
+      if (strncmp (arg, "-l", 2) == 0)
+       {
+         if (arg[2] == 0)
+           {
+             ++i;
+             left = strtoul (argv[i], NULL, 10);
+           }
+         else
+           {
+             left = strtoul (argv[i] + 2, NULL, 10);
+           }
+       }
+      else if (strncmp (arg, "-r", 2) == 0)
+       {
+         if (arg[2] == 0)
+           {
+             ++i;
+             right = strtoul (argv[i], NULL, 10);
+           }
+         else
+           {
+             right = strtoul (argv[i] + 2, NULL, 10);
+           }
+       }
+      else if (strcmp (arg, "--") == 0)
+       {
+         i++;
+         break;
+       }
+      else if (arg[0] == '-')
+       {
+         if (arg[1] == 0)
+           break;
+         else if ((arg[1] == 'h' || arg[1] == '?') && arg[2] == 0)
+           {
+             usage (stdout);
+             return 0;
+           }
+         else
+           {
+             fprintf (stderr, "%s: unrecognized argument %s\n",
+                      mu_program_name, arg);
+             usage (stderr);
+             return 1;
+           }
+       }
+      else
+       break;
+    }
+
+  if (i == argc)
+    {
+      fprintf (stderr, "%s: no files\n", mu_program_name);
+      usage (stderr);
+      return 1;
+    }
+  
+  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+  MU_ASSERT (mu_wordwrap_stream_create (&str, mu_strout, left, right));
+
+  for (; i < argc; i++)
+    {
+      char *arg = argv[i];
+      if (strncmp (arg, "-l", 2) == 0)
+       {
+         if (arg[2] == 0)
+           {
+             ++i;
+             arg = argv[i];
+           }
+         else
+           arg += 2;
+
+         if (arg[0] == '+' || arg[0] == '-')
+           {
+             int off = strtol (arg, NULL, 10);
+             MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                                         MU_IOCTL_WORDWRAP_MOVE_MARGIN,
+                                         &off));
+           }
+         else
+           {
+             left = strtoul (arg, NULL, 10);
+             MU_ASSERT (mu_stream_ioctl (str, MU_IOCTL_WORDWRAPSTREAM,
+                                         MU_IOCTL_WORDWRAP_SET_MARGIN,
+                                         &left));
+           }
+       }
+      else if (arg[0] == '-' && arg[1] == 0)
+       {
+         MU_ASSERT (mu_stream_copy (str, mu_strin, 0, NULL));
+         mu_stream_close (mu_strin);
+       }
+      else
+       {
+         mu_stream_t in;
+         MU_ASSERT (mu_file_stream_create (&in, arg, MU_STREAM_READ));
+         MU_ASSERT (mu_stream_copy (str, in, 0, NULL));
+         mu_stream_destroy (&in);
+       }
+    }
+  mu_stream_destroy (&str);
+  return 0;
+}
+    
+
+  
+           
diff --git a/libmailutils/tests/wordwrap00.at b/libmailutils/tests/wordwrap00.at
new file mode 100644
index 0000000..07d5802
--- /dev/null
+++ b/libmailutils/tests/wordwrap00.at
@@ -0,0 +1,45 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([Fixed margins])
+AT_KEYWORDS([wordwrap wordwrap00])
+AT_DATA([input],[My Father had a small Estate in Nottinghamshire; I was the 
Third of five Sons. He sent me to Emanuel-College in Cambridge, at Fourteen 
Years old, where I resided three Years, and applyed my self close to my 
Studies: But the Charge of maintaining me (although I had a very scanty 
Allowance) being too great for a narrow Fortune; I was bound Apprentice to Mr. 
James Bates, an eminent Surgeon in London, with whom I continued four Years; 
and my Father now and then sending me small Sums of Money,  I laid them out in 
learning Navigation, and other parts of the Mathematicks, useful to those who 
intend to travel, as I always believed it would be some time or other my 
Fortune to do. When I left Mr. Bates, I went down to my Father; where, by the 
Assistance of him and my Uncle John, and some other Relations, I got Forty 
Pounds, and a Promise of Thirty Pounds a Year to maintain me at Leyden: There I 
studied Physick two Years and seven Months, knowing it would be useful in 
 long Voyages.
+])
+AT_CHECK([wordwrap -l 20 -r 70 input],
+[0],
+[                    My Father had a small Estate in Nottinghamshire; I
+                    was the Third of five Sons. He sent me to 
+                    Emanuel-College in Cambridge, at Fourteen Years 
+                    old, where I resided three Years, and applyed my 
+                    self close to my Studies: But the Charge of 
+                    maintaining me (although I had a very scanty 
+                    Allowance) being too great for a narrow Fortune; I
+                    was bound Apprentice to Mr. James Bates, an 
+                    eminent Surgeon in London, with whom I continued 
+                    four Years; and my Father now and then sending me 
+                    small Sums of Money,  I laid them out in learning 
+                    Navigation, and other parts of the Mathematicks, 
+                    useful to those who intend to travel, as I always 
+                    believed it would be some time or other my Fortune
+                    to do. When I left Mr. Bates, I went down to my 
+                    Father; where, by the Assistance of him and my 
+                    Uncle John, and some other Relations, I got Forty 
+                    Pounds, and a Promise of Thirty Pounds a Year to 
+                    maintain me at Leyden: There I studied Physick two
+                    Years and seven Months, knowing it would be useful
+                    in long Voyages.
+])
+AT_CLEANUP
\ No newline at end of file
diff --git a/libmailutils/tests/wordwrap01.at b/libmailutils/tests/wordwrap01.at
new file mode 100644
index 0000000..2274378
--- /dev/null
+++ b/libmailutils/tests/wordwrap01.at
@@ -0,0 +1,37 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([Move margin right])
+AT_KEYWORDS([wordwrap wordwrap01])
+AT_DATA([input0],[My Father had a small Estate in Nottinghamshire; I was the 
Third of five Sons.
+])
+AT_DATA([input1],[He sent me to Emanuel-College in Cambridge, at Fourteen 
Years old, where I resided three Years, and applyed my self close to my Studies:
+])
+AT_CHECK([cat input0 | tr -d '\n' | wordwrap -l 20 -r 70 - -l +8 input1],
+[0],
+[                    My Father had a small Estate in Nottinghamshire; I
+                    was the Third of five Sons.        He sent me to
+                                                       Emanuel-College
+                                                       in Cambridge,
+                                                       at Fourteen
+                                                       Years old,
+                                                       where I resided
+                                                       three Years,
+                                                       and applyed my
+                                                       self close to
+                                                       my Studies:
+])
+AT_CLEANUP
\ No newline at end of file
diff --git a/libmailutils/tests/wordwrap02.at b/libmailutils/tests/wordwrap02.at
new file mode 100644
index 0000000..f631684
--- /dev/null
+++ b/libmailutils/tests/wordwrap02.at
@@ -0,0 +1,33 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([Move margin left])
+AT_KEYWORDS([wordwrap wordwrap02])
+AT_DATA([input0],[My Father had a small Estate in Nottinghamshire; I was the 
Third of five Sons.
+])
+AT_DATA([input1],[He sent me to Emanuel-College in Cambridge, at Fourteen 
Years old, where I resided three Years, and applyed my self close to my Studies:
+])
+AT_CHECK([cat input0 | tr -d '\n' | wordwrap -l 20 -r 70 - -l -8 input1],
+[0],
+[                    My Father had a small Estate in Nottinghamshire; I
+                    was the Third of five Sons.
+                                       He sent me to Emanuel-College
+                                       in Cambridge, at Fourteen Years
+                                       old, where I resided three
+                                       Years, and applyed my self
+                                       close to my Studies:
+])
+AT_CLEANUP
\ No newline at end of file
diff --git a/libmailutils/tests/parseopt25.at b/libmailutils/tests/wordwrap03.at
similarity index 77%
copy from libmailutils/tests/parseopt25.at
copy to libmailutils/tests/wordwrap03.at
index 2cbbe3f..22854bc 100644
--- a/libmailutils/tests/parseopt25.at
+++ b/libmailutils/tests/wordwrap03.at
@@ -13,14 +13,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
-
-AT_SETUP([MU_PARSEOPT_VERSION_HOOK])
-AT_KEYWORDS([parseopt MU_PARSEOPT_VERSION_HOOK parseopt25])
-AT_CHECK([
-PARSEOPT_DEFAULT
-MU_PARSEOPT_VERSION_HOOK=1 parseopt -V
+AT_SETUP([Corner cases])
+AT_KEYWORDS([wordwrap wordwrap03])
+AT_CHECK([echo abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz|\
+ wordwrap -r 10 -
 ],
 [0],
-[version hook called
+[abcdefghijklmnopqrstuvwxyz
+abcdefghijklmnopqrstuvwxyz
 ])
-AT_CLEANUP
+AT_CLEANUP
\ No newline at end of file


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]