2017-02-22 57 views
2

Большинство арабских букв имеют несколько контекстных форм, например, последний ب имеет общий юникод 0628.Получить средний/начальный/конечный арабский символ в строке

Но если последнее в начале слова примет эту форму بـ‎ unicode FE91.

Middle = ـبـ‎ unicode FE92.

Конец слова = ـب‎‎ unicode FE90.

Я пытаюсь получить код char, но я всегда получаю общий юникод.

procedure TfMain.btn2Click(Sender: TObject); 
const 
    Str = 'يبداء'; 
    Ch = 'ب'; 
begin 
    ShowMessage(IntToHex(Ord(Ch), 4)); // return 0628 - Correct 
    ShowMessage(IntToHex(Ord(Str[2]), 4)); // return 0628 - Wrong 
end; 

В: Как я могу получить правильный код для символа в зависимости от его положения в слове?

Дополнительная информация

https://en.wikipedia.org/wiki/Bet_(letter)#Arabic_b.C4.81.CA.BE https://en.wikipedia.org/wiki/Arabic_script_in_Unicode

+3

Я подозреваю, что ваш код работает правильно. Показанная строка действительно содержит код символа 0628, поэтому чтение 'Ord (Str [2])' дает вам это значение. Средство визуализации текста * интерпретирует * этот код символа по-разному в зависимости от контекста. Когда он появляется в конце слова, он становится * отображаемым *, как если бы это был fe90. С другой стороны, символы fe90-2 - это способы получения зависимых от контекста глифов без учета окружающего контекста. То есть символ fe90 будет отображаться как символ конца слова независимо от того, какие другие коды символов находятся в смежных позициях в переменной 'string'. –

+0

