|
1 /* |
|
2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Line breaker class customized to meet Series 60 specifications. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "AknLineBreaker.h" |
|
21 #include "aknenv.h" |
|
22 #include <linebreak.h> |
|
23 #include <featmgr.h> //FeatureManager |
|
24 |
|
25 // CONSTANTS |
|
26 |
|
27 const TUint KOpFlag = 1 << MLineBreaker::EOpLineBreakClass; |
|
28 const TUint KClFlag = 1 << MLineBreaker::EClLineBreakClass; |
|
29 // const TUint KQuFlag = 1 << MLineBreaker::EQuLineBreakClass; |
|
30 // const TUint KGlFlag = 1 << MLineBreaker::EGlLineBreakClass; |
|
31 const TUint KNsFlag = 1 << MLineBreaker::ENsLineBreakClass; |
|
32 const TUint KExFlag = 1 << MLineBreaker::EExLineBreakClass; |
|
33 const TUint KSyFlag = 1 << MLineBreaker::ESyLineBreakClass; |
|
34 const TUint KIsFlag = 1 << MLineBreaker::EIsLineBreakClass; |
|
35 const TUint KPrFlag = 1 << MLineBreaker::EPrLineBreakClass; |
|
36 const TUint KPoFlag = 1 << MLineBreaker::EPoLineBreakClass; |
|
37 const TUint KNuFlag = 1 << MLineBreaker::ENuLineBreakClass; |
|
38 const TUint KAlFlag = 1 << MLineBreaker::EAlLineBreakClass; |
|
39 const TUint KIdFlag = 1 << MLineBreaker::EIdLineBreakClass; |
|
40 const TUint KInFlag = 1 << MLineBreaker::EInLineBreakClass; |
|
41 // const TUint KHyFlag = 1 << MLineBreaker::EHyLineBreakClass; |
|
42 // const TUint KBaFlag = 1 << MLineBreaker::EBaLineBreakClass; |
|
43 const TUint KBbFlag = 1 << MLineBreaker::EBbLineBreakClass; |
|
44 const TUint KB2Flag = 1 << MLineBreaker::EB2LineBreakClass; |
|
45 const TUint KZwFlag = 1 << MLineBreaker::EZwLineBreakClass; |
|
46 const TUint KCmFlag = 1 << MLineBreaker::ECmLineBreakClass; |
|
47 // const TUint KBkFlag = 1 << MLineBreaker::EBkLineBreakClass; |
|
48 // const TUint KCrFlag = 1 << MLineBreaker::ECrLineBreakClass; |
|
49 // const TUint KLfFlag = 1 << MLineBreaker::ELfLineBreakClass; |
|
50 // const TUint KSgFlag = 1 << MLineBreaker::ESgLineBreakClass; |
|
51 // const TUint KCbFlag = 1 << MLineBreaker::ECbLineBreakClass; |
|
52 // const TUint KSpFlag = 1 << MLineBreaker::ESpLineBreakClass; |
|
53 // const TUint KSaFlag = 1 << MLineBreaker::ESaLineBreakClass; |
|
54 const TUint KAiFlag = 1 << MLineBreaker::EAiLineBreakClass; |
|
55 // const TUint KXxFlag = 1 << MLineBreaker::EXxLineBreakClass; |
|
56 |
|
57 const TUint KAllBreaks = 0xFFFFFFFF; |
|
58 |
|
59 const TUint KUsualForbidden = KClFlag | KExFlag | KSyFlag | KIsFlag | KZwFlag; |
|
60 |
|
61 const TUint KUsualAllowed = |
|
62 KOpFlag | KPrFlag | KPoFlag | KNuFlag | KAlFlag | KIdFlag | KInFlag | |
|
63 KBbFlag | KB2Flag | KAiFlag; |
|
64 |
|
65 struct TLineBreakRule |
|
66 { |
|
67 // Classes that breaks are illegal before, even after spaces. |
|
68 TUint iForbid; |
|
69 // Classes that breaks are legal before, even without spaces. |
|
70 TUint iAllow; |
|
71 }; |
|
72 |
|
73 // A table of break rules, indexed by the class of the character before the |
|
74 // possible break. |
|
75 static const TLineBreakRule |
|
76 TheLineBreakRuleTable[MLineBreaker::ELineBreakClasses] = |
|
77 { |
|
78 { KAllBreaks - KCmFlag,0 }, // Op |
|
79 { KUsualForbidden | KNsFlag,KUsualAllowed - KPoFlag }, // Cl |
|
80 { KUsualForbidden | KOpFlag,0 }, // Qu |
|
81 { KUsualForbidden, 0 }, // Gl |
|
82 { KUsualForbidden, KUsualAllowed }, // Ns |
|
83 { KUsualForbidden, KUsualAllowed }, // Ex |
|
84 { KUsualForbidden, KUsualAllowed - KNuFlag }, // Sy |
|
85 { KUsualForbidden, KUsualAllowed - KNuFlag }, // Is |
|
86 { KUsualForbidden, KPrFlag | KPoFlag | KInFlag | KBbFlag | KB2Flag }, // Pr |
|
87 { KUsualForbidden, KUsualAllowed }, // Po |
|
88 { KUsualForbidden, KOpFlag | KPrFlag | KIdFlag | KBbFlag | KB2Flag }, // Nu |
|
89 { KUsualForbidden, KOpFlag | KPrFlag | KPoFlag | KIdFlag | KBbFlag | KB2Flag }, // Al |
|
90 { KUsualForbidden, KUsualAllowed - KPoFlag - KInFlag }, // Id |
|
91 { KUsualForbidden, KUsualAllowed - KInFlag }, // In |
|
92 { KUsualForbidden, KUsualAllowed }, // Hy |
|
93 { KUsualForbidden, KUsualAllowed }, // Ba |
|
94 { KUsualForbidden, 0 }, // Bb |
|
95 { KUsualForbidden | KB2Flag, KUsualAllowed }, // B2 |
|
96 { KZwFlag, KAllBreaks - KZwFlag - KCmFlag}, // Zw |
|
97 { KUsualForbidden, KOpFlag | KPrFlag | KPoFlag | KIdFlag | KBbFlag | KB2Flag }, // Cm |
|
98 { 0, 0, }, // Bk |
|
99 { 0, 0, }, // Cr |
|
100 { 0, 0, }, // Lf |
|
101 { 0, 0, }, // Sg |
|
102 { 0, 0, }, // Cb |
|
103 { KAllBreaks, 0, }, // Sp |
|
104 { 0, 0, }, // Sa |
|
105 // the next line is different from GDI's table! |
|
106 { KUsualForbidden, KOpFlag | KPrFlag | KPoFlag | KIdFlag | KBbFlag | KB2Flag }, // Ai |
|
107 { 0, 0, } // Xx |
|
108 }; |
|
109 |
|
110 // These are from editing UI spec. |
|
111 // 0xFFxx values are corresponding full width forms used in Chinese translations |
|
112 |
|
113 _LIT( KWrappingBeforeOrAfterChars, |
|
114 "#_@&/\\=\xFF03\xFF3F\xFF20\xFF06\xFF0F\xFF3C\xFF1D" ); |
|
115 |
|
116 const TText KPrivateUseAreaStart = 0xE000; |
|
117 const TText KPrivateUseAreaEnd = 0xF900; |
|
118 |
|
119 // ============================ MEMBER FUNCTIONS =============================== |
|
120 |
|
121 // ----------------------------------------------------------------------------- |
|
122 // TAknLineBreaker::LineBreakClass() |
|
123 // ----------------------------------------------------------------------------- |
|
124 // |
|
125 TUint TAknLineBreaker::LineBreakClass( |
|
126 TUint aCode, TUint& aRangeStart, TUint& aRangeEnd ) const |
|
127 { |
|
128 aRangeStart = aCode; |
|
129 aRangeEnd = aCode + 1; |
|
130 |
|
131 // Need to fix those areas of TheLineBreakRangeTable (see linebreak.cpp) |
|
132 // here, where our special wrapping characters reside. |
|
133 |
|
134 TUint lineclass; |
|
135 if (IsSpecialVariantChar(aCode, aRangeStart, aRangeEnd, lineclass)) |
|
136 { |
|
137 return lineclass; |
|
138 } |
|
139 |
|
140 if ( aCode == 0x003C || aCode == 0x003E || aCode == 0x005E ) |
|
141 { |
|
142 return EAlLineBreakClass; |
|
143 } |
|
144 |
|
145 if ( aCode >= 0x0041 && aCode <= 0x005A ) |
|
146 { |
|
147 aRangeStart = 0x0041; |
|
148 aRangeEnd = 0x005B; |
|
149 return EAlLineBreakClass; |
|
150 } |
|
151 |
|
152 if ( aCode >= 0x0060 && aCode <= 0x007A ) |
|
153 { |
|
154 aRangeStart = 0x0060; |
|
155 aRangeEnd = 0x007B; |
|
156 return EAlLineBreakClass; |
|
157 } |
|
158 |
|
159 // Regions, where our full with form special wrapping characters reside, |
|
160 // already return EIdLineBreakClass in TheLineBreakRangeTable, so no |
|
161 // need to fix them. |
|
162 |
|
163 if ( KWrappingBeforeOrAfterChars().Locate( aCode ) != KErrNotFound ) |
|
164 { |
|
165 // this allows break before and after |
|
166 return EIdLineBreakClass; |
|
167 } |
|
168 if ( aCode >= KPrivateUseAreaStart && aCode < KPrivateUseAreaEnd ) |
|
169 { |
|
170 aRangeStart = KPrivateUseAreaStart; |
|
171 aRangeEnd = KPrivateUseAreaEnd; |
|
172 // this allows break before and after |
|
173 return EIdLineBreakClass; |
|
174 } |
|
175 else |
|
176 { |
|
177 return MLineBreaker::LineBreakClass( aCode, aRangeStart, aRangeEnd ); |
|
178 } |
|
179 } |
|
180 |
|
181 // ----------------------------------------------------------------------------- |
|
182 // TAknLineBreaker::LineBreakPossible() |
|
183 // This function is identical with the base implementation in LineBreak.dll. |
|
184 // Only the used table TheLineBreakRuleTable is different. |
|
185 // ----------------------------------------------------------------------------- |
|
186 // |
|
187 TBool TAknLineBreaker::LineBreakPossible( |
|
188 TUint aPrevClass, TUint aNextClass, TBool aHaveSpaces ) const |
|
189 { |
|
190 if (aPrevClass >= ELineBreakClasses || aNextClass >= ELineBreakClasses) |
|
191 return FALSE; |
|
192 const TLineBreakRule& rule = TheLineBreakRuleTable[aPrevClass]; |
|
193 TUint flag = 1 << aNextClass; |
|
194 if (rule.iForbid & flag) |
|
195 return FALSE; |
|
196 return aHaveSpaces || (rule.iAllow & flag); |
|
197 } |
|
198 |
|
199 |
|
200 struct TLineBreakRangeForSpecialVariant |
|
201 { |
|
202 TUint iStart; |
|
203 TUint iEnd; |
|
204 TUint iClass; |
|
205 }; |
|
206 |
|
207 // ----------------------------------------------------------------------------- |
|
208 // The following definitions are for Japane variant |
|
209 // ----------------------------------------------------------------------------- |
|
210 // |
|
211 static const TLineBreakRangeForSpecialVariant TheLineBreakRangeTableForJapanese[] = |
|
212 { |
|
213 { 0x301c, 0x301d, MLineBreaker::EIdLineBreakClass }, //wave dash |
|
214 { 0x30fc, 0x30fd, MLineBreaker::ENsLineBreakClass }, //katakana-hiragana prolonged sound mark |
|
215 { 0x30fe, 0x30ff, MLineBreaker::ENsLineBreakClass }, //katakana voiced iteration mark |
|
216 { 0xff66, 0xff67, MLineBreaker::EIdLineBreakClass }, //halfwidth katakana letter wo |
|
217 { 0xff71, 0xff9e, MLineBreaker::EIdLineBreakClass }, //halfwidth katakana letter a - nn |
|
218 }; |
|
219 |
|
220 // ----------------------------------------------------------------------------- |
|
221 // TAknLineBreaker::IsSpecialVariantChar() |
|
222 // Converts Unicode character into line breaking class for special variant. |
|
223 // ----------------------------------------------------------------------------- |
|
224 // |
|
225 EXPORT_C TBool TAknLineBreaker::IsSpecialVariantChar(TUint aCode, TUint& aRangeStart,TUint& aRangeEnd, TUint& aClass) |
|
226 { |
|
227 TBool ret = EFalse; |
|
228 |
|
229 // return if feature language is not Japanese |
|
230 CAknEnv* env = CAknEnv::Static(); |
|
231 if (env) |
|
232 { |
|
233 if (!env->IsFeatureLanguage(KFeatureIdJapanese)) |
|
234 { |
|
235 return ret; |
|
236 } |
|
237 } |
|
238 else |
|
239 { |
|
240 return ret; |
|
241 } |
|
242 |
|
243 // Now search the table. |
|
244 const TLineBreakRangeForSpecialVariant* base = TheLineBreakRangeTableForJapanese; |
|
245 const TLineBreakRangeForSpecialVariant* end = base + |
|
246 (sizeof(TheLineBreakRangeTableForJapanese) |
|
247 / sizeof(TheLineBreakRangeTableForJapanese[0])); |
|
248 while (base < end) |
|
249 { |
|
250 TInt n = end - base; |
|
251 const TLineBreakRangeForSpecialVariant* r = &base[n / 2]; |
|
252 if (r->iStart > aCode) |
|
253 { |
|
254 end = r; |
|
255 } |
|
256 else if (r->iEnd <= aCode) |
|
257 { |
|
258 base = r + 1; |
|
259 } |
|
260 else |
|
261 { |
|
262 aRangeStart = r->iStart; |
|
263 aRangeEnd = r->iEnd; |
|
264 aClass = r->iClass; |
|
265 ret = ETrue; |
|
266 break; |
|
267 } |
|
268 } |
|
269 return ret; |
|
270 } |
|
271 |
|
272 // End of File |