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
, IndicSyllable
**syllables
, int *syllable_count
, lexical_function lex
, reorder_function reorder_f
)
223 if (!lex
|| ! reorder_f
)
225 ERR("Failure to have required functions\n");
229 debug_output_string(input
, cChar
, lex
);
232 while((next
< cChar
) && lex(input
[next
]) == lex_Generic
)
235 next
= Indic_process_next_syllable(input
, cChar
, 0, ¢er
, index
, lex
);
239 *syllables
= HeapReAlloc(GetProcessHeap(),0,*syllables
, sizeof(IndicSyllable
)*(*syllable_count
+1));
241 *syllables
= HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable
));
242 (*syllables
)[*syllable_count
].start
= index
;
243 (*syllables
)[*syllable_count
].base
= center
;
244 (*syllables
)[*syllable_count
].end
= next
-1;
245 reorder_f(input
, &(*syllables
)[*syllable_count
], lex
);
247 *syllable_count
= (*syllable_count
)+1;
249 else if (index
< cChar
)
252 TRACE("Processing failed at %i\n",index
);
253 for (i
= index
; i
< cChar
; i
++)
254 if (lex(input
[i
])==lex_Generic
)
256 TRACE("Restart processing at %i\n",i
);
263 TRACE("Processed %i of %i characters into %i syllables\n",index
,cChar
,*syllable_count
);
266 int Indic_FindBaseConsonant(LPWSTR input
, IndicSyllable
*s
, lexical_function lex
)
269 /* try to find a base consonant */
270 if (!is_consonant( lex(input
[s
->base
]) ))
272 for (i
= s
->end
; i
>= s
->start
; i
--)
273 if (is_consonant( lex(input
[i
]) ))