Browse Source

+ adds UTF8 support to RTL

mazen 21 years ago
parent
commit
438509d3d3
1 changed files with 120 additions and 0 deletions
  1. 120 0
      rtl/objpas/utf8bidi.pp

+ 120 - 0
rtl/objpas/utf8bidi.pp

@@ -0,0 +1,120 @@
+{
+Author Mazen NEIFER
+Licence LGPL
+}
+unit UTF8BIDI;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils; 
+
+type
+  TChar = WideChar;
+  TUTF8Char = String[3];
+  TUTF8Str = UTF8String;
+  TDirection=(
+    drNONE,
+    drRTL,
+    drLTR
+  );
+
+procedure insert(aChar:TChar;var uString:TUTF8Str; var CursorPos:Integer);
+
+implementation
+
+function UnicodeToUtf8(aChar:TChar):TUTF8Char;
+var
+  w:Word;
+begin
+  w:= Word(aChar);
+  case w of
+    0..$7f:
+      begin
+        Result[1]:=char(w);
+        SetLength(Result,1);
+      end;
+    $80..$7ff:
+      begin
+        Result[1]:=char($c0 or (w shr 6));
+        Result[2]:=char($80 or (w and $3f));
+        SetLength(Result,2);
+      end;
+    else
+      begin
+        Result[1]:=char($e0 or (w shr 12));
+        Result[2]:=char($80 or ((w shr 6)and $3f));
+        Result[3]:=char($80 or (w and $3f));
+        SetLength(Result,3);
+      end;
+  end;
+end;
+
+procedure insert(aChar:TChar;var uString:TUTF8Str; var CursorPos:Integer);
+var
+{At beginning of the line we don't know which direction, thus the first
+ character usually decides of paragrph direction}
+  dir:TDirection;
+  LeftCursorPos, RightCursorPos, InsertPos:Integer;
+  CharToInsert:TUTF8Char;
+  uLen:Integer;
+begin
+  dir := drNONE;
+  uLen := Length(uString);
+  CharToInsert := UnicodeToUTF8(aChar);
+  LeftCursorPos := 1;
+  RightCursorPos := 1;
+  InsertPos := 1;
+  if(uLen > 0) then
+    repeat
+      case uString[InsertPos] of
+        #32,'{','}','/'://Does not change direction, this is a neutral character;
+          begin
+            if(dir = drLTR) then
+              Inc(RightCursorPos);
+          end;
+        #$d8,#$d9://Arabic
+          begin
+            dir := drRTL;
+            Inc(InsertPos);//Consume control character
+          end;
+      else //Latin
+        begin
+          dir := drLTR;
+          RightCursorPos := LeftCursorPos + 1;
+        end;
+      end;
+      Inc(LeftCursorPos);
+      Inc(InsertPos);
+    until(InsertPos > uLen) or
+         ((dir = drLTR) and (LeftCursorPos > CursorPos)) or
+         ((dir = drRTL) and (RightCursorPos > CursorPos));
+//WriteLn('uLen=',uLen,' InsertPos=',InsertPos,' CursorPos=',CursorPos,' LeftCursorPos=',LeftCursorPos,' RightCursorPos=',RightCursorPos);
+  if(InsertPos > uLen)
+  then begin
+    if(CursorPos > LeftCursorPos) then begin
+      Inc(InsertPos, CursorPos - LeftCursorPos);
+      LeftCursorPos := CursorPos;
+    end;
+    Inc(LeftCursorPos);
+    if(CursorPos > RightCursorPos) then
+      if(dir = drLTR) then
+        RightCursorPos := CursorPos;
+    uString := uString  + StringOfChar(' ', InsertPos - uLen);
+  end;
+//WriteLn('CursorPos=',CursorPos,' LeftCursorPos=',LeftCursorPos,' RightCursorPos=',RightCursorPos);
+  System.insert(CharToInsert, uString,InsertPos);
+  case CharToInsert[1] of
+    #32:
+      CursorPos := LeftCursorPos;
+    #$d8,#$d9:
+      CursorPos := RightCursorPos;
+    else
+      CursorPos := LeftCursorPos;
+  end;
+//WriteLn('InsertPos=',InsertPos,' New CursorPos=',CursorPos);
+end;
+end.
+