maint: update copyright
[gnulib.git] / lib / unilbrk / u32-width-linebreaks.c
1 /* Line breaking of UTF-32 strings.
2    Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2001.
4
5    This program is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Lesser General Public License as published
7    by the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 /* Specification.  */
21 #include "unilbrk.h"
22
23 #include "uniwidth.h"
24
25 int
26 u32_width_linebreaks (const uint32_t *s, size_t n,
27                       int width, int start_column, int at_end_columns,
28                       const char *o, const char *encoding,
29                       char *p)
30 {
31   const uint32_t *s_end;
32   char *last_p;
33   int last_column;
34   int piece_width;
35
36   u32_possible_linebreaks (s, n, encoding, p);
37
38   s_end = s + n;
39   last_p = NULL;
40   last_column = start_column;
41   piece_width = 0;
42   while (s < s_end)
43     {
44       ucs4_t uc = *s;
45
46       /* Respect the override.  */
47       if (o != NULL && *o != UC_BREAK_UNDEFINED)
48         *p = *o;
49
50       if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY)
51         {
52           /* An atomic piece of text ends here.  */
53           if (last_p != NULL && last_column + piece_width > width)
54             {
55               /* Insert a line break.  */
56               *last_p = UC_BREAK_POSSIBLE;
57               last_column = 0;
58             }
59         }
60
61       if (*p == UC_BREAK_MANDATORY)
62         {
63           /* uc is a line break character.  */
64           /* Start a new piece at column 0.  */
65           last_p = NULL;
66           last_column = 0;
67           piece_width = 0;
68         }
69       else
70         {
71           /* uc is not a line break character.  */
72           int w;
73
74           if (*p == UC_BREAK_POSSIBLE)
75             {
76               /* Start a new piece.  */
77               last_p = p;
78               last_column += piece_width;
79               piece_width = 0;
80               /* No line break for the moment, may be turned into
81                  UC_BREAK_POSSIBLE later, via last_p. */
82             }
83
84           *p = UC_BREAK_PROHIBITED;
85
86           w = uc_width (uc, encoding);
87           if (w >= 0) /* ignore control characters in the string */
88             piece_width += w;
89         }
90
91       s++;
92       p++;
93       if (o != NULL)
94         o++;
95     }
96
97   /* The last atomic piece of text ends here.  */
98   if (last_p != NULL && last_column + piece_width + at_end_columns > width)
99     {
100       /* Insert a line break.  */
101       *last_p = UC_BREAK_POSSIBLE;
102       last_column = 0;
103     }
104
105   return last_column + piece_width;
106 }