]> TLD Linux GIT Repositories - packages/coreutils.git/blob - coreutils-fmt-wchars.patch
- updated to 8.26
[packages/coreutils.git] / coreutils-fmt-wchars.patch
1 --- coreutils-8.26/po/pl.po.orig        2017-02-08 09:48:16.712532143 +0000
2 +++ coreutils-8.26/po/pl.po     2017-02-08 09:50:39.112530540 +0000
3 @@ -4440,12 +4440,14 @@
4  #, no-c-format
5  msgid ""
6  "  -t, --tagged-paragraph    indentation of first line different from second\n"
7 -"  -u, --uniform-spacing     one space between words, two after sentences\n"
8 +"  -u, --uniform-spacing     one space between words, two between sentences\n"
9 +"  -n, --single-spaces       single spaces between sentences\n"
10  "  -w, --width=WIDTH         maximum line width (default of 75 columns)\n"
11  "  -g, --goal=WIDTH          goal width (default of 93% of width)\n"
12  msgstr ""
13  "  -t, --tagged-paragraph    wcięcie pierwszej linii inne niż drugiej\n"
14  "  -u, --uniform-spacing     jedna spacja między słowami, dwie między zdaniami\n"
15 +"  -n, --single-spaces       pojedyncze spacje między zdaniami\n"
16  "  -w, --width=SZEROKOŚĆ     maksymalna SZEROKOŚĆ linii (domyślnie 75 kolumn)\n"
17  "  -g, --goal=SZEROKOŚĆ      docelowa SZEROKOŚĆ (domyślnie 93% of szerokości\n"
18  "                              linii)\n"
19 --- coreutils-8.19/src/fmt.c.orig       2012-07-21 16:54:31.000000000 +0200
20 +++ coreutils-8.19/src/fmt.c    2012-10-14 11:02:27.109233796 +0200
21 @@ -17,6 +17,7 @@
22  /* Written by Ross Paterson <rap@doc.ic.ac.uk>.  */
23  
24  #include <config.h>
25 +#include <wchar.h>
26  #include <stdio.h>
27  #include <sys/types.h>
28  #include <getopt.h>
29 @@ -40,7 +41,7 @@
30  /* The following parameters represent the program's idea of what is
31     "best".  Adjust to taste, subject to the caveats given.  */
32  
33 -/* Default longest permitted line length (max_width).  */
34 +/* Default longest permitted line width (max_width).  */
35  #define WIDTH  75
36  
37  /* Prefer lines to be LEEWAY % shorter than the maximum width, giving
38 @@ -52,7 +53,7 @@
39  #define DEF_INDENT 3
40  
41  /* Costs and bonuses are expressed as the equivalent departure from the
42 -   optimal line length, multiplied by 10.  e.g. assigning something a
43 +   optimal line width, multiplied by 10.  e.g. assigning something a
44     cost of 50 means that it is as bad as a line 5 characters too short
45     or too long.  The definition of SHORT_COST(n) should not be changed.
46     However, EQUIV(n) may need tuning.  */
47 @@ -79,11 +80,11 @@
48  #define LINE_COST      EQUIV (70)
49  
50  /* Cost of breaking a line after the first word of a sentence, where
51 -   the length of the word is N.  */
52 +   the width of the word is N.  */
53  #define WIDOW_COST(n)  (EQUIV (200) / ((n) + 2))
54  
55  /* Cost of breaking a line before the last word of a sentence, where
56 -   the length of the word is N.  */
57 +   the width of the word is N.  */
58  #define ORPHAN_COST(n) (EQUIV (150) / ((n) + 2))
59  
60  /* Bonus for breaking a line at the end of a sentence.  */
61 @@ -115,11 +116,30 @@
62  #define MAXWORDS       1000
63  #define MAXCHARS       5000
64  
65 +/* Wide character support */
66 +
67 +static wint_t
68 +xgetwc (FILE *stream)
69 +{
70 +  wint_t c = getwc (stream);
71 +  if (c == WEOF && ferror (stream))
72 +    error (EXIT_FAILURE, errno, _("read error"));
73 +  return c;
74 +}
75 +
76 +static inline int
77 +xwcwidth (wchar_t wc)
78 +{
79 +  int w = wcwidth (wc);
80 +  return w < 0 ? 0 : w;
81 +}
82 +
83  /* Extra ctype(3)-style macros.  */
84  
85 -#define isopen(c)      (strchr ("(['`\"", c) != NULL)
86 -#define isclose(c)     (strchr (")]'\"", c) != NULL)
87 -#define isperiod(c)    (strchr (".?!", c) != NULL)
88 +#define isopen(c)      \
89 +  (wcschr (L"(['`\"\u2018\u201A\u201B\u201C\u201E\u201F", c) != NULL)
90 +#define isclose(c)     (wcschr (L")]'\"\u2018\u2019\u201C\u201D", c) != NULL)
91 +#define isperiod(c)    (wcschr (L".?!", c) != NULL)
92  
93  /* Size of a tab stop, for expansion on input and re-introduction on
94     output.  */
95 @@ -134,8 +154,9 @@
96  
97      /* Static attributes determined during input.  */
98  
99 -    const char *text;          /* the text of the word */
100 -    int length;                        /* length of this word */
101 +    const wchar_t *text;       /* the text of the word */
102 +    int length;                        /* length of this word, in characters */
103 +    int width;                 /* width of this word, in columns */
104      int space;                 /* the size of the following space */
105      unsigned int paren:1;      /* starts with open paren */
106      unsigned int period:1;     /* ends in [.?!])* */
107 @@ -144,7 +165,7 @@
108  
109      /* The remaining fields are computed during the optimization.  */
110  
111 -    int line_length;           /* length of the best line starting here */
112 +    int line_width;            /* width of the best line starting here */
113      COST best_cost;            /* cost of best paragraph starting here */
114      WORD *next_break;          /* break which achieves best_cost */
115    };
116 @@ -154,16 +175,16 @@
117  static void set_prefix (char *p);
118  static void fmt (FILE *f);
119  static bool get_paragraph (FILE *f);
120 -static int get_line (FILE *f, int c);
121 -static int get_prefix (FILE *f);
122 -static int get_space (FILE *f, int c);
123 -static int copy_rest (FILE *f, int c);
124 -static bool same_para (int c);
125 +static wint_t get_line (FILE *f, wint_t c);
126 +static wint_t get_prefix (FILE *f);
127 +static wint_t get_space (FILE *f, wint_t c);
128 +static wint_t copy_rest (FILE *f, wint_t c);
129 +static bool same_para (wint_t c);
130  static void flush_paragraph (void);
131  static void fmt_paragraph (void);
132  static void check_punctuation (WORD *w);
133  static COST base_cost (WORD *this);
134 -static COST line_cost (WORD *next, int len);
135 +static COST line_cost (WORD *next, int wid);
136  static void put_paragraph (WORD *finish);
137  static void put_line (WORD *w, int indent);
138  static void put_word (WORD *w);
139 @@ -183,8 +204,11 @@
140  /* If true, don't preserve inter-word spacing (default false).  */
141  static bool uniform;
142  
143 +/* How many spaces to put after a sentence (1 or 2).  */
144 +static int sentence_space;
145 +
146  /* Prefix minus leading and trailing spaces (default "").  */
147 -static const char *prefix;
148 +static wchar_t *prefix;
149  
150  /* User-supplied maximum line width (default WIDTH).  The only output
151     lines longer than this will each comprise a single word.  */
152 @@ -192,14 +216,14 @@
153  
154  /* Values derived from the option values.  */
155  
156 -/* The length of prefix minus leading space.  */
157 -static int prefix_full_length;
158 +/* The width of prefix minus leading space.  */
159 +static int prefix_full_width;
160  
161 -/* The length of the leading space trimmed from the prefix.  */
162 +/* The width of the leading space trimmed from the prefix.  */
163  static int prefix_lead_space;
164  
165 -/* The length of prefix minus leading and trailing space.  */
166 -static int prefix_length;
167 +/* The width of prefix minus leading and trailing space.  */
168 +static int prefix_width;
169  
170  /* The preferred width of text lines, set to LEEWAY % less than max_width.  */
171  static int goal_width;
172 @@ -214,10 +238,10 @@
173  
174  /* Space for the paragraph text -- longer paragraphs are handled neatly
175     (cf. flush_paragraph()).  */
176 -static char parabuf[MAXCHARS];
177 +static wchar_t parabuf[MAXCHARS];
178  
179  /* A pointer into parabuf, indicating the first unused character position.  */
180 -static char *wptr;
181 +static wchar_t *wptr;
182  
183  /* The words of a paragraph -- longer paragraphs are handled neatly
184     (cf. flush_paragraph()).  */
185 @@ -249,16 +273,16 @@
186     prefix (next_prefix_indent).  See get_paragraph() and copy_rest().  */
187  
188  /* The last character read from the input file.  */
189 -static int next_char;
190 +static wint_t next_char;
191  
192  /* The space before the trimmed prefix (or part of it) on the next line
193     after the current paragraph.  */
194  static int next_prefix_indent;
195  
196 -/* If nonzero, the length of the last line output in the current
197 +/* If nonzero, the width of the last line output in the current
198     paragraph, used to charge for raggedness at the split point for long
199     paragraphs chosen by fmt_paragraph().  */
200 -static int last_line_length;
201 +static int last_line_width;
202  
203  void
204  usage (int status)
205 @@ -287,7 +311,8 @@
206           format string:  xgettext:no-c-format */
207        fputs (_("\
208    -t, --tagged-paragraph    indentation of first line different from second\n\
209 -  -u, --uniform-spacing     one space between words, two after sentences\n\
210 +  -u, --uniform-spacing     one space between words, two between sentences\n\
211 +  -n, --single-spaces       single spaces between sentences\n\
212    -w, --width=WIDTH         maximum line width (default of 75 columns)\n\
213    -g, --goal=WIDTH          goal width (default of 93% of width)\n\
214  "), stdout);
215 @@ -311,6 +336,7 @@
216    {"split-only", no_argument, NULL, 's'},
217    {"tagged-paragraph", no_argument, NULL, 't'},
218    {"uniform-spacing", no_argument, NULL, 'u'},
219 +  {"single-spaces", no_argument, NULL, 'n'},
220    {"width", required_argument, NULL, 'w'},
221    {"goal", required_argument, NULL, 'g'},
222    {GETOPT_HELP_OPTION_DECL},
223 @@ -335,9 +361,10 @@
224    atexit (close_stdout);
225  
226    crown = tagged = split = uniform = false;
227 +  sentence_space = 2;
228    max_width = WIDTH;
229 -  prefix = "";
230 -  prefix_length = prefix_lead_space = prefix_full_length = 0;
231 +  prefix = L"";
232 +  prefix_width = prefix_lead_space = prefix_full_width = 0;
233  
234    if (argc > 1 && argv[1][0] == '-' && ISDIGIT (argv[1][1]))
235      {
236 @@ -350,7 +377,7 @@
237        argc--;
238      }
239  
240 -  while ((optchar = getopt_long (argc, argv, "0123456789cstuw:p:g:",
241 +  while ((optchar = getopt_long (argc, argv, "0123456789cstunw:p:g:",
242                                   long_options, NULL))
243           != -1)
244      switch (optchar)
245 @@ -378,6 +405,10 @@
246          uniform = true;
247          break;
248  
249 +      case 'n':
250 +        sentence_space = 1;
251 +        break;
252 +
253        case 'w':
254          max_width_option = optarg;
255          break;
256 @@ -461,26 +492,32 @@
257  }
258  
259  /* Trim space from the front and back of the string P, yielding the prefix,
260 -   and record the lengths of the prefix and the space trimmed.  */
261 +   and record the widths of the prefix and the space trimmed.  */
262  
263  static void
264  set_prefix (char *p)
265  {
266 -  char *s;
267 +  size_t len;
268 +  wchar_t *s;
269  
270    prefix_lead_space = 0;
271 -  while (*p == ' ')
272 +  while (*p == L' ')
273      {
274        prefix_lead_space++;
275        p++;
276      }
277 -  prefix = p;
278 -  prefix_full_length = strlen (p);
279 -  s = p + prefix_full_length;
280 -  while (s > p && s[-1] == ' ')
281 -    s--;
282 -  *s = '\0';
283 -  prefix_length = s - p;
284 +  len = mbsrtowcs (NULL, (const char **) &p, 0, NULL);
285 +  prefix = xmalloc (len * sizeof (wchar_t));
286 +  mbsrtowcs (prefix, (const char **) &p, len, NULL);
287 +  for (s = prefix; *s; s++)
288 +    prefix_full_width += xwcwidth (*s);
289 +  prefix_width = prefix_full_width;
290 +  while (s > prefix && s[-1] == L' ')
291 +    {
292 +      s--;
293 +      prefix_width--;
294 +    }
295 +  *s = L'\0';
296  }
297  
298  /* read file F and send formatted output to stdout.  */
299 @@ -550,24 +587,24 @@
300  static bool
301  get_paragraph (FILE *f)
302  {
303 -  int c;
304 +  wint_t c;
305  
306 -  last_line_length = 0;
307 +  last_line_width = 0;
308    c = next_char;
309  
310    /* Scan (and copy) blank lines, and lines not introduced by the prefix.  */
311  
312 -  while (c == '\n' || c == EOF
313 +  while (c == L'\n' || c == WEOF
314           || next_prefix_indent < prefix_lead_space
315 -         || in_column < next_prefix_indent + prefix_full_length)
316 +         || in_column < next_prefix_indent + prefix_full_width)
317      {
318        c = copy_rest (f, c);
319 -      if (c == EOF)
320 +      if (c == WEOF)
321          {
322 -          next_char = EOF;
323 +          next_char = WEOF;
324            return false;
325          }
326 -      putchar ('\n');
327 +      putwchar (L'\n');
328        c = get_prefix (f);
329      }
330  
331 @@ -628,26 +665,26 @@
332     that failed to match the prefix.  In the latter, C is \n or EOF.
333     Return the character (\n or EOF) ending the line.  */
334  
335 -static int
336 -copy_rest (FILE *f, int c)
337 +static wint_t
338 +copy_rest (FILE *f, wint_t c)
339  {
340 -  const char *s;
341 +  const wchar_t *s;
342  
343    out_column = 0;
344 -  if (in_column > next_prefix_indent || (c != '\n' && c != EOF))
345 +  if (in_column > next_prefix_indent || (c != L'\n' && c != WEOF))
346      {
347        put_space (next_prefix_indent);
348        for (s = prefix; out_column != in_column && *s; out_column++)
349 -        putchar (*s++);
350 -      if (c != EOF && c != '\n')
351 +        putwchar (*s++);
352 +      if (c != WEOF && c != L'\n')
353          put_space (in_column - out_column);
354 -      if (c == EOF && in_column >= next_prefix_indent + prefix_length)
355 -        putchar ('\n');
356 +      if (c == WEOF && in_column >= next_prefix_indent + prefix_width)
357 +        putwchar (L'\n');
358      }
359 -  while (c != '\n' && c != EOF)
360 +  while (c != L'\n' && c != WEOF)
361      {
362 -      putchar (c);
363 -      c = getc (f);
364 +      putwchar (c);
365 +      c = xgetwc (f);
366      }
367    return c;
368  }
369 @@ -657,11 +694,11 @@
370     otherwise false.  */
371  
372  static bool
373 -same_para (int c)
374 +same_para (wint_t c)
375  {
376    return (next_prefix_indent == prefix_indent
377 -          && in_column >= next_prefix_indent + prefix_full_length
378 -          && c != '\n' && c != EOF);
379 +          && in_column >= next_prefix_indent + prefix_full_width
380 +          && c != L'\n' && c != WEOF);
381  }
382  
383  /* Read a line from input file F, given first non-blank character C
384 @@ -672,11 +709,11 @@
385  
386     Return the first non-blank character of the next line.  */
387  
388 -static int
389 -get_line (FILE *f, int c)
390 +static wint_t
391 +get_line (FILE *f, wint_t c)
392  {
393    int start;
394 -  char *end_of_parabuf;
395 +  wchar_t *end_of_parabuf;
396    WORD *end_of_word;
397  
398    end_of_parabuf = &parabuf[MAXCHARS];
399 @@ -688,6 +725,7 @@
400        /* Scan word.  */
401  
402        word_limit->text = wptr;
403 +      word_limit->width = 0;
404        do
405          {
406            if (wptr == end_of_parabuf)
407 @@ -696,10 +734,12 @@
408                flush_paragraph ();
409              }
410            *wptr++ = c;
411 -          c = getc (f);
412 +          word_limit->width += xwcwidth (c);
413 +          c = xgetwc (f);
414          }
415 -      while (c != EOF && !isspace (c));
416 -      in_column += word_limit->length = wptr - word_limit->text;
417 +      while (c != WEOF && !isspace (c));
418 +      word_limit->length = wptr - word_limit->text;
419 +      in_column += word_limit->width;
420        check_punctuation (word_limit);
421  
422        /* Scan inter-word space.  */
423 @@ -707,11 +747,11 @@
424        start = in_column;
425        c = get_space (f, c);
426        word_limit->space = in_column - start;
427 -      word_limit->final = (c == EOF
428 +      word_limit->final = (c == WEOF
429                             || (word_limit->period
430 -                               && (c == '\n' || word_limit->space > 1)));
431 -      if (c == '\n' || c == EOF || uniform)
432 -        word_limit->space = word_limit->final ? 2 : 1;
433 +                           && (c == L'\n' || word_limit->space > 1)));
434 +      if (c == L'\n' || c == WEOF || uniform)
435 +        word_limit->space = word_limit->final ? sentence_space : 1;
436        if (word_limit == end_of_word)
437          {
438            set_other_indent (true);
439 @@ -719,34 +759,34 @@
440          }
441        word_limit++;
442      }
443 -  while (c != '\n' && c != EOF);
444 +  while (c != L'\n' && c != WEOF);
445    return get_prefix (f);
446  }
447  
448  /* Read a prefix from input file F.  Return either first non-matching
449     character, or first non-blank character after the prefix.  */
450  
451 -static int
452 +static wint_t
453  get_prefix (FILE *f)
454  {
455 -  int c;
456 +  wint_t c;
457  
458    in_column = 0;
459 -  c = get_space (f, getc (f));
460 -  if (prefix_length == 0)
461 +  c = get_space (f, xgetwc (f));
462 +  if (prefix_width == 0)
463      next_prefix_indent = prefix_lead_space < in_column ?
464        prefix_lead_space : in_column;
465    else
466      {
467 -      const char *p;
468 +      const wchar_t *p;
469        next_prefix_indent = in_column;
470 -      for (p = prefix; *p != '\0'; p++)
471 +      for (p = prefix; *p != L'\0'; p++)
472          {
473 -          unsigned char pc = *p;
474 +          wchar_t pc = *p;
475            if (c != pc)
476              return c;
477            in_column++;
478 -          c = getc (f);
479 +          c = xgetwc (f);
480          }
481        c = get_space (f, c);
482      }
483 @@ -756,21 +796,21 @@
484  /* Read blank characters from input file F, starting with C, and keeping
485     in_column up-to-date.  Return first non-blank character.  */
486  
487 -static int
488 -get_space (FILE *f, int c)
489 +static wint_t
490 +get_space (FILE *f, wint_t c)
491  {
492    while (true)
493      {
494 -      if (c == ' ')
495 +      if (c == L' ')
496          in_column++;
497 -      else if (c == '\t')
498 +      else if (c == L'\t')
499          {
500            tabs = true;
501            in_column = (in_column / TABWIDTH + 1) * TABWIDTH;
502          }
503        else
504          return c;
505 -      c = getc (f);
506 +      c = xgetwc (f);
507      }
508  }
509  
510 @@ -779,9 +819,9 @@
511  static void
512  check_punctuation (WORD *w)
513  {
514 -  char const *start = w->text;
515 -  char const *finish = start + (w->length - 1);
516 -  unsigned char fin = *finish;
517 +  wchar_t const *start = w->text;
518 +  wchar_t const *finish = start + (w->length - 1);
519 +  wchar_t fin = *finish;
520  
521    w->paren = isopen (*start);
522    w->punct = !! ispunct (fin);
523 @@ -805,7 +845,9 @@
524  
525    if (word_limit == word)
526      {
527 -      fwrite (parabuf, sizeof *parabuf, wptr - parabuf, stdout);
528 +      wchar_t *outptr;
529 +      for (outptr = parabuf; outptr < wptr; outptr++)
530 +        putwchar (*outptr);
531        wptr = parabuf;
532        return;
533      }
534 @@ -837,7 +879,8 @@
535    /* Copy text of words down to start of parabuf -- we use memmove because
536       the source and target may overlap.  */
537  
538 -  memmove (parabuf, split_point->text, wptr - split_point->text);
539 +  memmove (parabuf, split_point->text,
540 +           (wptr - split_point->text) * sizeof (wchar_t));
541    shift = split_point->text - parabuf;
542    wptr -= shift;
543  
544 @@ -861,53 +904,53 @@
545  fmt_paragraph (void)
546  {
547    WORD *start, *w;
548 -  int len;
549 +  int wid;
550    COST wcost, best;
551 -  int saved_length;
552 +  int saved_width;
553  
554    word_limit->best_cost = 0;
555 -  saved_length = word_limit->length;
556 -  word_limit->length = max_width;      /* sentinel */
557 +  saved_width = word_limit->width;
558 +  word_limit->width = max_width;       /* sentinel */
559  
560    for (start = word_limit - 1; start >= word; start--)
561      {
562        best = MAXCOST;
563 -      len = start == word ? first_indent : other_indent;
564 +      wid = start == word ? first_indent : other_indent;
565  
566        /* At least one word, however long, in the line.  */
567  
568        w = start;
569 -      len += w->length;
570 +      wid += w->width;
571        do
572          {
573            w++;
574  
575            /* Consider breaking before w.  */
576  
577 -          wcost = line_cost (w, len) + w->best_cost;
578 -          if (start == word && last_line_length > 0)
579 -            wcost += RAGGED_COST (len - last_line_length);
580 +         wcost = line_cost (w, wid) + w->best_cost;
581 +         if (start == word && last_line_width > 0)
582 +           wcost += RAGGED_COST (wid - last_line_width);
583            if (wcost < best)
584              {
585                best = wcost;
586                start->next_break = w;
587 -              start->line_length = len;
588 +             start->line_width = wid;
589              }
590  
591 -          /* This is a kludge to keep us from computing 'len' as the
592 -             sum of the sentinel length and some non-zero number.
593 -             Since the sentinel w->length may be INT_MAX, adding
594 +         /* This is a kludge to keep us from computing 'wid' as the
595 +            sum of the sentinel width and some non-zero number.
596 +            Since the sentinel w->width may be INT_MAX, adding
597               to that would give a negative result.  */
598            if (w == word_limit)
599              break;
600  
601 -          len += (w - 1)->space + w->length;   /* w > start >= word */
602 +         wid += (w - 1)->space + w->width;     /* w > start >= word */
603          }
604 -      while (len < max_width);
605 +      while (wid < max_width);
606        start->best_cost = best + base_cost (start);
607      }
608  
609 -  word_limit->length = saved_length;
610 +  word_limit->width = saved_width;
611  }
612  
613  /* Return the constant component of the cost of breaking before the
614 @@ -932,33 +975,33 @@
615        else if ((this - 1)->punct)
616          cost -= PUNCT_BONUS;
617        else if (this > word + 1 && (this - 2)->final)
618 -        cost += WIDOW_COST ((this - 1)->length);
619 +        cost += WIDOW_COST ((this - 1)->width);
620      }
621  
622    if (this->paren)
623      cost -= PAREN_BONUS;
624    else if (this->final)
625 -    cost += ORPHAN_COST (this->length);
626 +    cost += ORPHAN_COST (this->width);
627  
628    return cost;
629  }
630  
631  /* Return the component of the cost of breaking before word NEXT that
632 -   depends on LEN, the length of the line beginning there.  */
633 +   depends on WID, the width of the line beginning there.  */
634  
635  static COST
636 -line_cost (WORD *next, int len)
637 +line_cost (WORD *next, int wid)
638  {
639    int n;
640    COST cost;
641  
642    if (next == word_limit)
643      return 0;
644 -  n = goal_width - len;
645 +  n = goal_width - wid;
646    cost = SHORT_COST (n);
647    if (next->next_break != word_limit)
648      {
649 -      n = len - next->line_length;
650 +      n = wid - next->line_width;
651        cost += RAGGED_COST (n);
652      }
653    return cost;
654 @@ -987,8 +1030,8 @@
655  
656    out_column = 0;
657    put_space (prefix_indent);
658 -  fputs (prefix, stdout);
659 -  out_column += prefix_length;
660 +  fputws (prefix, stdout);
661 +  out_column += prefix_width;
662    put_space (indent - out_column);
663  
664    endline = w->next_break - 1;
665 @@ -998,8 +1041,8 @@
666        put_space (w->space);
667      }
668    put_word (w);
669 -  last_line_length = out_column;
670 -  putchar ('\n');
671 +  last_line_width = out_column;
672 +  putwchar (L'\n');
673  }
674  
675  /* Output to stdout the word W.  */
676 @@ -1007,13 +1050,13 @@
677  static void
678  put_word (WORD *w)
679  {
680 -  const char *s;
681 +  const wchar_t *s;
682    int n;
683  
684    s = w->text;
685    for (n = w->length; n != 0; n--)
686 -    putchar (*s++);
687 -  out_column += w->length;
688 +    putwchar (*s++);
689 +  out_column += w->width;
690  }
691  
692  /* Output to stdout SPACE spaces, or equivalent tabs.  */
693 @@ -1030,13 +1073,13 @@
694        if (out_column + 1 < tab_target)
695          while (out_column < tab_target)
696            {
697 -            putchar ('\t');
698 +           putwchar (L'\t');
699              out_column = (out_column / TABWIDTH + 1) * TABWIDTH;
700            }
701      }
702    while (out_column < space_target)
703      {
704 -      putchar (' ');
705 +      putwchar (L' ');
706        out_column++;
707      }
708  }