1 /* Line breaking of UTF-8 strings.
2 Copyright (C) 2001-2003, 2006-2008 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 <http://www.gnu.org/licenses/>. */
26 #include "unilbrk/tables.h"
27 #include "uniwidth/cjk.h"
31 u8_possible_linebreaks (const uint8_t *s, size_t n, const char *encoding, char *p)
33 int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
34 const uint8_t *s_end = s + n;
35 int last_prop = LBP_BK; /* line break property of last non-space character */
36 char *seen_space = NULL; /* Was a space seen after the last non-space character? */
37 char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
39 /* Don't break inside multibyte characters. */
40 memset (p, UC_BREAK_PROHIBITED, n);
45 int count = u8_mbtouc_unsafe (&uc, s, s_end - s);
46 int prop = unilbrkprop_lookup (uc);
50 /* Mandatory break. */
51 *p = UC_BREAK_MANDATORY;
60 /* Resolve property values whose behaviour is not fixed. */
64 /* Resolve ambiguous. */
65 prop = LBP_AI_REPLACEMENT;
68 /* This is arbitrary. */
72 /* We don't handle complex scripts yet.
73 Treat LBP_SA like LBP_XX. */
75 /* This is arbitrary. */
80 /* Deal with combining characters. */
84 /* Don't break just before a combining character. */
85 *p = UC_BREAK_PROHIBITED;
86 /* A combining character turns a preceding space into LBP_AL. */
87 if (seen_space != NULL)
90 seen_space = seen_space2;
92 goto lookup_via_table;
95 else if (prop == LBP_SP)
97 /* Don't break just before a space. */
98 *p = UC_BREAK_PROHIBITED;
99 seen_space2 = seen_space;
105 /* prop must be usable as an index for table 7.3 of UTR #14. */
106 if (!(prop >= 1 && prop <= sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
109 if (last_prop == LBP_BK)
111 /* Don't break at the beginning of a line. */
112 *q = UC_BREAK_PROHIBITED;
116 switch (unilbrk_table [last_prop-1] [prop-1])
119 *q = UC_BREAK_POSSIBLE;
122 *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
125 *q = UC_BREAK_PROHIBITED;
148 /* Read the contents of an input stream, and return it, terminated with a NUL
151 read_file (FILE *stream)
159 while (! feof (stream))
161 if (size + BUFSIZE > alloc)
163 alloc = alloc + alloc / 2;
164 if (alloc < size + BUFSIZE)
165 alloc = size + BUFSIZE;
166 buf = realloc (buf, alloc);
169 fprintf (stderr, "out of memory\n");
173 count = fread (buf + size, 1, BUFSIZE, stream);
185 buf = realloc (buf, size + 1);
188 fprintf (stderr, "out of memory\n");
197 main (int argc, char * argv[])
201 /* Display all the break opportunities in the input string. */
202 char *input = read_file (stdin);
203 int length = strlen (input);
204 char *breaks = malloc (length);
207 u8_possible_linebreaks ((uint8_t *) input, length, "UTF-8", breaks);
209 for (i = 0; i < length; i++)
213 case UC_BREAK_POSSIBLE:
214 /* U+2027 in UTF-8 encoding */
215 putc (0xe2, stdout); putc (0x80, stdout); putc (0xa7, stdout);
217 case UC_BREAK_MANDATORY:
218 /* U+21B2 (or U+21B5) in UTF-8 encoding */
219 putc (0xe2, stdout); putc (0x86, stdout); putc (0xb2, stdout);
221 case UC_BREAK_PROHIBITED:
226 putc (input[i], stdout);