Click here to Skip to main content
Licence CPOL
First Posted 19 Jan 2003
Views 191,487
Bookmarked 44 times

Arabic Support for Windows CE

By Mohamed Abdel-Monem | 19 Jan 2003
This article explains how to support the Arabic language in your applications written for Windows CE.
1 vote, 1.8%
1

2

3
7 votes, 12.5%
4
48 votes, 85.7%
5
4.90/5 - 57 votes
1 removed
μ 4.67, σa 1.09 [?]

Sample Image - arabicsupport.gif

Introduction

When Microsoft Windows CE first came to life and the number of PDAs based on it increased rapidly, the software market was opened widely for a new type of applications and we all wanted to write new applications or to port our application already written for Win32 to Windows CE. Unfortunately, for the Arabic market, there is no Arabic language support in WinCE 2.11 and WinCE 3.0.

After a long time some third parties introduced some solutions and each claimed “We have the first and best Arabic Language Support for Windows CE (or PocketPC)”. They offered their solutions for a big amount of what is called “money”. Too big for a poor freelance programmer to handle. And after one of the companies offering the solution asked me $5000 for their solution (don’t tell them I told you it was bad), I started to write the first and best Arabic Language support for Windows CE myself. It was about 14 months ago. And here is what I did.

Problem Identification

The main problem is that the WinCE 2.11 and WinCE 3.0 do not have intrinsic support for BiDi (Bi-Directional) fonts and RTL (Right To Left) window controls. I don’t know why. I think it’s not too difficult and I also think that, it will not take much memory nor processing time to support those features.

Before I go deep with you, I wanted you to notice what an Arabic support solution makes to a string to be displayed the right way on a window.

The Arabic string is stored from left to right as in English. But when it’s to be displayed, the first character in the string should be the right most character. Further, in Arabic, the character can take more than one glyph (figure or shape) depending on its position in the word: at first, in middle, at last, and alone. In Arabic Enabled Windows and Unicode ready Windows (Windows 2000 and up) all this is implemented intrinsically in the GDI. In WinCE we have to do this ourselves.

The solution

First, You have to install an Arabic TrueType font. The Tahoma of Arabic-Enabled Windows is great.

Arabization involves reversing the string, considering that numbers shouldn’t be reversed and perform glyph substitution manually.

To reverse the string I use:

//////////////////////////////////////////////////////////////////////
void ArabicReverse(CString &s)
{
    CString out, rev;
    s.MakeReverse();

    int i=0;
    while(i<s.GetLength())
    {
        if((s[i]>='0' && s[i]<='9'))    // isDigit(s[i]) ?
        {
            rev.Empty();
            while((s[i]>='0' && s[i]<='9'))    // isDigit(s[i]) ?
            {
                rev = rev + s[i];
                ++i;
            }
            rev.MakeReverse();
            out = out + rev;
        }
        else
        {
            out = out + s[i];
            ++i;
        }
    }
    s=out;
}
//////////////////////////////////////////////////////////////////////

The second step is a bit more tricky so be ready. We know that the Arabic string in the memory contains the Unicode characters that take the same form of the isolated glyphs of the letters. We have to make mapping from the character to the right glyphs to be displayed, considering all states of the letter.

I some how could construct an array of all Arabic letters' state. It is not sorted alphabetically. The first row in the table is the first piece of data I could collect about a letter and it was the letter ‘thal’.

As far as I know .. the rules of glyph substitution are somewhere in the TTF file but I found it very complex. To help constructing the rules for glyph substitution, I made two sets of characters according to whether it may need a link to the previous or the next character.

