Github messages for voidlinux
 help / color / mirror / Atom feed
* [PR PATCH] Added unicode patch for par-1.52
@ 2019-10-26 14:43 voidlinux-github
  2019-10-27  7:07 ` voidlinux-github
                   ` (21 more replies)
  0 siblings, 22 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-26 14:43 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 494 bytes --]

There is a new pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

Added unicode patch for par-1.52
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87591 bytes --]

From 5baf18aaa323ea1a1fb6c7f8d3d48adf8b358cc0 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 1 file changed, 2858 insertions(+)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Added unicode patch for par-1.52
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
@ 2019-10-27  7:07 ` voidlinux-github
  2019-10-27  8:31 ` par: added unicode support voidlinux-github
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  7:07 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 558 bytes --]

New comment by Hoshpak on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546667783

Comment:
We usually don't patch software to introduce new features, I will refer to the maintainer of the package regarding this though.

Please not that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`. Also you should increase the revision in the package template, otherwise the builders won't rebuild the package with the change.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
  2019-10-27  7:07 ` voidlinux-github
@ 2019-10-27  8:31 ` voidlinux-github
  2019-10-27  8:32 ` voidlinux-github
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  8:31 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 739 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546672767

Comment:
> We usually don't patch software to introduce new features, I will refer to the maintainer of the package regarding this though.
Should've done that myself, but just overreacted yesterday, when par -w80rj had almost left me without me lectures on history.
> Please not that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.
Done.
> Also you should increase the revision in the package template, otherwise the builders won't rebuild the package with the change.
Done in the first place rev. 3->4.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
  2019-10-27  7:07 ` voidlinux-github
  2019-10-27  8:31 ` par: added unicode support voidlinux-github
@ 2019-10-27  8:32 ` voidlinux-github
  2019-10-27  8:33 ` voidlinux-github
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  8:32 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 747 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546672767

Comment:
> We usually don't patch software to introduce new features, I will refer to the maintainer of the package regarding this though.

Should've done that myself, but just overreacted yesterday, when par -w80rj had almost left me without me lectures on history.

> Please not that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.

Done.
> Also you should increase the revision in the package template, otherwise the builders won't rebuild the package with the change.

Done in the first place rev. 3->4.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (2 preceding siblings ...)
  2019-10-27  8:32 ` voidlinux-github
@ 2019-10-27  8:33 ` voidlinux-github
  2019-10-27  8:41 ` [PR PATCH] [Updated] " voidlinux-github
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  8:33 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 726 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546672767

Comment:
> We usually don't patch software to introduce new features, I will refer to the maintainer of the package regarding this though.

Should've done that myself, but just overreacted yesterday, when par -w80rj had almost left me without me lectures on history.

> Please not that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.

Done.
> Also you should increase the revision in the package template, otherwise the builders won't rebuild the package with the change.

Working on it

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (4 preceding siblings ...)
  2019-10-27  8:41 ` [PR PATCH] [Updated] " voidlinux-github
@ 2019-10-27  8:41 ` voidlinux-github
  2019-10-27  9:04 ` voidlinux-github
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  8:41 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 88194 bytes --]

From 5baf18aaa323ea1a1fb6c7f8d3d48adf8b358cc0 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH 1/2] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 1 file changed, 2858 insertions(+)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test

From 0de45e335b94326075c9b8361508d6b601e3c675 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sun, 27 Oct 2019 11:39:05 +0300
Subject: [PATCH 2/2] par: bumped revision

---
 srcpkgs/par/template | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (3 preceding siblings ...)
  2019-10-27  8:33 ` voidlinux-github
@ 2019-10-27  8:41 ` voidlinux-github
  2019-10-27  8:41 ` voidlinux-github
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  8:41 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 88194 bytes --]

From 5baf18aaa323ea1a1fb6c7f8d3d48adf8b358cc0 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH 1/2] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 1 file changed, 2858 insertions(+)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test

From 0de45e335b94326075c9b8361508d6b601e3c675 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sun, 27 Oct 2019 11:39:05 +0300
Subject: [PATCH 2/2] par: bumped revision

---
 srcpkgs/par/template | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (6 preceding siblings ...)
  2019-10-27  9:04 ` voidlinux-github
@ 2019-10-27  9:04 ` voidlinux-github
  2019-10-27  9:06 ` voidlinux-github
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:04 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87591 bytes --]

From 5baf18aaa323ea1a1fb6c7f8d3d48adf8b358cc0 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 1 file changed, 2858 insertions(+)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (5 preceding siblings ...)
  2019-10-27  8:41 ` voidlinux-github
@ 2019-10-27  9:04 ` voidlinux-github
  2019-10-27  9:04 ` voidlinux-github
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:04 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87591 bytes --]

From 5baf18aaa323ea1a1fb6c7f8d3d48adf8b358cc0 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 1 file changed, 2858 insertions(+)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (7 preceding siblings ...)
  2019-10-27  9:04 ` voidlinux-github
@ 2019-10-27  9:06 ` voidlinux-github
  2019-10-27  9:06 ` voidlinux-github
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:06 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87974 bytes --]

From 3471e0e5d4101da93fb2417c0d340cb4940e32e5 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    2 +-
 2 files changed, 2859 insertions(+), 1 deletion(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (8 preceding siblings ...)
  2019-10-27  9:06 ` voidlinux-github
@ 2019-10-27  9:06 ` voidlinux-github
  2019-10-27  9:09 ` voidlinux-github
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:06 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87974 bytes --]

From 3471e0e5d4101da93fb2417c0d340cb4940e32e5 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] Added unicode patch for par-1.52

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    2 +-
 2 files changed, 2859 insertions(+), 1 deletion(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (9 preceding siblings ...)
  2019-10-27  9:06 ` voidlinux-github
@ 2019-10-27  9:09 ` voidlinux-github
  2019-10-27  9:32 ` voidlinux-github
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:09 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 269 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546675551

Comment:
Ok, can anyone tell me what to do with Travis' "srcpkgs/par/template:9: use SPDX id for 'custom' license or see Manual.md"?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (10 preceding siblings ...)
  2019-10-27  9:09 ` voidlinux-github
@ 2019-10-27  9:32 ` voidlinux-github
  2019-10-27  9:46 ` voidlinux-github
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:32 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 361 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546675551

Comment:
Ok, can anyone tell me what to do with Travis' "srcpkgs/par/template:9: use SPDX id for 'custom' license or see Manual.md"?

There's no exact license in par.doc, or anywhere nearby. Maintainer choice was "custom".

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (11 preceding siblings ...)
  2019-10-27  9:32 ` voidlinux-github
@ 2019-10-27  9:46 ` voidlinux-github
  2019-10-27  9:50 ` [PR PATCH] [Updated] " voidlinux-github
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:46 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 397 bytes --]

New comment by zdtcd on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546678279

Comment:
> > Please note that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.
> 
> Done.

He meant you needed to change the commit message itself, not this PR's title.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (12 preceding siblings ...)
  2019-10-27  9:46 ` voidlinux-github
@ 2019-10-27  9:50 ` voidlinux-github
  2019-10-27  9:50 ` voidlinux-github
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:50 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87964 bytes --]

From 951be4b1e30a11e50eb45493f12c4ffee0da9b60 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] par: add unicode patch

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    2 +-
 2 files changed, 2859 insertions(+), 1 deletion(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (13 preceding siblings ...)
  2019-10-27  9:50 ` [PR PATCH] [Updated] " voidlinux-github
@ 2019-10-27  9:50 ` voidlinux-github
  2019-10-27  9:51 ` voidlinux-github
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:50 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 87964 bytes --]

From 951be4b1e30a11e50eb45493f12c4ffee0da9b60 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] par: add unicode patch

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    2 +-
 2 files changed, 2859 insertions(+), 1 deletion(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..d3e2d5886ad 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,7 +1,7 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (14 preceding siblings ...)
  2019-10-27  9:50 ` voidlinux-github
@ 2019-10-27  9:51 ` voidlinux-github
  2019-10-27  9:51 ` voidlinux-github
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:51 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546678635

Comment:
> > > Please note that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.
> > 
> > 
> > Done.
> 
> He meant you needed to change the commit message itself, not this PR's title.

Done.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (15 preceding siblings ...)
  2019-10-27  9:51 ` voidlinux-github
@ 2019-10-27  9:51 ` voidlinux-github
  2019-10-27  9:58 ` voidlinux-github
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:51 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 469 bytes --]

New comment by ValTimchenko on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546678635

Comment:
> > > Please note that should this be merged, the commit title should be formatted with the package name first and then what it does, like `par: add unicode patch`.
> > 
> > 
> > Done.
> 
> He meant you needed to change the commit message itself, not this PR's title.

Done. Still don't know what to do with license.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (16 preceding siblings ...)
  2019-10-27  9:51 ` voidlinux-github
@ 2019-10-27  9:58 ` voidlinux-github
  2019-10-27 15:06 ` voidlinux-github
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27  9:58 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 237 bytes --]

New comment by zdtcd on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546679175

Comment:
> Done. Still don't know what to do with license.

`s/custom/&:par/` or `s/custom/&:nicemice/`


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (17 preceding siblings ...)
  2019-10-27  9:58 ` voidlinux-github
@ 2019-10-27 15:06 ` voidlinux-github
  2019-10-27 18:43 ` [PR PATCH] [Updated] " voidlinux-github
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27 15:06 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 203 bytes --]

New comment by leahneukirchen on void-packages repository

https://github.com/void-linux/void-packages/pull/15812#issuecomment-546703049

