2 * Implementation of Indic Syllables for the Uniscribe Script Processor
4 * Copyright 2011 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
35 #include "usp10_internal.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
39 static void debug_output_string(LPCWSTR str, int cChar, lexical_function f)
42 if (TRACE_ON(uniscribe))
44 for (i = 0; i < cChar; i++)
48 case lex_Consonant: TRACE("C"); break;
49 case lex_Ra: TRACE("Ra"); break;
50 case lex_Vowel: TRACE("V"); break;
51 case lex_Nukta: TRACE("N"); break;
52 case lex_Halant: TRACE("H"); break;
53 case lex_ZWNJ: TRACE("Zwnj"); break;
54 case lex_ZWJ: TRACE("Zwj"); break;
55 case lex_Matra_post: TRACE("Mp");break;
56 case lex_Matra_above: TRACE("Ma");break;
57 case lex_Matra_below: TRACE("Mb");break;
58 case lex_Matra_pre: TRACE("Mm");break;
59 case lex_Modifier: TRACE("Sm"); break;
60 case lex_Vedic: TRACE("Vd"); break;
61 case lex_Anudatta: TRACE("A"); break;
62 case lex_Composed_Vowel: TRACE("t"); break;
71 static inline BOOL is_consonant( int type )
73 return (type == lex_Ra || type == lex_Consonant);
76 static inline BOOL is_matra( int type )
78 return (type == lex_Matra_above || type == lex_Matra_below ||
79 type == lex_Matra_pre || type == lex_Matra_post);
82 static inline BOOL is_joiner( int type )
84 return (type == lex_ZWJ || type == lex_ZWNJ);
87 static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next,
90 if (!is_consonant( lex(input[next]) )) return -1;
92 if ((next < cChar) && lex(input[next]) == lex_Nukta)
94 if (lex(input[next])==lex_Halant)
97 if((next < cChar) && is_joiner( lex(input[next]) ))
99 if ((next < cChar) && is_consonant( lex(input[next]) ))
102 else if (is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant)
105 if ((next < cChar) && is_consonant( lex(input[next]) ))
111 static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start,
112 INT *main, INT next, lexical_function lex)
118 check = consonant_header(input,cChar,start,next,lex);
124 } while (check != -1);
125 if (headers || is_consonant( lex(input[next]) ))
132 if ((next < cChar) && lex(input[next]) == lex_Nukta)
134 if ((next < cChar) && lex(input[next]) == lex_Anudatta)
137 if ((next < cChar) && lex(input[next]) == lex_Halant)
140 if((next < cChar) && is_joiner( lex(input[next]) ))
143 else if (next < cChar)
145 while((next < cChar) && is_matra( lex(input[next]) ))
147 if ((next < cChar) && lex(input[next]) == lex_Nukta)
149 if ((next < cChar) && lex(input[next]) == lex_Halant)
152 if ((next < cChar) && lex(input[next]) == lex_Modifier)
154 if ((next < cChar) && lex(input[next]) == lex_Vedic)
159 static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start,
160 INT next, lexical_function lex)
162 if ((next < cChar) && lex(input[next]) == lex_Nukta)
164 if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant && is_consonant( lex(input[next+2]) ))
166 else if ((next < cChar) && lex(input[next])==lex_Halant && is_consonant( lex(input[next+1]) ))
168 else if ((next < cChar) && lex(input[next])==lex_ZWJ && is_consonant( lex(input[next+1]) ))
171 if (is_matra( lex(input[next]) ))
173 while((next < cChar) && is_matra( lex(input[next]) ))
175 if ((next < cChar) && lex(input[next]) == lex_Nukta)
177 if ((next < cChar) && lex(input[next]) == lex_Halant)
181 if ((next < cChar) && lex(input[next]) == lex_Modifier)
183 if ((next < cChar) && lex(input[next]) == lex_Vedic)
188 static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT* main, INT next, lexical_function lex )
190 if (lex(input[next])==lex_Vowel)
193 return parse_vowel_syllable(input, cChar, start, next+1, lex);
195 else if ((cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_Vowel)
198 return parse_vowel_syllable(input, cChar, start, next+3, lex);
201 else if (start == next && lex(input[next])==lex_NBSP)
204 return parse_vowel_syllable(input, cChar, start, next+1, lex);
206 else if (start == next && (cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_NBSP)
209 return parse_vowel_syllable(input, cChar, start, next+3, lex);
212 return parse_consonant_syllable(input, cChar, start, main, next, lex);
215 void Indic_ReorderCharacters( LPWSTR input, int cChar, lexical_function lex, reorder_function reorder_f)
221 if (!lex || ! reorder_f)
223 ERR("Failure to have required functions\n");
227 debug_output_string(input, cChar, lex);
230 while((next < cChar) && lex(input[next]) == lex_Generic)
233 next = Indic_process_next_syllable(input, cChar, 0, ¢er, index, lex);
236 reorder_f(input, index, center, next-1, lex);
239 else if (index < cChar)
242 TRACE("Processing failed at %i\n",index);
243 for (i = index; i < cChar; i++)
244 if (lex(input[i])==lex_Generic)
246 TRACE("Restart processing at %i\n",i);
253 TRACE("Processed %i of %i characters\n",index,cChar);
256 int Indic_FindBaseConsonant(LPWSTR input, INT start, INT main, INT end, lexical_function lex)
259 /* try to find a base consonant */
260 if (!is_consonant( lex(input[main]) ))
262 for (i = end; i >= start; i--)
263 if (is_consonant( lex(input[i]) ))