Возможный дубликат [Как получить одну арабскую букву в строке со значением преобразования Unicode в DELPHI?] (Http://stackoverflow.com/questions/16556586/how-to-get-a-single-arabic-letter -в-а-строка-с-его-Юникода-преобразования-ва) – ventiseis

ответ

1

Я пришел с этой идеей, как полностью завершенного обходной путь на данный момент.

Следующая функция вернет правильный символ формы U-Table в зависимости от его положения из переданной строки.

Эта функция учитывает грамматику на арабском языке.

type 
    T3Ch = array[0..2] of Char; 
    T5Ch = array[0..4] of Char; 

{Arabic — Unicode Character Table} 
const 
    cAlif : T3Ch = (#$0627, #$FE8D, #$FE8E); // General/Isolated/End 
    cBa  : T5Ch = (#$0628, #$FE8F, #$FE90, #$FE92, #$FE91); // General/Isolated/End/Middle/Beginning 
    cTa  : T5Ch = (#$062A, #$FE95, #$FE96, #$FE98, #$FE97); 
    cTha  : T5Ch = (#$062B, #$FE99, #$FE9A, #$FE9C, #$FE9B); 
    cGim  : T5Ch = (#$062C, #$FE9D, #$FE9E, #$FEA0, #$FE9F); 
    c7a  : T5Ch = (#$062D, #$FEA1, #$FEA2, #$FEA4, #$FEA3); 
    c5a  : T5Ch = (#$062E, #$FEA5, #$FEA6, #$FEA8, #$FEA7); 
    cDal  : T3Ch = (#$062F, #$FEA9, #$FEAA); 
    cThal : T3Ch = (#$0630, #$FEAB, #$FEAC); 
    cRa  : T3Ch = (#$0631, #$FEAD, #$FEAE); 
    cZa  : T3Ch = (#$0632, #$FEAF, #$FEB0); 
    cSin  : T5Ch = (#$0633, #$FEB1, #$FEB2, #$FEB4, #$FEB3); 
    cShin : T5Ch = (#$0634, #$FEB5, #$FEB6, #$FEB8, #$FEB7); 
    cSad  : T5Ch = (#$0635, #$FEB9, #$FEBA, #$FEBC, #$FEBB); 
    cDad  : T5Ch = (#$0636, #$FEBD, #$FEBE, #$FEC0, #$FEBF); 
    c6a  : T5Ch = (#$0637, #$FEC1, #$FEC2, #$FEC4, #$FEC3); 
    c6_a  : T5Ch = (#$0638, #$FEC5, #$FEC6, #$FEC8, #$FEC7); 
    cAyn  : T5Ch = (#$0639, #$FEC9, #$FECA, #$FECC, #$FECB); 
    cGayn : T5Ch = (#$063A, #$FECD, #$FECE, #$FED0, #$FECF); 
    cFa  : T5Ch = (#$0641, #$FED1, #$FED2, #$FED4, #$FED3); 
    cQaf  : T5Ch = (#$0642, #$FED5, #$FED6, #$FED8, #$FED7); 
    cKaf  : T5Ch = (#$0643, #$FED9, #$FEDA, #$FEDC, #$FEDB); 
    cLam  : T5Ch = (#$0644, #$FEDD, #$FEDE, #$FEE0, #$FEDF); 
    cMim  : T5Ch = (#$0645, #$FEE1, #$FEE2, #$FEE4, #$FEE3); 
    cNun  : T5Ch = (#$0646, #$FEE5, #$FEE6, #$FEE8, #$FEE7); 
    cHa  : T5Ch = (#$0647, #$FEE9, #$FEEA, #$FEEC, #$FEEB); 
    cWaw  : T3Ch = (#$0648, #$FEED, #$FEEE); 
    cYa  : T5Ch = (#$064A, #$FEF1, #$FEF2, #$FEF4, #$FEF3); 
    cAlifMad : T3Ch = (#$0622, #$FE81, #$FE82); 
    cTaMar : T3Ch = (#$0629, #$FE93, #$FE94); 
    cAlifMaq : T3Ch = (#$0649, #$FEEF, #$FEF0); 

type 
    TChAsEnd = array[0..6] of Char; 
const 
    cChAsEnd : TChAsEnd = (#$0627, #$062F, #$0630, #$0631, #$0632, #$0648, #$0622); 

function ChrInSet(C: Char; const ChSet: array of Char): Boolean; 
var 
    Ch: Char; 
begin 
    Result := False; 
    for Ch in ChSet do begin 
    if Ch = C then begin 
     Result := True; 
     Exit; 
    end; 
    end; 
end; 

function _GetArabicChar(const AText: string; CharPos: Integer): Char; 
var 
    Ch : Char; 
    Len : Integer; 
begin 
    Len := Length(AText); 
    if CharPos > Len then Exit; 
    Ch := Chr(Ord(Atext[CharPos])); 

    if (ChrInSet(Atext[CharPos-1], cChAsEnd)) then begin 
    if CharPos = Len then 
     Exit(Ch) 
    else begin 
     CharPos := 1; // retrun a beginning form 
    end; 
    end; 

    Result := Ch; 

    if (Ch = cAlif[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cAlif[2] 
    end; 

    if (Ch = cBa[0]) then begin 
    Result := cBa[3]; // defualt result is the Middle 

    if (CharPos = Len) then 
     Result := cBa[2]; 

    if (CharPos = 1) then 
     Result := cBa[4]; 
    end; 

    if (Ch = cTa[0]) then begin 
    Result := cTa[3]; 

    if (CharPos = Len) then 
     Result := cTa[2]; 

    if (CharPos = 1) then 
     Result := cTa[4]; 
    end; 

    if (Ch = cTha[0]) then begin 
    Result := cTha[3]; 

    if (CharPos = Len) then 
     Result := cTha[2]; 

    if (CharPos = 1) then 
     Result := cTha[4]; 
    end; 

    if (Ch = cGim[0]) then begin 
    Result := cGim[3]; 

    if (CharPos = Len) then 
     Result := cGim[2]; 

    if (CharPos = 1) then 
     Result := cGim[4]; 
    end; 

    if (Ch = c7a[0]) then begin 
    Result := c7a[3]; 

    if (CharPos = Len) then 
     Result := c7a[2]; 

    if (CharPos = 1) then 
     Result := c7a[4]; 
    end; 

    if (Ch = c5a[0]) then begin 
    Result := c5a[3]; 

    if (CharPos = Len) then 
     Result := c5a[2]; 

    if (CharPos = 1) then 
     Result := c5a[4]; 
    end; 

    if (Ch = cDal[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cDal[2] 
    end; 

    if (Ch = cThal[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cThal[2] 
    end; 

    if (Ch = cRa[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cRa[2] 
    end; 

    if (Ch = cZa[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cZa[2] 
    end; 

    if (Ch = cSin[0]) then begin 
    Result := cSin[3]; 

    if (CharPos = Len) then 
     Result := cSin[2]; 

    if (CharPos = 1) then 
     Result := cSin[4]; 
    end; 

    if (Ch = cShin[0]) then begin 
    Result := cShin[3]; 

    if (CharPos = Len) then 
     Result := cShin[2]; 

    if (CharPos = 1) then 
     Result := cShin[4]; 
    end; 

    if (Ch = cSad[0]) then begin 
    Result := cSad[3]; 

    if (CharPos = Len) then 
     Result := cSad[2]; 

    if (CharPos = 1) then 
     Result := cSad[4]; 
    end; 

    if (Ch = cDad[0]) then begin 
    Result := cDad[3]; 

    if (CharPos = Len) then 
     Result := cDad[2]; 

    if (CharPos = 1) then 
     Result := cDad[4]; 
    end; 

    if (Ch = c6a[0]) then begin 
    Result := c6a[3]; 

    if (CharPos = Len) then 
     Result := c6a[2]; 

    if (CharPos = 1) then 
     Result := c6a[4]; 
    end; 

    if (Ch = c6_a[0]) then begin 
    Result := c6_a[3]; 

    if (CharPos = Len) then 
     Result := c6_a[2]; 

    if (CharPos = 1) then 
     Result := c6_a[4]; 
    end; 

    if (Ch = cAyn[0]) then begin 
    Result := cAyn[3]; 

    if (CharPos = Len) then 
     Result := cAyn[2]; 

    if (CharPos = 1) then 
     Result := cAyn[4]; 
    end; 

    if (Ch = cGayn[0]) then begin 
    Result := cGayn[3]; 

    if (CharPos = Len) then 
     Result := cGayn[2]; 

    if (CharPos = 1) then 
     Result := cGayn[4]; 
    end; 

    if (Ch = cFa[0]) then begin 
    Result := cFa[3]; 

    if (CharPos = Len) then 
     Result := cFa[2]; 

    if (CharPos = 1) then 
     Result := cFa[4]; 
    end; 

    if (Ch = cQaf[0]) then begin 
    Result := cQaf[3]; 

    if (CharPos = Len) then 
     Result := cQaf[2]; 

    if (CharPos = 1) then 
     Result := cQaf[4]; 
    end; 

    if (Ch = cKaf[0]) then begin 
    Result := cKaf[3]; 

    if (CharPos = Len) then 
     Result := cKaf[2]; 

    if (CharPos = 1) then 
     Result := cKaf[4]; 
    end; 

    if (Ch = cLam[0]) then begin 
    Result := cLam[3]; 

    if (CharPos = Len) then 
     Result := cLam[2]; 

    if (CharPos = 1) then 
     Result := cLam[4]; 
    end; 

    if (Ch = cMim[0]) then begin 
    Result := cMim[3]; 

    if (CharPos = Len) then 
     Result := cMim[2]; 

    if (CharPos = 1) then 
     Result := cMim[4]; 
    end; 

    if (Ch = cNun[0]) then begin 
    Result := cNun[3]; 

    if (CharPos = Len) then 
     Result := cNun[2]; 

    if (CharPos = 1) then 
     Result := cNun[4]; 
    end; 

    if (Ch = cHa[0]) then begin 
    Result := cHa[3]; 

    if (CharPos = Len) then 
     Result := cHa[2]; 

    if (CharPos = 1) then 
     Result := cHa[4]; 
    end; 

    if (Ch = cWaw[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cWaw[2] 
    end; 

    if (Ch = cYa[0]) then begin 
    Result := cYa[3]; 

    if (CharPos = Len) then 
     Result := cYa[2]; 

    if (CharPos = 1) then 
     Result := cYa[4]; 
    end; 

    if (Ch = cAlifMad[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cAlifMad[2] 
    end; 

    if (Ch = cTaMar[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cTaMar[2] 
    end; 

    if (Ch = cAlifMaq[0]) then begin 
    if (CharPos = 1) then 
     Result := Ch 
    else 
     Result := cAlifMaq[2] 
    end; 
end; 

Использование/вывода следующим образом:

procedure TfMain.btn2Click(Sender: TObject); 
const 
    cMiddle = 'يبداء'; 
    cBeginning = 'بداء'; 
    cEnd1  = 'ألعاب'; 
    cEnd2  = 'سحب'; 
begin 
    ShowMessage(IntToHex(Ord(_GetArabicChar(cMiddle, 2)), 4));   // return FE92 
    ShowMessage(IntToHex(Ord(_GetArabicChar(cBeginning, 1)), 4));   // return FE91 
    ShowMessage(IntToHex(Ord(_GetArabicChar(cEnd2, Length((cEnd2)))), 4));// return FE90 
    ShowMessage(IntToHex(Ord(_GetArabicChar(cEnd1, Length((cEnd1)))), 4));// return 0628 
end;