Comment:
Debian has this patch too, I don't object to adding it.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (19 preceding siblings ...)
  2019-10-27 18:43 ` [PR PATCH] [Updated] " voidlinux-github
@ 2019-10-27 18:43 ` voidlinux-github
  2019-10-28  8:57 ` [PR PATCH] [Merged]: " voidlinux-github
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27 18:43 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 88202 bytes --]

From a840bcb1601183e765e3545b777cb0f07a55a145 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] par: add unicode patch

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    4 +-
 2 files changed, 2860 insertions(+), 2 deletions(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..54747129b79 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,12 +1,12 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"
 maintainer="Leah Neukirchen <leah@vuxu.org>"
-license="custom"
+license="custom:par"
 homepage="http://www.nicemice.net/par/"
 distfiles="http://www.nicemice.net/par/Par152-autoconf.tar.gz
  http://www.nicemice.net/par/Par152.tar.gz"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Updated] par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (18 preceding siblings ...)
  2019-10-27 15:06 ` voidlinux-github
@ 2019-10-27 18:43 ` voidlinux-github
  2019-10-27 18:43 ` voidlinux-github
  2019-10-28  8:57 ` [PR PATCH] [Merged]: " voidlinux-github
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-27 18:43 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

There is an updated pull request by ValTimchenko against master on the void-packages repository

https://github.com/ValTimchenko/void-packages par-unicode
https://github.com/void-linux/void-packages/pull/15812

par: added unicode support
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

A patch file from https://github.com/void-linux/void-packages/pull/15812.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-par-unicode-15812.patch --]
[-- Type: text/x-diff, Size: 88202 bytes --]

From a840bcb1601183e765e3545b777cb0f07a55a145 Mon Sep 17 00:00:00 2001
From: ValTimchenko <ValTimchenko@gmail.com>
Date: Sat, 26 Oct 2019 17:35:29 +0300
Subject: [PATCH] par: add unicode patch

---
 srcpkgs/par/patches/par-i18n.patch | 2858 ++++++++++++++++++++++++++++
 srcpkgs/par/template               |    4 +-
 2 files changed, 2860 insertions(+), 2 deletions(-)
 create mode 100644 srcpkgs/par/patches/par-i18n.patch

diff --git a/srcpkgs/par/patches/par-i18n.patch b/srcpkgs/par/patches/par-i18n.patch
new file mode 100644
index 00000000000..2755425f702
--- /dev/null
+++ b/srcpkgs/par/patches/par-i18n.patch
@@ -0,0 +1,2858 @@
+diff -c ./buffer.c ../Par152-unicode/buffer.c
+*** ./buffer.c	2001-03-09 02:51:11.000000000 +0300
+--- ../Par152-unicode/buffer.c	2019-10-26 17:21:08.542050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,23 ****
+--- 20,26 ----
+  
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wchar.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 60,66 ****
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     strcpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+--- 63,69 ----
+    blk = malloc(sizeof (block));
+    items = malloc(maxhere * itemsize);
+    if (!buf || !blk || !items) {
+!     wcscpy(errmsg,outofmem);
+      goto nberror;
+    }
+  
+***************
+*** 127,133 ****
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         strcpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+--- 130,136 ----
+        new = malloc(sizeof (block));
+        items = malloc(maxhere * itemsize);
+        if (!new || !items) {
+!         wcscpy(errmsg,outofmem);
+          goto aierror;
+        }
+        blk->next = new;
+***************
+*** 174,180 ****
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     strcpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+--- 177,183 ----
+  
+    r = malloc(n * itemsize);
+    if (!r) {
+!     wcscpy(errmsg,outofmem);
+      return NULL;
+    }
+  
+diff -c ./buffer.h ../Par152-unicode/buffer.h
+*** ./buffer.h	2001-03-09 02:51:25.000000000 +0300
+--- ../Par152-unicode/buffer.h	2019-10-26 17:21:08.543050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* buffer.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* buffer.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+diff -c ./charset.c ../Par152-unicode/charset.c
+*** ./charset.c	2001-04-03 01:51:48.000000000 +0400
+--- ../Par152-unicode/charset.c	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.c         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.c           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 18,25 ****
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+- #include <ctype.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+--- 20,28 ----
+                        /* prototypes.  Also includes "errmsg.h". */
+  #include "buffer.h"   /* Also includes <stddef.h>.              */
+  
+  #include <stdio.h>
++ #include <wchar.h>
++ #include <wctype.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+***************
+*** 39,46 ****
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   char *inlist;    /* Characters in inlist are in the set.                */
+!   char *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+--- 42,49 ----
+  typedef unsigned char csflag_t;
+  
+  struct charset {
+!   wchar_t *inlist;    /* Characters in inlist are in the set.                */
+!   wchar_t *outlist;   /* Characters in outlist are not in the set.           */
+                     /* inlist and outlist must have no common characters.  */
+                     /* inlist and outlist may be NULL, which acts like "". */
+    csflag_t flags;  /* Characters in neither list are in the set if they   */
+***************
+*** 56,80 ****
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(char c, const char *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && strchr(str,c);
+  }
+  
+  
+! static int hexdigtoint(char c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const char *p, * const hexdigits = "0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = strchr(hexdigits, *(unsigned char *)&c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+--- 59,83 ----
+                        CS_NUL   = 8;  /* Includes the NUL character.      */
+  
+  
+! static int appearsin(wchar_t c, const wchar_t *str)
+  
+  /* Returns 0 if c is '\0' or str is NULL or c     */
+  /* does not appear in *str.  Otherwise returns 1. */
+  {
+!   return c && str && wcschr(str,c);
+  }
+  
+  
+! static int hexdigtoint(wchar_t c)
+  
+  /* Returns the value represented by the hexadecimal */
+  /* digit c, or -1 if c is not a hexadecimal digit.  */
+  {
+!   const wchar_t *p, * const hexdigits = L"0123456789ABCDEFabcdef";
+    int n;
+  
+    if (!c) return -1;
+!   p = wcschr(hexdigits, c);
+    if (!p) return -1;
+    n = p - hexdigits;
+    if (n >= 16) n -= 6;
+***************
+*** 87,125 ****
+  }
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const char *p, * const singleescapes = "_sbqQx";
+    int hex1, hex2;
+!   char ch;
+! 
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     strcpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == '_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == '_') ch = '_' ;
+!         else if (*p == 's') ch = ' ' ;
+!         else if (*p == 'b') ch = '\\';
+!         else if (*p == 'q') ch = '\'';
+!         else if (*p == 'Q') ch = '\"';
+          else /*  *p == 'x'  */ {
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           *(unsigned char *)&ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+--- 90,129 ----
+  }
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg)
+  {
+    charset *cset = NULL;
+    buffer *cbuf = NULL;
+!   const wchar_t *p, * const singleescapes = L"_sbqQx";
+    int hex1, hex2;
+!   wchar_t ch;
+!       
+    cset = malloc(sizeof (charset));
+    if (!cset) {
+!     wcscpy(errmsg,outofmem);
+      goto pcserror;
+    }
+    cset->inlist = cset->outlist = NULL;
+    cset->flags = 0;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto pcserror;
+  
+    for (p = str;  *p;  ++p)
+!     if (*p == L'_') {
+        ++p;
+        if (appearsin(*p, singleescapes)) {
+!         if      (*p == L'_') ch = L'_' ;
+!         else if (*p == L's') ch = L' ' ;
+!         else if (*p == L'b') ch = L'\\';
+!         else if (*p == L'q') ch = L'\'';
+!         else if (*p == L'Q') ch = L'\"';
+          else /*  *p == 'x'  */ {
++           /* FIXME _x metacharacter should allow wide characters input.*/
+            hex1 = hexdigtoint(p[1]);
+            hex2 = hexdigtoint(p[2]);
+            if (hex1 < 0  ||  hex2 < 0) goto pcsbadstr;
+!           ch = 16 * hex1 + hex2;
+            p += 2;
+          }
+          if (!ch)
+***************
+*** 130,143 ****
+          }
+        }
+        else {
+!         if      (*p == 'A') cset->flags |= CS_UCASE;
+!         else if (*p == 'a') cset->flags |= CS_LCASE;
+!         else if (*p == '0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf,p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+--- 134,147 ----
+          }
+        }
+        else {
+!         if      (*p == L'A') cset->flags |= CS_UCASE;
+!         else if (*p == L'a') cset->flags |= CS_LCASE;
+!         else if (*p == L'0') cset->flags |= CS_DIGIT;
+          else goto pcsbadstr;
+        }
+      }
+      else {
+!       additem(cbuf, p,errmsg);
+        if (*errmsg) goto pcserror;
+      }
+    ch = '\0';
+***************
+*** 149,159 ****
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
+    return cset;
+  
+  pcsbadstr:
+  
+!   sprintf(errmsg, "Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+--- 153,164 ----
+  pcscleanup:
+  
+    if (cbuf) freebuffer(cbuf);
++   //if (wstr) free(wstr);
+    return cset;
+  
+  pcsbadstr:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad charset syntax: %.*s\n", errmsg_size - 22, str);
+  
+  pcserror:
+  
+***************
+*** 171,184 ****
+  }
+  
+  
+! int csmember(char c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!       ( (cset->flags & CS_LCASE && islower(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_UCASE && isupper(*(unsigned char *)&c)) ||
+!         (cset->flags & CS_DIGIT && isdigit(*(unsigned char *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+--- 176,189 ----
+  }
+  
+  
+! int csmember(wchar_t c, const charset *cset)
+  {
+    return
+      appearsin(c, cset->inlist) ||
+      ( !appearsin(c, cset->outlist) &&
+!         ( (cset->flags & CS_LCASE && iswlower(*(wint_t *)&c)) ||
+!           (cset->flags & CS_UCASE && iswupper(*(wint_t *)&c)) ||
+!           (cset->flags & CS_DIGIT && iswdigit(*(wint_t *)&c)) ||
+          (cset->flags & CS_NUL   && !c                           )   ) );
+  }
+  
+***************
+*** 191,206 ****
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   char *lists[4], **list, *p, nullchar = '\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     strcpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+--- 196,211 ----
+  {
+    charset *csu;
+    buffer *inbuf = NULL, *outbuf = NULL;
+!   wchar_t *lists[4], **list, *p, nullchar = L'\0';
+  
+    csu = malloc(sizeof (charset));
+    if (!csu) {
+!     wcscpy(errmsg,outofmem);
+      goto csuderror;
+    }
+!   inbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+!   outbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto csuderror;
+    csu->inlist = csu->outlist = NULL;
+    csu->flags =  u  ?  cset1->flags |  cset2->flags
+diff -c ./charset.h ../Par152-unicode/charset.h
+*** ./charset.h	2001-03-09 03:50:35.000000000 +0300
+--- ../Par152-unicode/charset.h	2019-10-26 17:21:08.544050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* charset.h         */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* charset.h           */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,24 ****
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! 
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const char *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+--- 13,26 ----
+  /* Note: Those functions declared here which do not use errmsg    */
+  /* always succeed, provided that they are passed valid arguments. */
+  
+! #include <wchar.h>
+  #include "errmsg.h"
+  
+  
+  typedef struct charset charset;
+  
+  
+! charset *parsecharset(const wchar_t *str, errmsg_t errmsg);
+  
+    /* parsecharset(str,errmsg) returns the set of characters defined by */
+    /* str using charset syntax (see par.doc).  Returns NULL on failure. */
+***************
+*** 30,36 ****
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(char c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+--- 32,38 ----
+    /* *cset.  cset may not be used after this call.      */
+  
+  
+! int csmember(wchar_t c, const charset *cset);
+  
+    /* csmember(c,cset) returns 1 if c is a member of *cset, 0 otherwise. */
+  
+diff -c ./errmsg.c ../Par152-unicode/errmsg.c
+*** ./errmsg.c	2001-03-09 03:50:46.000000000 +0300
+--- ../Par152-unicode/errmsg.c	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.c          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.c            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,18 ****
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const char * const outofmem =
+!   "Out of memory.\n";
+  
+! const char * const impossibility =
+!   "Impossibility #%d has occurred.  Please report it.\n";
+--- 13,23 ----
+  #include "errmsg.h"  /* Makes sure we're consistent with the declarations. */
+  
+  
+! const wchar_t * const outofmem =
+!   L"Out of memory.\n";
+  
+! const wchar_t * const mbserror =
+!   L"Error in input multibyte string.\n";
+! 
+! const wchar_t * const impossibility =
+!   L"Impossibility #%d has occurred.  Please report it.\n";
+diff -c ./errmsg.h ../Par152-unicode/errmsg.h
+*** ./errmsg.h	2001-03-09 03:50:56.000000000 +0300
+--- ../Par152-unicode/errmsg.h	2019-10-26 17:21:08.545050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* errmsg.h          */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* errmsg.h            */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 11,17 ****
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! 
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+--- 13,19 ----
+  #ifndef ERRMSG_H
+  #define ERRMSG_H
+  
+! #include <wchar.h>
+  #define errmsg_size 163
+  
+  /* This is the maximum number of characters that will  */
+***************
+*** 20,26 ****
+  /* versions of this header file.                       */
+  
+  
+! typedef char errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+--- 22,28 ----
+  /* versions of this header file.                       */
+  
+  
+! typedef wchar_t errmsg_t[errmsg_size];
+  
+  /* Any function which takes the argument errmsg_t errmsg must, before */
+  /* returning, either set errmsg[0] to '\0' (indicating success), or   */
+***************
+*** 28,37 ****
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const char * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const char * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+--- 30,42 ----
+  /* being careful not to overrun the space.                            */
+  
+  
+! extern const wchar_t * const outofmem;
+    /* "Out of memory.\n" */
+  
+! extern const wchar_t * const mbserror;
+!   /* "Error in input multibyte string.\n" */
+!   
+! extern const wchar_t * const impossibility;
+    /* "Impossibility #%d has occurred.  Please report it.\n" */
+  
+  
+diff -c ./par.1 ../Par152-unicode/par.1
+*** ./par.1	2001-04-30 01:16:22.000000000 +0400
+--- ../Par152-unicode/par.1	2019-10-26 17:21:08.546050853 +0300
+***************
+*** 1,6 ****
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52      *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+--- 1,6 ----
+  .\"*********************
+  .\"* par.1             *
+! .\"* for Par 1.52 i18n *
+  .\"* Copyright 2001 by *
+  .\"* Adam M. Costello  *
+  .\"*********************
+diff -c ./par.c ../Par152-unicode/par.c
+*** ./par.c	2001-04-02 08:25:57.000000000 +0400
+--- ../Par152-unicode/par.c	2019-10-26 17:21:08.547050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* par.c             */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* par.c               */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 12,22 ****
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <ctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+--- 14,27 ----
+  #include "buffer.h"    /* Also includes <stddef.h>. */
+  #include "reformat.h"
+  
+! #include <langinfo.h>
+! #include <wchar.h>
+! #include <wctype.h>
+  #include <locale.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <errno.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 25,80 ****
+  #define free(ptr)
+  #endif
+  
+- 
+- /*===
+- 
+- Regarding char and unsigned char:  ANSI C is a nightmare in this
+- respect.  Some functions, like puts(), strchr(), and getenv(), use char
+- or char*, so they work well with character constants like 'a', which
+- are char, and with argv, which is char**.  But several other functions,
+- like getchar(), putchar(), and isdigit(), use unsigned char (converted
+- to/from int).  Therefore innocent-looking code can be wrong, for
+- example:
+- 
+-     int c = getchar();
+-     if (c == 'a') ...
+- 
+- This is wrong because 'a' is char (converted to int) and could be
+- negative, but getchar() returns unsigned char (converted to int), so c
+- is always nonnegative or EOF.  For similar reasons, it is wrong to pass
+- a char to a function that expects an unsigned char:
+- 
+-     putchar('\n');
+-     if (isdigit(argv[1][0])) ...
+- 
+- Inevitably, we need to convert between char and unsigned char.  This can
+- be done by integral conversion (casting or assigning a char to unsigned
+- char or vice versa), or by aliasing (converting a pointer to char to
+- a pointer to unsigned char (or vice versa) and then dereferencing
+- it).  ANSI C requires that integral conversion alters the bits when the
+- unsigned value is not representable in the signed type and the signed
+- type does not use two's complement representation.  Aliasing, on the
+- other hand, preserves the bits.  Although the C standard is not at all
+- clear about which sort of conversion is appropriate for making the
+- standard library functions interoperate, I think preserving the bits
+- is what is needed.  Under that assumption, here are some examples of
+- correct code:
+- 
+-     int c = getchar();
+-     char ch;
+- 
+-     if (c != EOF) {
+-       *(unsigned char *)&ch = c;
+-       if (ch == 'a') ...
+-       if (isdigit(c)) ...
+-     }
+- 
+-     char *s = ...
+-     if (isdigit(*(unsigned char *)s)) ...
+- 
+- ===*/
+- 
+- 
+  static const char * const usagemsg =
+  "\n"
+  "Options for par:\n"
+--- 30,35 ----
+***************
+*** 126,132 ****
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   char rc;        /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+--- 81,87 ----
+                    /* line, or the fallback prelen and suflen       */
+                    /* of the IP containing a non-bodiless line.     */
+    lflag_t flags;  /* Boolean properties (see below).               */
+!   wchar_t rc;     /* The repeated character of a bodiless line.    */
+  } lineprop;
+  
+  /* Flags for marking boolean properties: */
+***************
+*** 143,156 ****
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(char c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const char *p, * const digits = "0123456789";
+  
+    if (!c) return -1;
+!   p = strchr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+--- 98,111 ----
+  #define   isvacant(prop) (isbodiless(prop) && (prop)->rc == ' ')
+  
+  
+! static int digtoint(wchar_t c)
+  
+  /* Returns the value represented by the digit c, or -1 if c is not a digit. */
+  {
+!   const wchar_t *p, * const digits = L"0123456789";
+  
+    if (!c) return -1;
+!   p = wcschr(digits,c);
+    return  p  ?  p - digits  :  -1;
+  
+    /* We can't simply return c - '0' because this is ANSI C code,  */
+***************
+*** 161,167 ****
+  }
+  
+  
+! static int strtoudec(const char *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+--- 116,122 ----
+  }
+  
+  
+! static int strtoudec(const wchar_t *s, int *pn)
+  
+  /* Converts the longest prefix of string s consisting of decimal   */
+  /* digits to an integer, which is stored in *pn.  Normally returns */
+***************
+*** 187,193 ****
+  
+  
+  static void parsearg(
+!   const char *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+--- 142,148 ----
+  
+  
+  static void parsearg(
+!   const wchar_t *arg, int *phelp, int *pversion, charset *bodychars, charset
+    *protectchars, charset *quotechars, int *phang, int *pprefix, int *prepeat,
+    int *psuffix, int *pTab, int *pwidth, int *pbody, int *pcap, int *pdiv, int
+    *pErr, int *pexpel, int *pfit, int *pguess, int *pinvis, int *pjust, int
+***************
+*** 197,274 ****
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const char *savearg = arg;
+    charset *chars, *change;
+!   char oc;
+    int n;
+  
+    *errmsg = '\0';
+  
+!   if (*arg == '-') ++arg;
+! 
+!   if (!strcmp(arg, "help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!strcmp(arg, "version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == 'B' || *arg == 'P' || *arg == 'Q' ) {
+!     chars =  *arg == 'B'  ?  bodychars    :
+!              *arg == 'P'  ?  protectchars :
+!           /* *arg == 'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != '='  &&  *arg != '+'  &&  *arg != '-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == '=')   csswap(chars,change);
+!       else if (*arg == '+')   csadd(chars,change,errmsg);
+!       else  /* *arg == '-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (isdigit(*(unsigned char *)arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (isdigit(*(unsigned char *)arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == 'h' || oc == 'p' || oc == 'r'
+!         || oc == 's' || oc == 'T' || oc == 'w') {
+!       if      (oc == 'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == 'p')   *pprefix =  n;
+!       else if (oc == 'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == 's')   *psuffix =  n;
+!       else if (oc == 'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == 'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == 'b') *pbody   = n;
+!       else if (oc == 'c') *pcap    = n;
+!       else if (oc == 'd') *pdiv    = n;
+!       else if (oc == 'E') *pErr    = n;
+!       else if (oc == 'e') *pexpel  = n;
+!       else if (oc == 'f') *pfit    = n;
+!       else if (oc == 'g') *pguess  = n;
+!       else if (oc == 'i') *pinvis  = n;
+!       else if (oc == 'j') *pjust   = n;
+!       else if (oc == 'l') *plast   = n;
+!       else if (oc == 'q') *pquote  = n;
+!       else if (oc == 'R') *pReport = n;
+!       else if (oc == 't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+--- 152,229 ----
+  /* by the other pointers as appropriate.  *phelp and *pversion are boolean  */
+  /* flags indicating whether the help and version options were supplied.     */
+  {
+!   const wchar_t *savearg = arg;
+    charset *chars, *change;
+!   wchar_t oc;
+    int n;
+  
+    *errmsg = '\0';
++   
++   if (*arg == L'-') ++arg;
+  
+!   if (!wcscmp(arg, L"help")) {
+      *phelp = 1;
+      return;
+    }
+  
+!   if (!wcscmp(arg, L"version")) {
+      *pversion = 1;
+      return;
+    }
+  
+!   if (*arg == L'B' || *arg == L'P' || *arg == L'Q' ) {
+!     chars =  *arg == L'B'  ?  bodychars    :
+!              *arg == L'P'  ?  protectchars :
+!           /* *arg == L'Q' */  quotechars   ;
+      ++arg;
+!     if (*arg != L'='  &&  *arg != L'+'  &&  *arg != L'-') goto badarg;
+      change = parsecharset(arg + 1, errmsg);
+      if (change) {
+!       if      (*arg == L'=')   csswap(chars,change);
+!       else if (*arg == L'+')   csadd(chars,change,errmsg);
+!       else  /* *arg == L'-' */ csremove(chars,change,errmsg);
+        freecharset(change);
+      }
+      return;
+    }
+  
+!   if (iswdigit(*arg)) {
+      if (!strtoudec(arg, &n)) goto badarg;
+      if (n <= 8) *pprefix = n;
+      else *pwidth = n;
+    }
+  
+    for (;;) {
+!     while (iswdigit(*arg)) ++arg;
+      oc = *arg;
+      if (!oc) break;
+      n = -1;
+      if (!strtoudec(++arg, &n)) goto badarg;
+!     if (   oc == L'h' || oc == L'p' || oc == L'r'
+!         || oc == L's' || oc == L'T' || oc == L'w') {
+!       if      (oc == L'h')   *phang   =  n >= 0 ? n :  1;
+!       else if (oc == L'p')   *pprefix =  n;
+!       else if (oc == L'r')   *prepeat =  n >= 0 ? n :  3;
+!       else if (oc == L's')   *psuffix =  n;
+!       else if (oc == L'T')   *pTab    =  n >= 0 ? n :  8;
+!       else  /* oc == L'w' */ *pwidth  =  n >= 0 ? n : 79;
+      }
+      else {
+        if (n < 0) n = 1;
+        if (n > 1) goto badarg;
+!       if      (oc == L'b') *pbody   = n;
+!       else if (oc == L'c') *pcap    = n;
+!       else if (oc == L'd') *pdiv    = n;
+!       else if (oc == L'E') *pErr    = n;
+!       else if (oc == L'e') *pexpel  = n;
+!       else if (oc == L'f') *pfit    = n;
+!       else if (oc == L'g') *pguess  = n;
+!       else if (oc == L'i') *pinvis  = n;
+!       else if (oc == L'j') *pjust   = n;
+!       else if (oc == L'l') *plast   = n;
+!       else if (oc == L'q') *pquote  = n;
+!       else if (oc == L'R') *pReport = n;
+!       else if (oc == L't') *ptouch  = n;
+        else goto badarg;
+      }
+    }
+***************
+*** 277,288 ****
+  
+  badarg:
+  
+!   sprintf(errmsg, "Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static char **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+--- 232,243 ----
+  
+  badarg:
+  
+!   swprintf(errmsg, errmsg_size, L"Bad argument: %.*s\n", errmsg_size - 16, savearg);
+    *phelp = 1;
+  }
+  
+  
+! static wchar_t **readlines(
+    lineprop **pprops, const charset *protectchars,
+    const charset *quotechars, int Tab, int invis, int quote, errmsg_t errmsg
+  )
+***************
+*** 302,310 ****
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   int c, empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   char ch, *ln = NULL, nullchar = '\0', *nullline = NULL, *qpend,
+!        *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+--- 257,266 ----
+  /* it's not NULL.  On failure, returns NULL and sets *pprops to NULL.   */
+  {
+    buffer *cbuf = NULL, *lbuf = NULL, *lpbuf = NULL;
+!   wint_t c;
+!   int empty, blank, firstline, qsonly, oldqsonly = 0, vlnlen, i;
+!   wchar_t *ln = NULL, nullchar = L'\0', *nullline = NULL, *qpend, 
+!     *oldln = NULL, *oldqpend = NULL, *p, *op, *vln = NULL, **lines = NULL;
+    lineprop vprop = { 0, 0, 0, '\0' }, iprop = { 0, 0, 0, '\0' };
+  
+    /* oldqsonly, oldln, and oldquend don't really need to be initialized.   */
+***************
+*** 316,335 ****
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (char), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getchar();
+!     if (c == EOF) break;
+!     *(unsigned char *)&ch = c;
+!     if (ch == '\n') {
+        if (blank) {
+!         ungetc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+--- 272,296 ----
+  
+    *pprops = NULL;
+  
+!   cbuf = newbuffer(sizeof (wchar_t), errmsg);
+    if (*errmsg) goto rlcleanup;
+!   lbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rlcleanup;
+    lpbuf = newbuffer(sizeof (lineprop), errmsg);
+    if (*errmsg) goto rlcleanup;
+  
+    for (empty = blank = firstline = 1;  ;  ) {
+!     c = getwchar();
+!     if (c == WEOF) {
+!       if (errno == EILSEQ) {
+!       	wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+! 	goto rlcleanup;
+!       }
+!       break;
+!     }
+!     if (c == L'\n') {
+        if (blank) {
+!         ungetwc(c,stdin);
+          break;
+        }
+        additem(cbuf, &nullchar, errmsg);
+***************
+*** 338,346 ****
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == ' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  *p == '\0';
+!         while (qpend > ln && qpend[-1] == ' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+--- 299,307 ----
+        if (*errmsg) goto rlcleanup;
+        if (quote) {
+          for (qpend = ln;  *qpend && csmember(*qpend, quotechars);  ++qpend);
+!         for (p = qpend;  *p == L' ' || csmember(*p, quotechars);  ++p);
+!         qsonly =  (*p == L'\0');
+!         while (qpend > ln && qpend[-1] == L' ') --qpend;
+          if (!firstline) {
+            for (p = ln, op = oldln;
+                 p < qpend && op < oldqpend && *p == *op;
+***************
+*** 348,370 ****
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = '\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = '\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (char));
+                if (!vln) {
+!                 strcpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               strncpy(vln,ln,vlnlen);
+!               vln[vlnlen] = '\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+--- 309,331 ----
+            if (!(p == qpend && op == oldqpend)) {
+              if (!invis && (oldqsonly || qsonly)) {
+                if (oldqsonly) {
+!                 *op = L'\0';
+                  oldqpend = op;
+                }
+                if (qsonly) {
+!                 *p = L'\0';
+                  qpend = p;
+                }
+              }
+              else {
+                vlnlen = p - ln;
+!               vln = malloc((vlnlen + 1) * sizeof (wchar_t));
+                if (!vln) {
+!                 wcscpy(errmsg,outofmem);
+                  goto rlcleanup;
+                }
+!               wcsncpy(vln, ln, vlnlen);
+!               vln[vlnlen] = L'\0';
+                additem(lbuf, &vln, errmsg);
+                if (*errmsg) goto rlcleanup;
+                additem(lpbuf,  invis ? &iprop : &vprop,  errmsg);
+***************
+*** 388,415 ****
+      }
+      else {
+        if (empty) {
+!         if (csmember(ch, protectchars)) {
+!           ungetc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!ch) continue;
+!       if (ch == '\t') {
+!         ch = ' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &ch, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (isspace(c)) ch = ' ';
+!       else blank = 0;
+!       additem(cbuf, &ch, errmsg);
+!       if (*errmsg) goto rlcleanup;
+      }
+    }
+! 
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+--- 349,379 ----
+      }
+      else {
+        if (empty) {
+!         if (csmember(c, protectchars)) {
+!           ungetwc(c,stdin);
+            break;
+          }
+          empty = 0;
+        }
+!       if (!c) continue;
+!       if (c == L'\t') {
+!         c = L' ';
+          for (i = Tab - numitems(cbuf) % Tab;  i > 0;  --i) {
+!           additem(cbuf, &c, errmsg);
+            if (*errmsg) goto rlcleanup;
+          }
+          continue;
+        }
+!       if (iswspace(c)) 
+!         c = L' ';
+!       else 
+!         blank = 0;
+!       additem(cbuf, &c, errmsg);
+!       if (*errmsg) 
+!         goto rlcleanup;
+      }
+    }
+!   
+    if (!blank) {
+      additem(cbuf, &nullchar, errmsg);
+      if (*errmsg) goto rlcleanup;
+***************
+*** 449,455 ****
+  
+  
+  static void compresuflen(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+--- 413,419 ----
+  
+  
+  static void compresuflen(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf
+  )
+  /* lines is an array of strings, up to but not including endline.  */
+***************
+*** 457,465 ****
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+! 
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+--- 421,429 ----
+  /* lines in lines.  Assumes that they have already been determined */
+  /* to be at least pre and suf.  endline must not equal lines.      */
+  {
+!   const wchar_t *start, *end, *knownstart, * const *line, *p1, *p2, *knownend,
+               *knownstart2;
+!            
+    start = *lines;
+    end = knownstart = start + pre;
+    if (body)
+***************
+*** 474,480 ****
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != ' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+--- 438,444 ----
+    }
+    if (body)
+      for (p1 = end;  p1 > knownstart;  )
+!       if (*--p1 != L' ') {
+          if (csmember(*p1, bodychars))
+            end = p1;
+          else
+***************
+*** 501,518 ****
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == ' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == ' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const char * const *lines, const char * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+--- 465,482 ----
+    }
+    if (body) {
+      for (p1 = start;
+!          start < knownend && (*start == L' ' || csmember(*start, bodychars));
+           ++start);
+!     if (start > p1 && start[-1] == L' ') --start;
+    }
+    else
+!     while (end - start >= 2 && *start == L' ' && start[1] == L' ') ++start;
+    *psuf = end - start;
+  }
+  
+  
+  static void delimit(
+!   const wchar_t * const *lines, const wchar_t * const *endline,
+    const charset *bodychars, int repeat, int body, int div,
+    int pre, int suf, lineprop *props
+  )
+***************
+*** 523,530 ****
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const char * const *line, *end, *p, * const *nextline;
+!   char rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+--- 487,494 ----
+  /* and comsuflen of the lines in lines have already been     */
+  /* determined to be at least pre and suf, respectively.      */
+  {
+!   const wchar_t * const *line, *end, *p, * const *nextline;
+!   wchar_t rc;
+    lineprop *prop, *nextprop;
+    int anybodiless = 0, status;
+  
+***************
+*** 545,552 ****
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  ' ';
+!     if (rc != ' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+--- 509,516 ----
+      for (end = *line;  *end;  ++end);
+      end -= suf;
+      p = *line + pre;
+!     rc =  p < end  ?  *p  :  L' ';
+!     if (rc != L' ' && (!repeat || end - p < repeat))
+        prop->flags &= ~L_BODILESS;
+      else
+        while (p < end) {
+***************
+*** 589,597 ****
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == ' ');
+    do {
+!     if (((*line)[pre] == ' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+--- 553,561 ----
+    }
+  
+    line = lines, prop = props;
+!   status = ((*lines)[pre] == L' ');
+    do {
+!     if (((*line)[pre] == L' ') == status)
+        prop->flags |= L_FIRST;
+      ++line, ++prop;
+    } while (line < endline);
+***************
+*** 599,612 ****
+  
+  
+  static void marksuperf(
+!   const char * const * lines, const char * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const char * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+--- 563,576 ----
+  
+  
+  static void marksuperf(
+!   const wchar_t * const * lines, const wchar_t * const * endline, lineprop *props
+  )
+  /* lines points to the first line of a segment, and endline to one  */
+  /* line beyond the last line in the segment.  Sets L_SUPERF bits in */
+  /* the flags fields of the props array whenever the corresponding   */
+  /* line is superfluous.  L_BODILESS bits must already be set.       */
+  {
+!   const wchar_t * const *line, *p;
+    lineprop *prop, *mprop, dummy;
+    int inbody, num, mnum;
+  
+***************
+*** 619,625 ****
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != ' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+--- 583,589 ----
+    for (line = lines, prop = props;  line < endline;  ++line, ++prop)
+      if (isvacant(prop)) {
+        for (num = 0, p = *line;  *p;  ++p)
+!         if (*p != L' ') ++num;
+        if (inbody || num < mnum)
+          mnum = num, mprop = prop;
+        inbody = 0;
+***************
+*** 631,637 ****
+  
+  
+  static void setaffixes(
+!   const char * const *inlines, const char * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+--- 595,601 ----
+  
+  
+  static void setaffixes(
+!   const wchar_t * const *inlines, const wchar_t * const *endline,
+    const lineprop *props, const charset *bodychars,
+    const charset *quotechars, int hang, int body, int quote,
+    int *pafp, int *pfs, int *pprefix, int *psuffix
+***************
+*** 644,650 ****
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const char *p;
+  
+    numin = endline - inlines;
+  
+--- 608,614 ----
+  /* default value as specified in "par.doc".                            */
+  {
+    int numin, pre, suf;
+!   const wchar_t *p;
+  
+    numin = endline - inlines;
+  
+***************
+*** 666,676 ****
+  }
+  
+  
+! static void freelines(char **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   char **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+--- 630,640 ----
+  }
+  
+  
+! static void freelines(wchar_t **lines)
+  /* Frees the elements of lines, and lines itself. */
+  /* lines is a NULL-terminated array of strings.   */
+  {
+!   wchar_t **line;
+  
+    for (line = lines;  *line;  ++line)
+      free(*line);
+***************
+*** 678,745 ****
+    free(lines);
+  }
+  
+- 
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!        **nextline, **outlines = NULL, **line, ch;
+!   const char *env, * const whitechars = " \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   bodychars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   protectchars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   quotechars = parsecharset(env,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (char));
+      if (!parinit) {
+!       strcpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     strcpy(parinit,env);
+!     arg = strtok(parinit,whitechars);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = strtok(NULL,whitechars);
+      }
+      free(parinit);
+      parinit = NULL;
+--- 642,757 ----
+    free(lines);
+  }
+  
+  int main(int argc, const char * const *argv)
+  {
+    int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1,
+        Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0,
+        fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0,
+        touch = -1;
+!   int prefixbak, suffixbak, sawnonblank, oweblank, n, i, afp, fs;
+    charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL;
+!   wint_t c;
+!   wchar_t *state;
+!   wchar_t *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end,
+!     **nextline, **outlines = NULL, **line;
+!   const char *env;
+!   wchar_t *wenv = NULL;
+!   const wchar_t * const whitechars = L" \f\n\r\t\v";
+    errmsg_t errmsg = { '\0' };
+    lineprop *props = NULL, *firstprop, *nextprop;
+    FILE *errout;
++   char *langinfo;
+  
+  /* Set the current locale from the environment: */
+  
+    setlocale(LC_ALL,"");
++   langinfo = nl_langinfo(CODESET);
++   if (!strcmp(langinfo, "ANSI_X3.4-1968")) {
++     // We would like to fallback in an 8 bits encoding, but it is not easily possible.
++     //setlocale(LC_CTYPE, "C");
++     //langinfo = nl_langinfo(CODESET);
++     fwprintf( Err ? stderr : stdout, 
++         L"Warning: Locale seems not configured\n");
++   }
+  
+  /* Process environment variables: */
+  
+    env = getenv("PARBODY");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARBODY\n");
+!     goto parcleanup;
+!   }
+!   bodychars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARPROTECT");
+    if (!env) env = "";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARPROTECT\n");
+!     goto parcleanup;
+!   }
+!   protectchars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARQUOTE");
+    if (!env) env = "> ";
+!   wenv = malloc((strlen(env) + 1) * sizeof (wchar_t));
+!   if (!wenv) {
+!     wcscpy(errmsg,outofmem);
+!     goto parcleanup;
+!   }
+!   if (0 > mbstowcs(wenv,env, strlen(env) + 1)) {
+!     wcscpy(errmsg, L"Invalid multibyte sequence in PARQUOTE\n");
+!     goto parcleanup;
+!   }
+!   quotechars = parsecharset(wenv,errmsg);
+    if (*errmsg) {
+      help = 1;
+      goto parcleanup;
+    }
++   free(wenv);
++   wenv = NULL;
+  
+    env = getenv("PARINIT");
+    if (env) {
+!     parinit = malloc((strlen(env) + 1) * sizeof (wchar_t));
+      if (!parinit) {
+!       wcscpy(errmsg,outofmem);
+        goto parcleanup;
+      }
+!     if (0 > mbstowcs(parinit,env, strlen(env) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in PARINIT\n");
+!       goto parcleanup;
+!     }    
+!     arg = wcstok(parinit, whitechars, &state);
+      while (arg) {
+        parsearg(arg, &help, &version, bodychars, protectchars,
+                 quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+                 &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+                 &invis, &just, &last, &quote, &Report, &touch, errmsg );
+        if (*errmsg || help || version) goto parcleanup;
+!       arg = wcstok(NULL, whitechars, &state);
+      }
+      free(parinit);
+      parinit = NULL;
+***************
+*** 748,804 ****
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     parsearg(*argv, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     strcpy(errmsg, "<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+! 
+! /* Main loop: */
+! 
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getchar();
+!       if (c == EOF) break;
+!       *(unsigned char *)&ch = c;
+!       if (expel && ch == '\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(ch, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           puts("");
+            oweblank = 0;
+          }
+!         while (ch != '\n') {
+!           putchar(c);
+!           c = getchar();
+!           if (c == EOF) break;
+!           *(unsigned char *)&ch = c;
+          }
+        }
+!       if (ch != '\n') break;  /* subsumes the case that c == EOF */
+!       putchar(c);
+      }
+!     if (c == EOF) break;
+!     ungetc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+! 
+!     for (endline = inlines;  *endline;  ++endline);
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+--- 760,830 ----
+  /* Process command line arguments: */
+  
+    while (*++argv) {
+!     arg = malloc((strlen(*argv) + 1) * sizeof (wchar_t));
+!     if (0 > mbstowcs(arg, *argv, strlen(*argv) + 1)) {
+!       wcscpy(errmsg, L"Invalid multibyte sequence in argument\n");
+!       goto parcleanup;
+!     }
+!     parsearg(arg, &help, &version, bodychars, protectchars,
+               quotechars, &hang, &prefix, &repeat, &suffix, &Tab,
+               &width, &body, &cap, &div, &Err, &expel, &fit, &guess,
+               &invis, &just, &last, &quote, &Report, &touch, errmsg );
++     free(arg);
+      if (*errmsg || help || version) goto parcleanup;
+    }
+  
+    if (Tab == 0) {
+!     wcscpy(errmsg, L"<Tab> must not be 0.\n");
+      goto parcleanup;
+    }
+  
+    if (touch < 0) touch = fit || last;
+    prefixbak = prefix;
+    suffixbak = suffix;
+!   
+!   /* Main loop: */
+    for (sawnonblank = oweblank = 0;  ;  ) {
+      for (;;) {
+!       c = getwchar();
+!       if (c == WEOF) {
+!         if (errno == EILSEQ) {
+!           wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!           goto parcleanup;
+!         }
+!         break;
+!       }
+!       if (expel && c == L'\n') {
+          oweblank = sawnonblank;
+          continue;
+        }
+!       if (csmember(c, protectchars)) {
+          sawnonblank = 1;
+          if (oweblank) {
+!           fputwc(L'\n', stdout);
+            oweblank = 0;
+          }
+!         while (c != L'\n') {
+!           putwchar(c);
+!           c = getwchar();
+!           if (c == WEOF) {
+!             if (errno == EILSEQ) {
+!               wcscpy(errmsg, L"Invalid multibyte sequence in input\n");
+!               goto parcleanup;
+!             }
+!             break;
+!           }
+          }
+        }
+!       if (c != L'\n') break;  /* subsumes the case that c == EOF */
+!       putwchar(c);
+      }
+!     if (c == WEOF) break;
+!     ungetwc(c,stdin);
+  
+      inlines =
+        readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg);
+      if (*errmsg) goto parcleanup;
+!     for (endline = inlines;  *endline;  ++endline) ;
+      if (endline == inlines) {
+        free(inlines);
+        inlines = NULL;
+***************
+*** 807,844 ****
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       puts("");
+        oweblank = 0;
+      }
+  
+!     delimit((const char * const *) inlines,
+!             (const char * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const char * const *) inlines,
+!                  (const char * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == ' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == ' ') --end;
+!             *end = '\0';
+!             puts(*firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               sprintf(errmsg,impossibility,5);
+                goto parcleanup;
+              }
+!             printf("%.*s", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               putchar(*(unsigned char *)&firstprop->rc);
+!             puts(end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+--- 833,871 ----
+  
+      sawnonblank = 1;
+      if (oweblank) {
+!       fputwc(L'\n', stdout);
+        oweblank = 0;
+      }
+  
+!     delimit((const wchar_t * const *) inlines,
+!             (const wchar_t * const *) endline,
+              bodychars, repeat, body, div, 0, 0, props);
+  
+      if (expel)
+!       marksuperf((const wchar_t * const *) inlines,
+!                  (const wchar_t * const *) endline, props);
+  
+      firstline = inlines, firstprop = props;
++ 
+      do {
+        if (isbodiless(firstprop)) {
+          if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) {
+            for (end = *firstline;  *end;  ++end);
+!           if (!repeat || (firstprop->rc == L' ' && !firstprop->s)) {
+!             while (end > *firstline && end[-1] == L' ') --end;
+!             *end = L'\0';
+!             fwprintf(stdout, L"%ls\n", *firstline);
+            }
+            else {
+              n = width - firstprop->p - firstprop->s;
+              if (n < 0) {
+!               swprintf(errmsg,errmsg_size,impossibility,5);
+                goto parcleanup;
+              }
+!             fwprintf(stdout, L"%.*ls", firstprop->p, *firstline);
+              for (i = n;  i;  --i)
+!               fputwc(firstprop->rc, stdout);
+!             fwprintf(stdout, L"%ls\n", end - firstprop->s);
+            }
+          }
+          ++firstline, ++firstprop;
+***************
+*** 848,875 ****
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+! 
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const char * const *) firstline,
+!                  (const char * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         sprintf(errmsg,
+!                 "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const char * const *) firstline,
+!                  (const char * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+- 
+        for (line = outlines;  *line;  ++line)
+!         puts(*line);
+! 
+        freelines(outlines);
+        outlines = NULL;
+  
+--- 875,900 ----
+        for (nextline = firstline + 1, nextprop = firstprop + 1;
+             nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop);
+             ++nextline, ++nextprop);
+!       
+        prefix = prefixbak, suffix = suffixbak;
+!       setaffixes((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline, firstprop, bodychars,
+                   quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix);
+        if (width <= prefix + suffix) {
+!         swprintf(errmsg,errmsg_size,
+!                 L"<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n",
+                  width, prefix, suffix);
+          goto parcleanup;
+        }
+  
+        outlines =
+!         reformat((const wchar_t * const *) firstline,
+!                  (const wchar_t * const *) nextline,
+                   afp, fs, hang, prefix, suffix, width, cap,
+                   fit, guess, just, last, Report, touch, errmsg);
+        if (*errmsg) goto parcleanup;
+        for (line = outlines;  *line;  ++line)
+!         fwprintf(stdout, L"%ls\n", *line);
+        freelines(outlines);
+        outlines = NULL;
+  
+***************
+*** 884,890 ****
+    }
+  
+  parcleanup:
+! 
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+--- 909,915 ----
+    }
+  
+  parcleanup:
+!   if (wenv) free(wenv);
+    if (bodychars) freecharset(bodychars);
+    if (protectchars) freecharset(protectchars);
+    if (quotechars) freecharset(quotechars);
+***************
+*** 894,901 ****
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg);
+!   if (version) fputs("par 1.52\n",errout);
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+--- 919,930 ----
+    if (outlines) freelines(outlines);
+  
+    errout = Err ? stderr : stdout;
+!   if (*errmsg) fwprintf(errout, L"par error:\n%.*ls", errmsg_size, errmsg);
+! #ifdef NOWIDTH
+!   if (version) fputws(L"par 1.52-i18n.4 (without wcwidth() support)\n",errout);
+! #else
+!   if (version) fputws(L"par 1.52-i18n.4\n",errout);
+! #endif
+    if (help)    fputs(usagemsg,errout);
+  
+    return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS;
+Только в ../Par152-unicode/: par.c.orig
+diff -c ./par.doc ../Par152-unicode/par.doc
+*** ./par.doc	2001-04-30 01:17:28.000000000 +0400
+--- ../Par152-unicode/par.doc	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,6 ****
+    *********************
+    * par.doc           *
+!   * for Par 1.52      *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+--- 1,6 ----
+    *********************
+    * par.doc           *
+!   * for Par 1.52 i18n *
+    * Copyright 2001 by *
+    * Adam M. Costello  *
+    *********************
+diff -c ./protoMakefile ../Par152-unicode/protoMakefile
+*** ./protoMakefile	2001-03-09 03:53:25.000000000 +0300
+--- ../Par152-unicode/protoMakefile	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 47,53 ****
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+--- 47,53 ----
+  # Example (for Solaris 2.x with SPARCompiler C):
+  # CC = cc -c -O -s -Xc -DDONTFREE
+  
+! CC = cc -std=c99 -c
+  
+  # Define LINK1 and LINK2 so that the command
+  #
+diff -c ./reformat.c ../Par152-unicode/reformat.c
+*** ./reformat.c	2001-03-22 07:17:15.000000000 +0300
+--- ../Par152-unicode/reformat.c	2019-10-26 17:21:08.548050853 +0300
+***************
+*** 1,9 ****
+! /*********************/
+! /* reformat.c        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+--- 1,11 ----
+! /***********************/
+! /* reformat.c          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+***************
+*** 16,21 ****
+--- 18,24 ----
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
++ #include <wctype.h>
+  
+  #undef NULL
+  #define NULL ((void *) 0)
+***************
+*** 33,46 ****
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const char *chrs;       /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length;             /* Length of this word.                  */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+--- 36,50 ----
+  typedef unsigned char wflag_t;
+  
+  typedef struct word {
+!   const wchar_t *chrs;    /* Pointer to the characters in the word */
+                            /* (NOT terminated by '\0').             */
+    struct word *prev,      /* Pointer to previous word.             */
+                *next,      /* Pointer to next word.                 */
+                            /* Supposing this word were the first... */
+                *nextline;  /*   Pointer to first word in next line. */
+    int score,              /*   Value of the objective function.    */
+!       length,             /* Length (in widechar) of this word.    */
+!       width;              /* Visual width of this word.            */
+    wflag_t flags;          /* Notable properties of this word.      */
+  } word;
+  
+***************
+*** 57,73 ****
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const char *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !isalnum(*(unsigned char *)p);
+         ++p);
+!   return p < end && !islower(*(unsigned char *)p);
+  }
+  
+  
+--- 61,99 ----
+  #define iscurious(w) (((w)->flags & 2) != 0)
+  #define iscapital(w) (((w)->flags & 4) != 0)
+  
++ static int getWidth(const wchar_t *beg, const wchar_t *end)
++ /* Compute (visual) width of a  word. This function is aware */
++ /* about double-width characters used in oriental langages.  */
++ {
++   int ret, tmp;
++   
++   for (ret = 0; beg != end; beg++) {
++ #ifdef NOWIDTH
++     tmp = 1;
++ #else
++     tmp = wcwidth(*beg);
++ #endif
++     // BUG: It is not really easy to handle case of zero width characters.
++     // If we don't do this, size mallloc for q1 will be less than real 
++     // size and program will segfault. So I prefer to have a bug than a segfault.
++     if (tmp <= 0)
++       tmp = 1;
++     ret += tmp;
++   }
++   
++   return ret;
++ }
+  
+  static int checkcapital(word *w)
+  /* Returns 1 if *w is capitalized according to the definition */
+  /* in par.doc (assuming <cap> is 0), or 0 if not.             */
+  {
+!   const wchar_t *p, *end;
+  
+    for (p = w->chrs, end = p + w->length;
+!        p < end && !iswalnum(*p);
+         ++p);
+!   return p < end && !iswlower(*p);
+  }
+  
+  
+***************
+*** 75,93 ****
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const char *start, *p;
+!   char ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (isalnum(*(unsigned char *)&ch)) return 0;
+!     if (ch == '.' || ch == '?' || ch == '!' || ch == ':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (isalnum(*(unsigned char *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+--- 101,119 ----
+  /* Returns 1 if *w is curious according to */
+  /* the definition in par.doc, or 0 if not. */
+  {
+!   const wchar_t *start, *p;
+!   wchar_t ch;
+  
+    for (start = w->chrs, p = start + w->length;  p > start;  --p) {
+      ch = p[-1];
+!     if (iswalnum(*(wchar_t *)&ch)) return 0;
+!     if (ch == L'.' || ch == L'?' || ch == L'!' || ch == L':') break;
+    }
+  
+    if (p <= start + 1) return 0;
+  
+    --p;
+!   do if (iswalnum(*(wchar_t *)--p)) return 1;
+    while (p > start);
+  
+    return 0;
+***************
+*** 95,125 ****
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! 
+! /* Chooses line breaks in a list of words which maximize the length of the   */
+! /* shortest line.  L is the maximum line length.  The last line counts as a  */
+! /* line only if last is non-zero. _head must point to a dummy word, and tail */
+! /* must point to the last word, whose next field must be NULL.  Returns the  */
+! /* length of the shortest line on success, -1 if there is a word of length   */
+! /* greater than L, or L if there are no lines.                               */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->length;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->length) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+--- 121,152 ----
+  
+  
+  static int simplebreaks(word *head, word *tail, int L, int last)
+! /* Chooses line  breaks in a  list of words  which maximize */
+! /* the length of  the shortest line. L is  the maximum line */
+! /* length. The last  line counts as a line only  if last is */
+! /* non-zero. _head  must point  to a  dummy word,  and tail */
+! /* must point  to the last  word, whose next field  must be */
+! /* NULL.  Returns  the  length  of  the  shortest  line  on */
+! /* success, -1 if there is a word of length greater than L, */
+! /* or L if there are no lines.                              */
+  {
+    word *w1, *w2;
+    int linelen, score;
+  
+    if (!head->next) return L;
+  
+!   for (w1 = tail, linelen = w1->width;
+         w1 != head && linelen <= L;
+!        linelen += isshifted(w1), w1 = w1->prev, linelen += 1 + w1->width) {
+      w1->score = last ? linelen : L;
+      w1->nextline = NULL;
+    }
+  
+    for ( ;  w1 != head;  w1 = w1->prev) {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= L;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        score = w2->score;
+        if (linelen < score) score = linelen;
+        if (score >= w1->score) {
+***************
+*** 168,174 ****
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     sprintf(errmsg,impossibility,1);
+      return;
+    }
+  
+--- 195,201 ----
+  
+    shortest = simplebreaks(head,tail,target,last);
+    if (shortest < 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,1);
+      return;
+    }
+  
+***************
+*** 178,186 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->length,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->length,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+--- 205,213 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (linelen = w1->width,  w2 = w1->next;
+           linelen <= target;
+!          linelen += 1 + isshifted(w2) + w2->width,  w2 = w2->next) {
+        extra = target - linelen;
+        minlen = shortest;
+        if (w2)
+***************
+*** 202,208 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,2);
+  }
+  
+  
+--- 229,235 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,2);
+  }
+  
+  
+***************
+*** 225,233 ****
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 252,260 ----
+    w1 = tail;
+    do {
+      w1->score = L;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 247,253 ****
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     strcpy(errmsg, "Cannot justify.\n");
+      return;
+    }
+  
+--- 274,280 ----
+  
+    maxgap = head->next->score;
+    if (maxgap >= L) {
+!     wcscpy(errmsg, L"Cannot justify.\n");
+      return;
+    }
+  
+***************
+*** 257,265 ****
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->length, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+--- 284,292 ----
+    w1 = tail;
+    do {
+      w1->score = -1;
+!     for (numgaps = 0, extra = L - w1->width, w2 = w1->next;
+           extra >= 0;
+!          ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next) {
+        gap = numgaps ? (extra + numgaps - 1) / numgaps : L;
+        if (w2)
+          score = w2->score;
+***************
+*** 288,327 ****
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     sprintf(errmsg,impossibility,3);
+  }
+  
+  
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const char * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   char *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+- 
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     sprintf(errmsg,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const char *));
+    if (!suffixes) {
+!     strcpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+--- 315,353 ----
+    } while (w1 != head);
+  
+    if (head->next->score < 0)
+!     swprintf(errmsg,errmsg_size,impossibility,3);
+  }
+  
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  )
+  {
+    int numin, affix, L, onfirstword = 1, linelen, numout, numgaps, extra, phase;
+!   const wchar_t * const *line, **suffixes = NULL, **suf, *end, *p1, *p2;
+!   wchar_t *q1, *q2, **outlines = NULL;
+    word dummy, *head, *tail, *w1, *w2;
+    buffer *pbuf = NULL;
+  
+  /* Initialization: */
+    *errmsg = '\0';
+    dummy.next = dummy.prev = NULL;
+    dummy.flags = 0;
+    head = tail = &dummy;
+    numin = endline - inlines;
+    if (numin <= 0) {
+!     swprintf(errmsg,errmsg_size,impossibility,4);
+      goto rfcleanup;
+    }
+    numgaps = extra = 0;  /* unnecessary, but quiets compiler warnings */
+  
+  /* Allocate space for pointers to the suffixes: */
+  
+!   suffixes = malloc(numin * sizeof (const wchar_t *));
+    if (!suffixes) {
+!     wcscpy(errmsg,outofmem);
+      goto rfcleanup;
+    }
+  
+***************
+*** 334,341 ****
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       sprintf(errmsg,
+!               "Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+--- 360,367 ----
+    do {
+      for (end = *line;  *end;  ++end);
+      if (end - *line < affix) {
+!       swprintf(errmsg,errmsg_size,
+!               L"Line %d shorter than <prefix> + <suffix> = %d + %d = %d\n",
+                line - inlines + 1, prefix, suffix, affix);
+        goto rfcleanup;
+      }
+***************
+*** 343,359 ****
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == ' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != ' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         strcpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+--- 369,385 ----
+      *suf = end;
+      p1 = *line + prefix;
+      for (;;) {
+!       while (p1 < end && *p1 == L' ') ++p1;
+        if (p1 == end) break;
+        p2 = p1;
+        if (onfirstword) {
+          p1 = *line + prefix;
+          onfirstword = 0;
+        }
+!       while (p2 < end && *p2 != L' ') ++p2;
+        w1 = malloc(sizeof (word));
+        if (!w1) {
+!         wcscpy(errmsg,outofmem);
+          goto rfcleanup;
+        }
+        w1->next = NULL;
+***************
+*** 361,366 ****
+--- 387,393 ----
+        tail = tail->next = w1;
+        w1->chrs = p1;
+        w1->length = p2 - p1;
++       w1->width = getWidth(p1, p2);
+        w1->flags = 0;
+        p1 = p2;
+      }
+***************
+*** 377,382 ****
+--- 404,410 ----
+          if (iscurious(w1)) {
+            if (w1->chrs[w1->length] && w1->chrs + w1->length + 1 == w2->chrs) {
+              w2->length += w1->length + 1;
++             w2->width += w1->width + 1;
+              w2->chrs = w1->chrs;
+              w2->prev = w1->prev;
+              w2->prev->next = w2;
+***************
+*** 397,416 ****
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->length > L) {
+!         linelen = w2->length;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         sprintf(errmsg, "Word too long: %.*s\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->length > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           strcpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+--- 425,444 ----
+  
+    if (Report)
+      for (w2 = head->next;  w2;  w2 = w2->next) {
+!       if (w2->width > L) {
+!         linelen = w2->width;
+          if (linelen > errmsg_size - 17)
+            linelen = errmsg_size - 17;
+!         swprintf(errmsg,errmsg_size, L"Word too long: %.*ls\n", linelen, w2->chrs);
+          goto rfcleanup;
+        }
+      }
+    else
+      for (w2 = head->next;  w2;  w2 = w2->next)
+!       while (w2->width > L) {
+          w1 = malloc(sizeof (word));
+          if (!w1) {
+!           wcscpy(errmsg,outofmem);
+            goto rfcleanup;
+          }
+          w1->next = w2;
+***************
+*** 420,426 ****
+--- 448,456 ----
+          w1->chrs = w2->chrs;
+          w2->chrs += L;
+          w1->length = L;
++         w1->width = getWidth(w1->chrs, w1->chrs + L);
+          w2->length -= L;
++         w2->width -= w1->width;
+          w1->flags = 0;
+          if (iscapital(w2)) {
+            w1->flags |= W_CAPITAL;
+***************
+*** 444,452 ****
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->length, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->length, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+--- 474,482 ----
+      L = 0;
+      w1 = head->next;
+      while (w1) {
+!       for (linelen = w1->width, w2 = w1->next;
+             w2 != w1->nextline;
+!            linelen += 1 + isshifted(w2) + w2->width, w2 = w2->next);
+        if (linelen > L) L = linelen;
+        w1 = w2;
+      }
+***************
+*** 454,520 ****
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (char *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->length;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->length, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (char));
+      if (!q1) {
+!       strcpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix);
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp);
+        q1 += afp;
+!       while (q1 < q2) *q1++ = ' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length);
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = ' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = ' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = ' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = ' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix);
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix);
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs);
+        q1 += fs;
+!       while(q1 < q2) *q1++ = ' ';
+      }
+!     *q2 = '\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+--- 484,550 ----
+  
+  /* Construct the lines: */
+  
+!   pbuf = newbuffer(sizeof (wchar_t *), errmsg);
+    if (*errmsg) goto rfcleanup;
+  
+    numout = 0;
+    w1 = head->next;
+    while (numout < hang || w1) {
+      if (w1)
+!       for (w2 = w1->next, numgaps = 0, extra = L - w1->width;
+             w2 != w1->nextline;
+!            ++numgaps, extra -= 1 + isshifted(w2) + w2->width, w2 = w2->next);
+      linelen = suffix || (just && (w2 || last)) ?
+                  L + affix :
+                  w1 ? prefix + L - extra : prefix;
+!     q1 = malloc((linelen + 1) * sizeof (wchar_t));
+      if (!q1) {
+!       wcscpy(errmsg,outofmem);
+        goto rfcleanup;
+      }
+      additem(pbuf, &q1, errmsg);
+      if (*errmsg) goto rfcleanup;
+      ++numout;
+      q2 = q1 + prefix;
+!     if      (numout <= numin) memcpy(q1, inlines[numout - 1], prefix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, endline[-1],         prefix * sizeof(wchar_t));
+      else {
+        if (afp > prefix) afp = prefix;
+!       memcpy(q1, endline[-1], afp * sizeof(wchar_t));
+        q1 += afp;
+!       while (q1 < q2) *q1++ = L' ';
+      }
+      q1 = q2;
+      if (w1) {
+        phase = numgaps / 2;
+        for (w2 = w1;  ;  ) {
+!         memcpy(q1, w2->chrs, w2->length * sizeof(wchar_t));
+          q1 += w2->length;
+          w2 = w2->next;
+          if (w2 == w1->nextline) break;
+!         *q1++ = L' ';
+          if (just && (w1->nextline || last)) {
+            phase += extra;
+            while (phase >= numgaps) {
+!             *q1++ = L' ';
+              phase -= numgaps;
+            }
+          }
+!         if (isshifted(w2)) *q1++ = L' ';
+        }
+      }
+      q2 += linelen - affix;
+!     while (q1 < q2) *q1++ = L' ';
+      q2 = q1 + suffix;
+!     if      (numout <= numin) memcpy(q1, suffixes[numout - 1], suffix * sizeof(wchar_t));
+!     else if (numin  >  hang ) memcpy(q1, suffixes[numin  - 1], suffix * sizeof(wchar_t));
+      else {
+        if (fs > suffix) fs = suffix;
+!       memcpy(q1, suffixes[numin - 1], fs * sizeof(wchar_t));
+        q1 += fs;
+!       while(q1 < q2) *q1++ = L' ';
+      }
+!     *q2 = L'\0';
+      if (w1) w1 = w1->nextline;
+    }
+  
+***************
+*** 543,547 ****
+--- 573,578 ----
+      freebuffer(pbuf);
+    }
+  
++   
+    return outlines;
+  }
+diff -c ./reformat.h ../Par152-unicode/reformat.h
+*** ./reformat.h	2001-03-09 03:53:43.000000000 +0300
+--- ../Par152-unicode/reformat.h	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,18 ****
+! /*********************/
+! /* reformat.h        */
+! /* for Par 1.52      */
+! /* Copyright 2001 by */
+! /* Adam M. Costello  */
+! /*********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
+  
+! 
+! char **reformat(
+!   const char * const *inlines, const char * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+--- 1,20 ----
+! /***********************/
+! /* reformat.h          */
+! /* for Par 1.52-i18n.4 */
+! /* Copyright 2001 by   */
+! /* Adam M. Costello    */
+! /* Modified by         */
+! /* Jérôme Pouiller     */
+! /***********************/
+  
+  /* This is ANSI C code (C89). */
+  
+  
+  #include "errmsg.h"
++ #include <wchar.h>
+  
+! wchar_t **reformat(
+!   const wchar_t * const *inlines, const wchar_t * const *endline, int afp, int fs,
+    int hang, int prefix, int suffix, int width, int cap, int fit, int guess,
+    int just, int last, int Report, int touch, errmsg_t errmsg
+  );
+diff -c ./releasenotes ../Par152-unicode/releasenotes
+*** ./releasenotes	2001-04-30 01:12:05.000000000 +0400
+--- ../Par152-unicode/releasenotes	2019-10-26 17:21:08.549050853 +0300
+***************
+*** 1,12 ****
+!   *********************
+!   * releasenotes      *
+!   * for Par 1.52      *
+!   * Copyright 2001 by *
+!   * Adam M. Costello  *
+!   *********************
+  
+  
+  Each entry below describes changes since the previous version.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+--- 1,28 ----
+!   ***********************
+!   * releasenotes        *
+!   * for Par 1.52-i18n.4 *
+!   * Copyright 2001 by   *
+!   * Adam M. Costello    *
+!   * Modified by         *
+!   * Jérôme Pouiller     *
+!   ***********************
+  
+  
+  Each entry below describes changes since the previous version.
++ Par 1.52-i18n.4 released 2009-May-05
++     Change nearly all char in wchar_t remove nightmare of unsigned char vs signed char
++     Fix bugs with option 'q'
++     Fix bugs with '\n'
++ 
++ Par 1.52-i18n.3 released 2006-Oct-03
++     Fix bug with option 'g'
++ 
++ Par 1.52-i18n.2 released 2006-Aug-03
++     Fix bug debian #310495.
++ 
++ Par 1.52-i18n.1 released 2006-Jun-22
++     Changed char in wchar_t. Allow support of multibytes characters.
++     Added support for double-width characters.
+  
+  Par 1.52 released 2001-Apr-29
+      Fixed a portability problem regarding unsigned char versus char.
+Общие подкаталоги: ./test и ../Par152-unicode/test
diff --git a/srcpkgs/par/template b/srcpkgs/par/template
index 585a8887841..54747129b79 100644
--- a/srcpkgs/par/template
+++ b/srcpkgs/par/template
@@ -1,12 +1,12 @@
 # Template file for 'par'
 pkgname=par
 version=1.52
-revision=3
+revision=4
 wrksrc=Par152
 build_style=gnu-configure
 short_desc="Paragraph reformatter"
 maintainer="Leah Neukirchen <leah@vuxu.org>"
-license="custom"
+license="custom:par"
 homepage="http://www.nicemice.net/par/"
 distfiles="http://www.nicemice.net/par/Par152-autoconf.tar.gz
  http://www.nicemice.net/par/Par152.tar.gz"

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PR PATCH] [Merged]: par: added unicode support
  2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
                   ` (20 preceding siblings ...)
  2019-10-27 18:43 ` voidlinux-github
@ 2019-10-28  8:57 ` voidlinux-github
  21 siblings, 0 replies; 23+ messages in thread