//////////////////////////////////////////////////////////////////////
CString Arabize (LPCTSTR in)
{
    static struct
    {
        WCHAR character;
        WCHAR endGlyph;
        WCHAR iniGlyph;
        WCHAR midGlyph;
        WCHAR isoGlyph;
    }a[N_DISTINCT_CHARACTERS]=
    {
        {0x630, 0xfeac, 0xfeab, 0xfeac, 0xfeab},
        {0x62f, 0xfeaa, 0xfea9, 0xfeaa, 0xfea9},
        {0x62c, 0xfe9e, 0xfe9f, 0xfea0, 0xfe9d},
        {0x62d, 0xfea2, 0xfea3, 0xfea4, 0xfea1},
        {0x62e, 0xfea6, 0xfea7, 0xfea8, 0xfea5},
        {0x647, 0xfeea, 0xfeeb, 0xfeec, 0xfee9},
        {0x639, 0xfeca, 0xfecb, 0xfecc, 0xfec9},
        {0x63a, 0xfece, 0xfecf, 0xfed0, 0xfecd},
        {0x641, 0xfed2, 0xfed3, 0xfed4, 0xfed1},
        {0x642, 0xfed6, 0xfed7, 0xfed8, 0xfed5},
        {0x62b, 0xfe9a, 0xfe9b, 0xfe9c, 0xfe99},
        {0x635, 0xfeba, 0xfebb, 0xfebc, 0xfeb9},
        {0x636, 0xfebe, 0xfebf, 0xfec0, 0xfebd},
        {0x637, 0xfec2, 0xfec3, 0xfec4, 0xfec1},
        {0x643, 0xfeda, 0xfedb, 0xfedc, 0xfed9},
        {0x645, 0xfee2, 0xfee3, 0xfee4, 0xfee1},
        {0x646, 0xfee6, 0xfee7, 0xfee8, 0xfee5},
        {0x62a, 0xfe96, 0xfe97, 0xfe98, 0xfe95},
        {0x627, 0xfe8e, 0xfe8d, 0xfe8e, 0xfe8d},
        {0x644, 0xfede, 0xfedf, 0xfee0, 0xfedd},
        {0x628, 0xfe90, 0xfe91, 0xfe92, 0xfe8f},
        {0x64a, 0xfef2, 0xfef3, 0xfef4, 0xfef1},
        {0x633, 0xfeb2, 0xfeb3, 0xfeb4, 0xfeb1},
        {0x634, 0xfeb6, 0xfeb7, 0xfeb8, 0xfeb5},
        {0x638, 0xfec6, 0xfec7, 0xfec8, 0xfec5},
        {0x632, 0xfeb0, 0xfeaf, 0xfeb0, 0xfeaf},
        {0x648, 0xfeee, 0xfeed, 0xfeee, 0xfeed},
        {0x629, 0xfe94, 0xfe93, 0xfe93, 0xfe93},
        {0x649, 0xfef0, 0xfeef, 0xfef0, 0xfeef},
        {0x631, 0xfeae, 0xfead, 0xfeae, 0xfead},
        {0x624, 0xfe86, 0xfe85, 0xfe86, 0xfe85},
        {0x621, 0xfe80, 0xfe80, 0xfe80, 0xfe7f},
        {0x626, 0xfe8a, 0xfe8b, 0xfe8c, 0xfe89},
        {0x623, 0xfe84, 0xfe83, 0xfe84, 0xfe83},
        {0x622, 0xfe82, 0xfe81, 0xfe82, 0xfe81},
        {0x625, 0xfe88, 0xfe87, 0xfe88, 0xfe87}
    };
    BOOL linkBefore, linkAfter;
    CString out;
    out=in;
    for(UINT i=0; i<_tcslen(in); i++)
    {
        WCHAR ch=in[i];
        if(((ch>=0x0621 && ch<=0x064a)) // is an Arabic character?
        {
            int idx = 0;
            while (idx < N_DISTINCT_CHARACTERS)
            {
                if (a[idx].character == in[i])
                    break;
                ++idx;
            }
            
            if(i == _tcslen(in) - 1)
                linkAfter=0;
            else
                linkAfter = (isFromTheSet1(in[i+1]) || 
                                   isFromTheSet2(in[i+1]));
            if(i == 0)
                linkBefore=0;
            else
                linkBefore=isFromTheSet1(in[i-1]);
    
            if(linkBefore && linkAfter)
                out.SetAt(i, a[idx].midGlyph);
            if(linkBefore && !linkAfter)
                out.SetAt(i, a[idx].endGlyph);
            if(!linkBefore && linkAfter)
                out.SetAt(i, a[idx].iniGlyph);
            if(!linkBefore && !linkAfter)
                out.SetAt(i, a[idx].glyph);
        }
    }
    ArabicReverse (out);
    return out;
}
//////////////////////////////////////////////////////////////////////
BOOL BzArabicRender::isFromTheSet1(WCHAR ch)
{
    static WCHAR theSet1[22]={
        0x62c, 0x62d, 0x62e, 0x647, 0x639, 0x63a, 0x641, 0x642,
        0x62b, 0x635, 0x636, 0x637, 0x643, 0x645, 0x646, 0x62a,
        0x644, 0x628, 0x64a, 0x633, 0x634, 0x638};
    int i = 0;
    while (i < 22)
    {
        if(ch == theSet1[i])
            return TRUE;
        ++i;
    }
    return FALSE;
}
//////////////////////////////////////////////////////////////////////
BOOL BzArabicRender::isFromTheSet2(WCHAR ch)
{
    static WCHAR theSet2[12]={
        0x627, 0x623, 0x625, 0x622, 0x62f, 0x630, 0x631, 0x632,
        0x648, 0x624, 0x629, 0x649};
    int i = 0;
    while (i < 12)
    {
        if(ch == theSet2[i])
            return TRUE;
        ++i;
    }
    return FALSE;
}
//////////////////////////////////////////////////////////////////////

To use this .. just SetWindowText the window you want to the output of the Arabize().

window.SetWindowText(str); //before
window.SetWindowText(Arabize(str)); //after

or

dc.DrawText(str,……); //before
dc.DrawText(Arabize(str),……); //after

… etc

So there is not much change in code if you already have written old code for English.

Of course it’s not the ideal solution. I think the optimum solution is to hook the DrawText function and add all this stuff. But when I wrote this code there was no online material showing how to hook Windows CE APIs.

I will update the document to show how to retrieve the characters from the glyphs to process them soon. Or it may be another article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mohamed Abdel-Monem

Chief Technology Officer
www.mmonem.com
Egypt Egypt

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionWhy ARABIC LETTER PEH is not shown correctly on Android 3.x? Pinmemberbreceivemail22:56 9 Oct '11  
GeneralNot supporting some combined fonts Pinmembersureshthapa0:42 27 Feb '11  
Generalhave problem in code Pinmemberrezam6916:44 30 Mar '10  
GeneralNice work! PinmemberMd. Ali Naser Khan1:20 7 May '09  
GeneralNice work... PinmemberBabakAnsari20:33 25 Jan '09  
QuestionRe: Nice work... PinmemberHarishkg2:13 2 Apr '09  
GeneralRe: Nice work... Pinmembernizinizinizi18:17 6 Apr '10  
GeneralProblem with 'Arabization' of Urdu Pinmemberabwd14:09 13 Jan '09  
GeneralRe: Problem with 'Arabization' of Urdu Pinmemberabwd21:25 13 Jan '09  
Hi,
 
Ok I believe I have been able to answer my own question and have posted the following in the hope that it will help someone else! My problem was basically that the characters had not been defined and as a result some strange things were happening where characters were being reversed (because the algorithm thought that they were non-Arabic..). I have been coding in C# but the similar changes could be made to the C++ version.
 
N.B. I have included (what I believe to be) the lookup table entries for the Urdu and Farsi characters but have not done the Pashto/Kurdish/others (indicated with 'Not yet included')
 
The first change I made was to the lookupArray which can be tacked onto the end of the existing one:
            {0x653, 0, 0, 0, 0},						// Not Used
            {0x654, 0, 0, 0, 0},						// Not Used
            {0x655, 0, 0, 0, 0},						// Not Used
            {0x656, 0, 0, 0, 0},						// Not Used
            {0x657, 0, 0, 0, 0},						// Not Used
            {0x658, 0, 0, 0, 0},						// Not Used
            {0x659, 0, 0, 0, 0},						// Not Used
            {0x65A, 0, 0, 0, 0},						// Not Used
            {0x65B, 0, 0, 0, 0},						// Not Used
            {0x65C, 0, 0, 0, 0},						// Not Used
            {0x65D, 0, 0, 0, 0},						// Not Used
            {0x65E, 0, 0, 0, 0},						// Not Used
            {0x65F, 0, 0, 0, 0},						// Not Used
            {0x660, 0x660, 0x660, 0x660, 0x660},        // 0
            {0x661, 0x661, 0x661, 0x661, 0x661},        // 1
            {0x662, 0x662, 0x662, 0x662, 0x662},        // 2
            {0x663, 0x663, 0x663, 0x663, 0x663},        // 3
            {0x664, 0x664, 0x664, 0x664, 0x664},        // 4
            {0x665, 0x665, 0x665, 0x665, 0x665},        // 5
            {0x666, 0x666, 0x666, 0x666, 0x666},        // 6
            {0x667, 0x667, 0x667, 0x667, 0x667},        // 7
            {0x668, 0x668, 0x668, 0x668, 0x668},        // 8
            {0x669, 0x669, 0x669, 0x669, 0x669},        // 9
            {0x66a, 0x66a, 0x66a, 0x66a, 0x66a},        // %
            {0x66b, 0x66b, 0x66b, 0x66b, 0x66b},        // ,
            {0x66c, 0x66c, 0x66c, 0x66c, 0x66c},        // ,
            {0x66d, 0x66d, 0x66d, 0x66d, 0x66d},        // *
            {0x66E, 0, 0, 0, 0},						// Not Used
            {0x66F, 0, 0, 0, 0},						// Not Used
            {0x670, 0, 0, 0, 0},                        // superscript alef
            {0x671, 0xfb51, 0xfb50, 0xfb51, 0xfb50},    // alef wasla
            {0x672, 0, 0, 0, 0},						// Not Used
            {0x673, 0, 0, 0, 0},						// Not Used
            {0x674, 0, 0, 0, 0},						// Not Used
            {0x675, 0, 0, 0, 0},						// Not Used
            {0x676, 0, 0, 0, 0},						// Not Used
            {0x677, 0, 0, 0, 0},						// Not Used
            {0x678, 0, 0, 0, 0},						// Not Used
            {0x679, 0xfb67, 0xfb68, 0xfb69, 0xfb66},    // Urdu te
            {0x67A, 0, 0, 0, 0},						// Not Used
            {0x67B, 0, 0, 0, 0},						// Not Used
            {0x67c, 0x67c, 0x67c, 0x67c, 0x67c},        // Not yet included
            {0x67D, 0, 0, 0, 0},						// Not Used
            {0x67e, 0xfb57, 0xfb58, 0xfb59, 0xfb56},    // Farsi pe
            {0x67F, 0, 0, 0, 0},						// Not Used
            {0x680, 0, 0, 0, 0},						// Not Used
            {0x681, 0x681, 0x681, 0x681, 0x681},        // Not yet included
            {0x682, 0, 0, 0, 0},						// Not Used
            {0x683, 0, 0, 0, 0},						// Not Used
            {0x684, 0, 0, 0, 0},						// Not Used
            {0x685, 0x685, 0x685, 0x685, 0x685},        // Not yet included
            {0x686, 0xfb7b, 0xfb7c, 0xfb7d, 0xfb7a},    // Farsi cim
            {0x687, 0, 0, 0, 0},						// Not Used
            {0x688, 0xfb89, 0xfb88, 0xfb89, 0xfb88},    // Urdu dal
            {0x689, 0x689, 0x689, 0x689, 0x689},        // Not yet included
            {0x68A, 0, 0, 0, 0},						// Not Used
            {0x68B, 0, 0, 0, 0},						// Not Used
            {0x68C, 0, 0, 0, 0},						// Not Used
            {0x68D, 0, 0, 0, 0},						// Not Used
            {0x68E, 0, 0, 0, 0},						// Not Used
            {0x68F, 0, 0, 0, 0},						// Not Used
            {0x690, 0, 0, 0, 0},						// Not Used
            {0x691, 0xfb8d, 0xfb8c, 0xfb8d, 0xfb8c},    // Urdu ar
            {0x692, 0, 0, 0, 0},						// Not Used
            {0x693, 0x693, 0x693, 0x693, 0x693},        // Not yet included
            {0x694, 0x694, 0x694, 0x694, 0x694},        // Not yet included
            {0x695, 0x695, 0x695, 0x695, 0x695},        // Not yet included
            {0x696, 0x696, 0x696, 0x696, 0x696},        // Not yet included
            {0x697, 0, 0, 0, 0},						// Not Used
            {0x698, 0xfb8b, 0xfb8a, 0xfb8b, 0xfb8a},    // Farsi zhe
            {0x699, 0, 0, 0, 0},						// Not Used
            {0x69a, 0x69a, 0x69a, 0x69a, 0x69a},        // Not yet included
            {0x69B, 0, 0, 0, 0},						// Not Used
            {0x69C, 0, 0, 0, 0},						// Not Used
            {0x69D, 0, 0, 0, 0},						// Not Used
            {0x69E, 0, 0, 0, 0},						// Not Used
            {0x69F, 0, 0, 0, 0},						// Not Used
            {0x6a0, 0x6a0, 0x6a0, 0x6a0, 0x6a0},        // Not yet included
            {0x6A1, 0, 0, 0, 0},						// Not Used
            {0x6A2, 0, 0, 0, 0},						// Not Used
            {0x6A3, 0, 0, 0, 0},						// Not Used
            {0x6a4, 0x6a4, 0x6a4, 0x6a4, 0x6a4},        // Not yet included
            {0x6A5, 0, 0, 0, 0},						// Not Used
            {0x6A6, 0, 0, 0, 0},						// Not Used
            {0x6A7, 0, 0, 0, 0},						// Not Used
            {0x6A8, 0, 0, 0, 0},						// Not Used
            {0x6a9, 0xfb8f, 0xfb90, 0xfb91, 0xfb8e},    // Farsi kaf
            {0x6AA, 0, 0, 0, 0},						// Not Used
            {0x6ab, 0x6ab, 0x6ab, 0x6ab, 0x6ab},        // Not yet included
            {0x6ac, 0x6ac, 0x6ac, 0x6ac, 0x6ac},        // Not yet included
            {0x6ad, 0x6ad, 0x6ad, 0x6ad, 0x6ad},        // Not yet included
            {0x6AE, 0, 0, 0, 0},						// Not Used
            {0x6af, 0xfb93, 0xfb94, 0xfb95, 0xfb92},    // Farsi gaf
            {0x6B0, 0, 0, 0, 0},						// Not Used
            {0x6B1, 0, 0, 0, 0},						// Not Used
            {0x6B2, 0, 0, 0, 0},						// Not Used
            {0x6B3, 0, 0, 0, 0},						// Not Used
            {0x6B4, 0, 0, 0, 0},						// Not Used
            {0x6b5, 0x6b5, 0x6b5, 0x6b5, 0x6b5},        // Not yet included
            {0x6b6, 0x6b6, 0x6b6, 0x6b6, 0x6b6},        // Not yet included
            {0x6b7, 0x6b7, 0x6b7, 0x6b7, 0x6b7},        // Not yet included
            {0x6B8, 0, 0, 0, 0},						// Not Used
            {0x6B9, 0, 0, 0, 0},						// Not Used
            {0x6ba, 0xfb9f, 0xfb9e, 0xfb9f, 0xfb9e},    // nun ghunna
            {0x6BB, 0, 0, 0, 0},						// Not Used
            {0x6bc, 0x6bc, 0x6bc, 0x6bc, 0x6bc},        // Not yet included
            {0x6bd, 0x6bd, 0x6bd, 0x6bd, 0x6bd},        // Not yet included
            {0x6be, 0xfbab, 0xfbac, 0xfbad, 0xfbaa},    // Urdu do cashmi he
            {0x6BF, 0, 0, 0, 0},						// Not Used
            {0x6c0, 0x6c0, 0x6c0, 0x6c0, 0x6c0},        // Not yet included
            {0x6c1, 0xfba7, 0xfba6, 0xfba7, 0xfba6},    // Urdu choti he
            {0x6c2, 0xfba5, 0xfba4, 0xfba5, 0xfba4},    // Urdu heh goal with hamza
            {0x6c3, 0x6c3, 0x6c3, 0x6c3, 0x6c3},        // Urdu teh marbuta goal (can't find 0xf000 range characters)
            {0x6C4, 0, 0, 0, 0},						// Not Used
            {0x6C5, 0, 0, 0, 0},						// Not Used
            {0x6c6, 0x6c6, 0x6c6, 0x6c6, 0x6c6},        // Not yet included
            {0x6c7, 0x6c7, 0x6c7, 0x6c7, 0x6c7},        // Not yet included
            {0x6c8, 0x6c8, 0x6c8, 0x6c8, 0x6c8},        // Not yet included
            {0x6c9, 0x6c9, 0x6c9, 0x6c9, 0x6c9},        // Not yet included
            {0x6CA, 0, 0, 0, 0},						// Not Used
            {0x6cb, 0x6cb, 0x6cb, 0x6cb, 0x6cb},        // Not yet included
            {0x6cc, 0xfbfd, 0xfbfe, 0xfbff, 0xfbfc},    // Farsi yeh
            {0x6cd, 0x6cd, 0x6cd, 0x6cd, 0x6cd},        // Not yet included
            {0x6ce, 0x6ce, 0x6ce, 0x6ce, 0x6ce},        // Not yet included
            {0x6cf, 0x6cf, 0x6cf, 0x6cf, 0x6cf},        // Not yet included
            {0x6D0, 0x6D0, 0x6D0, 0x6D0, 0x6D0},        // Not yet included
            {0x6D1, 0x6D1, 0x6D1, 0x6D1, 0x6D1},        // Not yet included
            {0x6D2, 0xFBAF, 0xFBAE, 0xFBAF, 0xFBAE},    // Urdu bari ye
            {0x6D3, 0xFBB1, 0xFBB0, 0xFBB1, 0xFBB0},    // Urdu bari ye with hamza
            {0x6D4, 0x6D4, 0x6D4, 0x6D4, 0x6D4},        // full stop
            {0x6D5, 0x6D5, 0x6D5, 0x6D5, 0x6D5},        // Not yet included
            {0x6D6, 0, 0, 0, 0},						// Not Used
            {0x6D7, 0, 0, 0, 0},						// Not Used
            {0x6D8, 0, 0, 0, 0},						// Not Used
            {0x6D9, 0, 0, 0, 0},						// Not Used
            {0x6DA, 0, 0, 0, 0},						// Not Used
            {0x6DB, 0, 0, 0, 0},						// Not Used
            {0x6DC, 0, 0, 0, 0},						// Not Used
            {0x6DD, 0, 0, 0, 0},						// Not Used
            {0x6DE, 0, 0, 0, 0},						// Not Used
            {0x6DF, 0, 0, 0, 0},						// Not Used
            {0x6E0, 0, 0, 0, 0},						// Not Used
            {0x6E1, 0, 0, 0, 0},						// Not Used
            {0x6E2, 0, 0, 0, 0},						// Not Used
            {0x6E3, 0, 0, 0, 0},						// Not Used
            {0x6E4, 0, 0, 0, 0},						// Not Used
            {0x6E5, 0, 0, 0, 0},						// Not Used
            {0x6E6, 0, 0, 0, 0},						// Not Used
            {0x6E7, 0, 0, 0, 0},						// Not Used
            {0x6E8, 0, 0, 0, 0},						// Not Used
            {0x6E9, 0, 0, 0, 0},						// Not Used
            {0x6EA, 0, 0, 0, 0},						// Not Used
            {0x6EB, 0, 0, 0, 0},						// Not Used
            {0x6EC, 0, 0, 0, 0},						// Not Used
            {0x6ED, 0, 0, 0, 0},						// Not Used
            {0x6EE, 0, 0, 0, 0},						// Not Used
            {0x6EF, 0, 0, 0, 0},						// Not Used
            {0x6F0, 0x6F0, 0x6F0, 0x6F0, 0x6F0},        // Farsi 0
            {0x6F1, 0x6F1, 0x6F1, 0x6F1, 0x6F1},        // Farsi 1
            {0x6F2, 0x6F2, 0x6F2, 0x6F2, 0x6F2},        // Farsi 2
            {0x6F3, 0x6F3, 0x6F3, 0x6F3, 0x6F3},        // Farsi 3
            {0x6F4, 0x6F4, 0x6F4, 0x6F4, 0x6F4},        // Farsi 4
            {0x6F5, 0x6F5, 0x6F5, 0x6F5, 0x6F5},        // Farsi 5
            {0x6F6, 0x6F6, 0x6F6, 0x6F6, 0x6F6},        // Farsi 6
            {0x6F7, 0x6F7, 0x6F7, 0x6F7, 0x6F7},        // Farsi 7
            {0x6F8, 0x6F8, 0x6F8, 0x6F8, 0x6F8},        // Farsi 8
            {0x6F9, 0x6F9, 0x6F9, 0x6F9, 0x6F9},        // Farsi 9
 
Next I updated Set 1 and 2 to include the new characters:
 
        private static readonly int[] set1 =
        {
            0x626, 0x628, 0x62a, 0x62b, 0x62c, 0x62d, 0x62e, 0x633,
            0x634, 0x635, 0x636, 0x637, 0x638, 0x639, 0x63a, 0x640,
            0x641, 0x642, 0x643, 0x644, 0x645, 0x646, 0x647, 0x64a,
            0x679, 0x67E, 0x686, 0x698, 0x6A9, 0x6AF, 0x6BE, 0x6CC
        };
 
        private static readonly int[] set2 =
        {
            0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630,
            0x631, 0x632, 0x648, 0x649, 0x671, 0x688, 0x691, 0x6BA,
            0x6C1, 0x6C2, 0x6C3, 0x6D2, 0x6D3
        };
 
and finally I had to modify the IsArabic function to handle the new linking characters and numbers:
 
        private static bool IsArabic(char ch)
        {
            int ch1 = ch;
            if((((ch1 & 0xff00) ^ 0x0600) != 0) &&
                (((ch1 & 0xff00) ^ 0xfe00) != 0) &&
                (((ch1 & 0xff00) ^ 0xfb00) != 0) ||
                (((ch1 & 0xfff0) ^ 0x0660) == 0) ||
                (((ch1 & 0xfff0) ^ 0x06f0) == 0))
                return false;
            return BinarySearch(arabicArray, ch1) >= 0;
        }
 

I have tried to do my best with regard to getting the right characters in the right places but as I said in my previous post, I don't know Arabic or Urdu so there may be mistakes. If someone who does know Arabic/Urdu and can find a problem then I am certainly interested to know!
 
I would also like to send out my sincere thanks to Mohamed Abdel-Monem and Sherif ElMetainy for their fantastic work!
 
Enjoy..
 
Andrew
QuestionFinding list of Installed softwares in windows ce device PinmemberG.Swamy Suresh19:43 27 Nov '08  
GeneralIf you agree to cooperate with me. PinmemberMember 104088623:41 18 Oct '08  
GeneralC# updated code - Points of concerns PinmemberAhmad El-Helaly6:16 21 Aug '08  
GeneralRe: C# updated code - Points of concerns PinmemberMember 68709121:19 14 Sep '08  
GeneralRe: C# updated code - Points of concerns PinmemberZynur17:51 23 Sep '08  
Generaltashkeel character Pinmemberbasicci@hotmail.com22:59 23 Jun '08  
GeneralConverted to VB version of arabize function for arabic support in win CE PinmemberAhmad Abrishami21:26 29 May '08  
GeneralRe: Converted to VB version of arabize function for arabic support in win CE Pinmemberbasicci@hotmail.com2:02 17 Jun '08  
QuestionArabic strings stored in XML files Pinmembermenuthaur3:44 10 May '08  
QuestionArabic strings stored in XML files Pinmembermenuthaur3:44 10 May '08  
QuestionArabic strings stored in XML files Pinmembermenuthaur3:44 10 May '08  
GeneralInternet Explorer doesn't render arabic correctly Pinmembersherifomran12:06 21 Apr '08  
Generali have problem in Arabic Pages in the internet explorer PinmemberMicroway0:55 25 Mar '08  
Generalhelp needed Pinmemberreham21:31 6 Feb '08  
GeneralFor all people that has problem ASCII to Unicode problem PinmemberAhmedEssamNaiem1:02 6 Oct '07  
Generalproblem with unicode characters Pinmemberbreceivemail8:30 5 Aug '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120210.1 | Last Updated 20 Jan 2003
Article Copyright 2003 by Mohamed Abdel-Monem
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid