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