1 /*
2 * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22 #include "break_lines.h"
23
24 #include "CharacterNames.h"
25 #include "TextBreakIterator.h"
26
27 #if PLATFORM(MAC)
28 #include <CoreServices/CoreServices.h>
29 #endif
30
31 namespace WebCore {
32
isBreakableSpace(UChar ch,bool treatNoBreakSpaceAsBreak)33 static inline bool isBreakableSpace(UChar ch, bool treatNoBreakSpaceAsBreak)
34 {
35 switch (ch) {
36 case ' ':
37 case '\n':
38 case '\t':
39 return true;
40 case noBreakSpace:
41 return treatNoBreakSpaceAsBreak;
42 default:
43 return false;
44 }
45 }
46
shouldBreakAfter(UChar ch)47 static inline bool shouldBreakAfter(UChar ch)
48 {
49 // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks.
50 // FIXME: it appears that IE behavior is more complex, see <http://bugs.webkit.org/show_bug.cgi?id=17475>.
51 switch (ch) {
52 case '-':
53 case '?':
54 #ifdef ANDROID_LAYOUT
55 // as '/' is used in uri which is always long, we would like to break it
56 case '/':
57 #endif
58 case softHyphen:
59 // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0
60 // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>.
61 // We may want to remove or conditionalize this workaround at some point.
62 case ideographicComma:
63 case ideographicFullStop:
64 return true;
65 default:
66 return false;
67 }
68 }
69
needsLineBreakIterator(UChar ch)70 static inline bool needsLineBreakIterator(UChar ch)
71 {
72 return ch > 0x7F && ch != noBreakSpace;
73 }
74
75 #if PLATFORM(MAC) && defined(BUILDING_ON_TIGER)
lineBreakLocator()76 static inline TextBreakLocatorRef lineBreakLocator()
77 {
78 TextBreakLocatorRef locator = 0;
79 UCCreateTextBreakLocator(0, 0, kUCTextBreakLineMask, &locator);
80 return locator;
81 }
82 #endif
83
nextBreakablePosition(const UChar * str,int pos,int len,bool treatNoBreakSpaceAsBreak)84 int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakSpaceAsBreak)
85 {
86 #if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
87 TextBreakIterator* breakIterator = 0;
88 #endif
89 int nextBreak = -1;
90
91 UChar lastCh = pos > 0 ? str[pos - 1] : 0;
92 for (int i = pos; i < len; i++) {
93 UChar ch = str[i];
94
95 if (isBreakableSpace(ch, treatNoBreakSpaceAsBreak) || shouldBreakAfter(lastCh))
96 return i;
97
98 if (needsLineBreakIterator(ch) || needsLineBreakIterator(lastCh)) {
99 if (nextBreak < i && i) {
100 #if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
101 if (!breakIterator)
102 breakIterator = lineBreakIterator(str, len);
103 if (breakIterator)
104 nextBreak = textBreakFollowing(breakIterator, i - 1);
105 #else
106 static TextBreakLocatorRef breakLocator = lineBreakLocator();
107 if (breakLocator) {
108 UniCharArrayOffset nextUCBreak;
109 if (UCFindTextBreak(breakLocator, kUCTextBreakLineMask, 0, str, len, i, &nextUCBreak) == 0)
110 nextBreak = nextUCBreak;
111 }
112 #endif
113 }
114 if (i == nextBreak && !isBreakableSpace(lastCh, treatNoBreakSpaceAsBreak))
115 return i;
116 }
117
118 lastCh = ch;
119 }
120
121 return len;
122 }
123
124 } // namespace WebCore
125