ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

indic.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of Indic Syllables for the Uniscribe Script Processor
00003  *
00004  * Copyright 2011 CodeWeavers, Aric Stewart
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  */
00021 #include "config.h"
00022 #include <stdarg.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "wingdi.h"
00030 #include "winnls.h"
00031 #include "usp10.h"
00032 #include "winternl.h"
00033 
00034 #include "wine/debug.h"
00035 #include "usp10_internal.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
00038 
00039 static void debug_output_string(LPCWSTR str, int cChar, lexical_function f)
00040 {
00041     int i;
00042     if (TRACE_ON(uniscribe))
00043     {
00044         for (i = 0; i < cChar; i++)
00045         {
00046             switch (f(str[i]))
00047             {
00048                 case lex_Consonant: TRACE("C"); break;
00049                 case lex_Ra: TRACE("Ra"); break;
00050                 case lex_Vowel: TRACE("V"); break;
00051                 case lex_Nukta: TRACE("N"); break;
00052                 case lex_Halant: TRACE("H"); break;
00053                 case lex_ZWNJ: TRACE("Zwnj"); break;
00054                 case lex_ZWJ: TRACE("Zwj"); break;
00055                 case lex_Matra_post: TRACE("Mp");break;
00056                 case lex_Matra_above: TRACE("Ma");break;
00057                 case lex_Matra_below: TRACE("Mb");break;
00058                 case lex_Matra_pre: TRACE("Mm");break;
00059                 case lex_Modifier: TRACE("Sm"); break;
00060                 case lex_Vedic: TRACE("Vd"); break;
00061                 case lex_Anudatta: TRACE("A"); break;
00062                 case lex_Composed_Vowel: TRACE("t"); break;
00063                 default:
00064                     TRACE("X"); break;
00065             }
00066         }
00067         TRACE("\n");
00068     }
00069 }
00070 
00071 static inline BOOL is_matra( int type )
00072 {
00073     return (type == lex_Matra_above || type == lex_Matra_below ||
00074             type == lex_Matra_pre || type == lex_Matra_post ||
00075             type == lex_Composed_Vowel);
00076 }
00077 
00078 static inline BOOL is_joiner( int type )
00079 {
00080     return (type == lex_ZWJ || type == lex_ZWNJ);
00081 }
00082 
00083 static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next,
00084                             lexical_function lex)
00085 {
00086     if (!is_consonant( lex(input[next]) )) return -1;
00087     next++;
00088     if ((next < cChar) && lex(input[next]) == lex_Nukta)
00089             next++;
00090     if ((next < cChar) && lex(input[next])==lex_Halant)
00091     {
00092         next++;
00093         if((next < cChar) && is_joiner( lex(input[next]) ))
00094             next++;
00095         if ((next < cChar) && is_consonant( lex(input[next]) ))
00096             return next;
00097     }
00098     else if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant)
00099     {
00100         next+=2;
00101         if ((next < cChar) && is_consonant( lex(input[next]) ))
00102             return next;
00103     }
00104     return -1;
00105 }
00106 
00107 static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start,
00108                                     INT *main, INT next, lexical_function lex)
00109 {
00110     int check;
00111     int headers = 0;
00112     do
00113     {
00114         check = consonant_header(input,cChar,start,next,lex);
00115         if (check != -1)
00116         {
00117             next = check;
00118             headers++;
00119         }
00120     } while (check != -1);
00121     if (headers || is_consonant( lex(input[next]) ))
00122     {
00123         *main = next;
00124         next++;
00125     }
00126     else
00127         return -1;
00128     if ((next < cChar) && lex(input[next]) == lex_Nukta)
00129             next++;
00130     if ((next < cChar) && lex(input[next]) == lex_Anudatta)
00131             next++;
00132 
00133     if ((next < cChar) && lex(input[next]) == lex_Halant)
00134     {
00135         next++;
00136         if((next < cChar) && is_joiner( lex(input[next]) ))
00137             next++;
00138     }
00139     else if (next < cChar)
00140     {
00141         while((next < cChar) && is_matra( lex(input[next]) ))
00142             next++;
00143         if ((next < cChar) && lex(input[next]) == lex_Nukta)
00144             next++;
00145         if ((next < cChar) && lex(input[next]) == lex_Halant)
00146             next++;
00147     }
00148     if ((next < cChar) && lex(input[next]) == lex_Modifier)
00149             next++;
00150     if ((next < cChar) && lex(input[next]) == lex_Vedic)
00151             next++;
00152     return next;
00153 }
00154 
00155 static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start,
00156                                     INT next, lexical_function lex)
00157 {
00158     if ((next < cChar) && lex(input[next]) == lex_Nukta)
00159         next++;
00160     if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant && is_consonant( lex(input[next+2]) ))
00161         next+=3;
00162     else if ((next < cChar) && lex(input[next])==lex_Halant && is_consonant( lex(input[next+1]) ))
00163         next+=2;
00164     else if ((next < cChar) && lex(input[next])==lex_ZWJ && is_consonant( lex(input[next+1]) ))
00165         next+=2;
00166 
00167     if ((next < cChar) && is_matra( lex(input[next]) ))
00168     {
00169         while((next < cChar) && is_matra( lex(input[next]) ))
00170             next++;
00171         if ((next < cChar) && lex(input[next]) == lex_Nukta)
00172             next++;
00173         if ((next < cChar) && lex(input[next]) == lex_Halant)
00174             next++;
00175     }
00176 
00177     if ((next < cChar) && lex(input[next]) == lex_Modifier)
00178         next++;
00179     if ((next < cChar) && lex(input[next]) == lex_Vedic)
00180         next++;
00181     return next;
00182 }
00183 
00184 static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT* main, INT next, lexical_function lex )
00185 {
00186     if (lex(input[next])==lex_Vowel)
00187     {
00188         *main = next;
00189         return parse_vowel_syllable(input, cChar, start, next+1, lex);
00190     }
00191     else if ((cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_Vowel)
00192     {
00193         *main = next+2;
00194         return parse_vowel_syllable(input, cChar, start, next+3, lex);
00195     }
00196 
00197     else if (start == next && lex(input[next])==lex_NBSP)
00198     {
00199         *main = next;
00200         return parse_vowel_syllable(input, cChar, start, next+1, lex);
00201     }
00202     else if (start == next && (cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_NBSP)
00203     {
00204         *main = next+2;
00205         return parse_vowel_syllable(input, cChar, start, next+3, lex);
00206     }
00207 
00208     return parse_consonant_syllable(input, cChar, start, main, next, lex);
00209 }
00210 
00211 static BOOL Consonent_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern)
00212 {
00213     if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
00214     {
00215         if (modern)
00216             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pstf") > 0);
00217         else
00218         {
00219             WCHAR cc[2];
00220             cc[0] = pwChar[s->base];
00221             cc[1] = pwChar[s->base-1];
00222             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pstf") > 0);
00223         }
00224     }
00225     return FALSE;
00226 }
00227 
00228 static BOOL Consonent_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern)
00229 {
00230     if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
00231     {
00232         if (modern)
00233             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "blwf") > 0);
00234         else
00235         {
00236             WCHAR cc[2];
00237             cc[0] = pwChar[s->base];
00238             cc[1] = pwChar[s->base-1];
00239             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "blwf") > 0);
00240         }
00241     }
00242     return FALSE;
00243 }
00244 
00245 static BOOL Consonent_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern)
00246 {
00247     if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
00248     {
00249         if (modern)
00250             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pref") > 0);
00251         else
00252         {
00253             WCHAR cc[2];
00254             cc[0] = pwChar[s->base];
00255             cc[1] = pwChar[s->base-1];
00256             return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pref") > 0);
00257         }
00258     }
00259     return FALSE;
00260 }
00261 
00262 static BOOL Consonent_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical)
00263 {
00264     if ((lexical(pwChar[s->start])==lex_Ra) && s->end > s->start && lexical(pwChar[s->start+1]) == lex_Halant)
00265         return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->start], 1, 2, "rphf") > 0);
00266     return FALSE;
00267 }
00268 
00269 static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, IndicSyllable *s, lexical_function lex, BOOL modern)
00270 {
00271     int i;
00272     BOOL blwf = FALSE;
00273     BOOL pref = FALSE;
00274 
00275     /* remove ralf from consideration */
00276     if (Consonent_is_ralf(hdc, psa, psc, input, s, lex))
00277     {
00278         s->ralf = s->start;
00279         s->start+=2;
00280     }
00281 
00282     /* try to find a base consonant */
00283     if (!is_consonant( lex(input[s->base]) ))
00284     {
00285         for (i = s->end; i >= s->start; i--)
00286             if (is_consonant( lex(input[i]) ))
00287             {
00288                 s->base = i;
00289                 break;
00290             }
00291     }
00292 
00293     while ((blwf = Consonent_is_below_base_form(hdc, psa, psc, input, s, lex, modern)) || Consonent_is_post_base_form(hdc, psa, psc, input, s, lex, modern) || (pref = Consonent_is_pre_base_form(hdc, psa, psc, input, s, lex, modern)))
00294     {
00295         if (blwf && s->blwf == -1)
00296             s->blwf = s->base - 1;
00297         if (pref && s->pref == -1)
00298             s->pref = s->base - 1;
00299 
00300         for (i = s->base-1; i >= s->start; i--)
00301             if (is_consonant( lex(input[i]) ))
00302             {
00303                 s->base = i;
00304                 break;
00305             }
00306     }
00307 
00308     if (s->ralf >= 0)
00309         s->start = s->ralf;
00310 
00311     if (s->ralf == s->base)
00312         s->ralf = -1;
00313 
00314     return s->base;
00315 }
00316 
00317 void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern)
00318 {
00319     int index = 0;
00320     int next = 0;
00321     int center = 0;
00322 
00323     *syllable_count = 0;
00324 
00325     if (!lex)
00326     {
00327         ERR("Failure to have required functions\n");
00328         return;
00329     }
00330 
00331     debug_output_string(input, cChar, lex);
00332     while (next != -1)
00333     {
00334         while((next < cChar) && lex(input[next]) == lex_Generic)
00335             next++;
00336         index = next;
00337         if (next >= cChar)
00338             break;
00339         next = Indic_process_next_syllable(input, cChar, 0, &center, index, lex);
00340         if (next != -1)
00341         {
00342             if (*syllable_count)
00343                 *syllables = HeapReAlloc(GetProcessHeap(),0,*syllables, sizeof(IndicSyllable)*(*syllable_count+1));
00344             else
00345                 *syllables = HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable));
00346             (*syllables)[*syllable_count].start = index;
00347             (*syllables)[*syllable_count].base = center;
00348             (*syllables)[*syllable_count].ralf = -1;
00349             (*syllables)[*syllable_count].blwf = -1;
00350             (*syllables)[*syllable_count].pref = -1;
00351             (*syllables)[*syllable_count].end = next-1;
00352             FindBaseConsonant(hdc, psa, psc, input, &(*syllables)[*syllable_count], lex, modern);
00353             index = next;
00354             *syllable_count = (*syllable_count)+1;
00355         }
00356         else if (index < cChar)
00357         {
00358             TRACE("Processing failed at %i\n",index);
00359             next = ++index;
00360         }
00361     }
00362     TRACE("Processed %i of %i characters into %i syllables\n",index,cChar,*syllable_count);
00363 }
00364 
00365 void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern)
00366 {
00367     int i;
00368 
00369     if (!reorder_f)
00370     {
00371         ERR("Failure to have required functions\n");
00372         return;
00373     }
00374 
00375     Indic_ParseSyllables(hdc, psa, psc, input, cChar, syllables, syllable_count, lex, modern);
00376     for (i = 0; i < *syllable_count; i++)
00377         reorder_f(input, &(*syllables)[i], lex);
00378 }

Generated on Sat May 26 2012 04:25:18 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.