summaryrefslogtreecommitdiff
path: root/lib/uniwbrk/u-wordbreaks.h
blob: 5ef4e8c1a926263e2265ed6ce0e7207899ca97c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Word breaks in UTF-8/UTF-16/UTF-32 strings.
   Copyright (C) 2009 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2009.

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published
   by the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

void
FUNC (const UNIT *s, size_t n, char *p)
{
  if (n > 0)
    {
      const UNIT *s_end = s + n;

      /* Word break property of the last character.
	 -1 at the very beginning of the string.  */
      int last_char_prop = -1;

      /* Format and Extend characters are ignored; this means, the mostly used
	 unit is the complex character (= character with subsequent ignored
	 characters).
	 Word break property of the last complex character.
	 -1 at the very beginning of the string.  */
      int last_compchar_prop = -1;
      char *last_compchar_ptr = NULL;

      /* For recognizing rules involving 3 complex characters:
	 Word break property of the second-to-last complex character.
	 -1 at the very beginning of the string.  */
      int secondlast_compchar_prop = -1;

      /* Don't break inside multibyte characters.  */
      memset (p, 0, n);

      while (s < s_end)
	{
	  ucs4_t uc;
	  int count = U_MBTOUC_UNSAFE (&uc, s, s_end - s);
	  int prop = uc_wordbreak_property (uc);

	  /* No break at the start of the string.  */
	  if (last_char_prop >= 0)
	    {
	      /* No break between CR and LF.  */
	      if (last_char_prop == WBP_CR && prop == WBP_LF)
		/* *p = 0 */;
	      /* Break before and after newlines.  */
	      else if (last_char_prop >= WBP_NEWLINE
		       /* same as:
			  last_char_prop == WBP_CR
			  || last_char_prop == WBP_LF
			  || last_char_prop == WBP_NEWLINE */
		       || prop >= WBP_NEWLINE
			  /* same as:
			     prop == WBP_CR
			     || prop == WBP_LF
			     || prop == WBP_NEWLINE */)
		*p = 1;
	      /* Ignore Format and Extend characters.  */
	      else if (!(prop == WBP_EXTEND || prop == WBP_FORMAT))
		{
		  /* No break in these situations (see UAX #29):

		      secondlast          last             current

		       ALetter   (MidLetter | MidNumLet) × ALetter      (WB7)
		       ALetter × (MidLetter | MidNumLet)   ALetter      (WB6)
		       Numeric   (MidNum | MidNumLet)    × Numeric      (WB11)
		       Numeric × (MidNum | MidNumLet)      Numeric      (WB12)
						 ALetter × ALetter      (WB5)
						 ALetter × Numeric      (WB9)
						 Numeric × ALetter      (WB10)
						 Numeric × Numeric      (WB8)
						Katakana × Katakana     (WB13)
			  (ALetter | Numeric | Katakana) × ExtendNumLet (WB13a)
					    ExtendNumLet × ExtendNumLet (WB13a)
			 ExtendNumLet × (ALetter | Numeric | Katakana)  (WB13b)
		   */
		  /* No break across certain punctuation.  Also, disable word
		     breaks that were recognized earlier (due to lookahead of
		     only one complex character).  */
		  if ((prop == WBP_ALETTER
		       && (last_compchar_prop == WBP_MIDLETTER
			   || last_compchar_prop == WBP_MIDNUMLET)
		       && secondlast_compchar_prop == WBP_ALETTER)
		      || (prop == WBP_NUMERIC
			  && (last_compchar_prop == WBP_MIDNUM
			      || last_compchar_prop == WBP_MIDNUMLET)
			  && secondlast_compchar_prop == WBP_NUMERIC))
		    {
		      *last_compchar_ptr = 0;
		      /* *p = 0; */
		    }
		  else
		    {
		      /* Perform a single table lookup.  */
		      if (uniwbrk_table[last_compchar_prop][prop])
			*p = 1;
		      /* else *p = 0; */
		    }
		}
	    }

	  last_char_prop = prop;
	  /* Ignore Format and Extend characters, except at the start of the string.  */
	  if (last_compchar_prop < 0 || !(prop == WBP_EXTEND || prop == WBP_FORMAT))
	    {
	      secondlast_compchar_prop = last_compchar_prop;
	      last_compchar_prop = prop;
	      last_compchar_ptr = p;
	    }

	  s += count;
	  p += count;
	}
    }
}