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