findprog-in: Relicense under LGPLv2+.
[gnulib.git] / lib / unilbrk / u16-width-linebreaks.c
blob66ab1ebb5851b187d49ca4e3fa0aeb9f77cad136
1 /* Line breaking of UTF-16 strings.
2 Copyright (C) 2001-2003, 2006-2020 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2001.
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.
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.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 #include <config.h>
20 /* Specification. */
21 #include "unilbrk.h"
23 #include "unistr.h"
24 #include "uniwidth.h"
26 int
27 u16_width_linebreaks (const uint16_t *s, size_t n,
28 int width, int start_column, int at_end_columns,
29 const char *o, const char *encoding,
30 char *p)
32 const uint16_t *s_end;
33 char *last_p;
34 int last_column;
35 int piece_width;
37 u16_possible_linebreaks (s, n, encoding, p);
39 s_end = s + n;
40 last_p = NULL;
41 last_column = start_column;
42 piece_width = 0;
43 while (s < s_end)
45 ucs4_t uc;
46 int count = u16_mbtouc_unsafe (&uc, s, s_end - s);
48 /* Respect the override. */
49 if (o != NULL && *o != UC_BREAK_UNDEFINED)
50 *p = *o;
52 if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY)
54 /* An atomic piece of text ends here. */
55 if (last_p != NULL && last_column + piece_width > width)
57 /* Insert a line break. */
58 *last_p = UC_BREAK_POSSIBLE;
59 last_column = 0;
63 if (*p == UC_BREAK_MANDATORY)
65 /* uc is a line break character. */
66 /* Start a new piece at column 0. */
67 last_p = NULL;
68 last_column = 0;
69 piece_width = 0;
71 else
73 /* uc is not a line break character. */
74 int w;
76 if (*p == UC_BREAK_POSSIBLE)
78 /* Start a new piece. */
79 last_p = p;
80 last_column += piece_width;
81 piece_width = 0;
82 /* No line break for the moment, may be turned into
83 UC_BREAK_POSSIBLE later, via last_p. */
86 *p = UC_BREAK_PROHIBITED;
88 w = uc_width (uc, encoding);
89 if (w >= 0) /* ignore control characters in the string */
90 piece_width += w;
93 s += count;
94 p += count;
95 if (o != NULL)
96 o += count;
99 /* The last atomic piece of text ends here. */
100 if (last_p != NULL && last_column + piece_width + at_end_columns > width)
102 /* Insert a line break. */
103 *last_p = UC_BREAK_POSSIBLE;
104 last_column = 0;
107 return last_column + piece_width;