From: voidlinux-github @ 2019-10-28  8:57 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 323 bytes --]

There's a merged pull request on the void-packages repository

par: added unicode support
https://github.com/void-linux/void-packages/pull/15812

Description:
Subj. Just added unicode patch made by Jérôme Pouiller as of: http://sysmic.org/dotclear/index.php?post/2006/06/22/55-add-multibyte-characters-support-in-par

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2019-10-28  8:57 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-26 14:43 [PR PATCH] Added unicode patch for par-1.52 voidlinux-github
2019-10-27  7:07 ` voidlinux-github
2019-10-27  8:31 ` par: added unicode support voidlinux-github
2019-10-27  8:32 ` voidlinux-github
2019-10-27  8:33 ` voidlinux-github
2019-10-27  8:41 ` [PR PATCH] [Updated] " voidlinux-github
2019-10-27  8:41 ` voidlinux-github
2019-10-27  9:04 ` voidlinux-github
2019-10-27  9:04 ` voidlinux-github
2019-10-27  9:06 ` voidlinux-github
2019-10-27  9:06 ` voidlinux-github
2019-10-27  9:09 ` voidlinux-github
2019-10-27  9:32 ` voidlinux-github
2019-10-27  9:46 ` voidlinux-github
2019-10-27  9:50 ` [PR PATCH] [Updated] " voidlinux-github
2019-10-27  9:50 ` voidlinux-github
2019-10-27  9:51 ` voidlinux-github
2019-10-27  9:51 ` voidlinux-github
2019-10-27  9:58 ` voidlinux-github
2019-10-27 15:06 ` voidlinux-github
2019-10-27 18:43 ` [PR PATCH] [Updated] " voidlinux-github
2019-10-27 18:43 ` voidlinux-github
2019-10-28  8:57 ` [PR PATCH] [Merged]: " voidlinux-github

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).