Jump to content
kosovali

Problem with BidiMode

Recommended Posts

I want set "123 SAMPLE 456" to a label

But displayed as : " SAMPLE 456 123" 

 

FormCapture.thumb.PNG.9acd7381c5cae1d7093188d91577e633.PNG

 

My Configuration:

Language for Unicode programs : Arabic (Syria)

Form BidiMode : bdRightToLeft

 

Configuration.thumb.png.cec8eb938943f115026b1f6db63192c6.png

 

Can you help me?

 

Share this post


Link to post
 
How should BiDi work?
  • This table shows all the different combinations of BiDiMode with Horizontal Alignment.
  • The table reflects the behavior of Delphi's VCL controls, and uses Delphi's terminology for BiDiMode settings.
  • The example is given with Hebrew words and punctuation marks, in order to give a realistic demonstration of BiDi behavior.
  • For those interested, the first phrase means "Not good...", the second means "Excellent!", and the third means "Alright;".

 

BiDiMode H.Alignment Action Comments Example
bdLeftToRight
(No BiDi support)
None, Left Align text to left Note that the ellipsis (...) is on the wrong side of the text. לא טוב...
Center Center text לא טוב...
Right Align text to right לא טוב...
bdRightToLeft
(Full BiDi support)
 
None, Left Align text to right The exclamation mark (!) is on the correct side of the word.
The alignment is opposite to the direction that is actually specified in H.Alignment.
מצויין!
Center Center text מצויין!
Right Align text to left מצויין!
bdRightToLeftNoAlign,
bdRightToLeftReadingOnly
(Partial BiDi support)
None, Left Align text to left The semicolon (;) is on the correct side of the word.
The alignment is as specified in H.Alignment.
בסדר;
Center Center text בסדר;
Right Align text to right בסדר;

 

source: https://reportman.sourceforge.io/doc/bidi_behavior.html

Edited by emailx45

Share this post


Link to post

H.Alignment  changes does not affected. 

 

LabelCapture.thumb.PNG.dcb70e7b05c633c1df232770f9cd7b0e.PNG

 

Sample output with DrawTextEx WinApi call :

 

procedure TForm1.Button1Click(Sender: TObject);
var
  Text:String;
  lpRect:TRect;
  uFormat:Cardinal;
  Options: Longint;
begin
   Text:= '123 SAMPLE 456';
   lpRect:=Rect(10,10,300,150);
   uFormat:= {DT_LEFT or }DT_EXPANDTABS or DT_NOPREFIX or DT_RTLREADING;   

   DrawTextEx(Canvas.Handle, @Text[1], Length(Text), lpRect, uFormat, nil);
end;

 

 

 

Share this post


Link to post

NOTE:  my MSWindows is in Portuguese-Brazil and I dont have any other language installed

  • Some languages do not follow the left to right reading order commonly found in Western languages, but rather use the right to left reading order for words and the left to right reading order for numbers. These languages are termed bi-directional (BiDi) because of this separation. The most common bi-directional languages are Arabic and Hebrew, although other Middle East languages are also bi-directional.
  • The VCL supports bi-directional localization through the BiDiMode and ParentBiDiMode properties. TApplication has two properties, BiDiKeyboard and NonBiDiKeyboard, that allow you to specify the keyboard layout.

 

 

 

image.pngimage.pngimage.png

 

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  lX_Position: integer;
begin
  {
    Specifies the bidirectional mode for the control.

    Use BiDiMode to enable the control to adjust its appearance and behavior automatically when the application runs in a locale that reads
    ... from right to left instead of left to right. The bidirectional mode controls the reading order for the text, the placement
    ... of the vertical scroll bar, and whether the alignment is changed.

    Alignment does not change for controls that are known to contain number, date, time, or currency values. For example, with data-aware controls,
    ... the alignment does not change for the following field types: ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency, ftBCD, ftDate, ftTime,
    ... ftDateTime, ftAutoInc.
  }
  // ListBox1.BiDiMode := TBiDiMode.bdLeftToRight;
  ListBox1.BiDiMode := TBiDiMode.bdRightToLeft;
  // ListBox1.BiDiMode := TBiDiMode.bdRightToLeftNoAlign;
  // ListBox1.BiDiMode := TBiDiMode.bdRightToLeftReadingOnly;
  //
  ListBox1.Items.Add('مرحبا العالم القاسي');
  ListBox1.Items.Add('هل هم بشر من أي وقت مضى؟');
  //
  Edit1.BiDiMode := TBiDiMode.bdRightToLeft;
  Edit1.Text     := 'مرحبا العالم القاسي';
  //
  Edit1.Text := '123 SAMPLE 456';
  //
  Label1.BiDiMode := Edit1.BiDiMode;
  Label1.Caption  := Edit1.Text;
  //
  lX_Position := (Edit1.Left + Edit1.Width) - Self.Canvas.TextWidth(Edit1.Text);
  //
  Self.Canvas.Font.Orientation := -180 * 10;
  Self.Canvas.Font.Color       := clBlue;
  //
  Self.Canvas.TextOut(lX_Position { x } , 270 { y } , Edit1.Text);


  // Rotation works in tenths of the angle reported, then:  (Angle * 10) = your rotation
  // Horizontal to Right  = (0 * 10)
  // Vertical to Down  = (-90 * 10)
  // Horizontal to Left  = (-180 * 10)
  // Vertical to Up = (90 * 10)

end;

hug

 

Edited by emailx45
  • Like 1

Share this post


Link to post

My 2 cents on this,

 

It is difficult to solve as it VCL is not much of help and OS is not helping too.

To explain this, lets use this code to understand the problem first

procedure TForm10.Button1Click(Sender: TObject);
var
  st: string;
begin
  st := '123 ';
  st := st + ' Sample ';
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + 'عينة';
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + 'عينة';
  st := st + ' Sample ';
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + ' Sample ';
  st := st + 'عينة';
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);
end;

Here the result 

image.thumb.png.73ad2fde034108cb10d921937dc2a321.png

 

Now we can have a glimpse what is going wrong and where

i separated building st to make sure the editors involved in copying and moving the sentences are irrelevant, this is essential.

From the result, you see clearly parsing and switching between words within a string can and does change the string printing output, even within Windows components the drawing behaviour does change, i remember also GDI/+ was doing things differently, but not sure for current versions and Windows 10, and which is which, that is a thing you should test for your self, things gets more ugly and less predictable with symbols.

 

One thing though, i love how Alexander In his HTML Delphi Components include the full parser algorithms to handle switching from RTL words and LTR in the same string, but also the it does fail in few corner cases when some char that steer the the parser in other direction like '.' or a bracket, but my DHTML is expired and old, and i don't expect any perfect algorithm to exist at all, the thing of me having the code for parsing i can change things to fir my need, as these symbols can be chars LTR ranges encapsulating RTL words, i think you are familiar with most popular case with brackets.

Another thing, in the above example you used Arabic numbers "123.." they called Arabic, while the Arabic languages most likely will use Hindu numbers "٠١٢٣٤٥٦٧٨٩", and using those will greatly change the behaviour in different places lets see the different behaviour

procedure TForm10.Button1Click(Sender: TObject);
var
  st: string;
begin
  st := '١٢٣ ';
  st := st + ' Sample ';
  st := st + ' ٤٥٦';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '١٢٣ ';
  st := st + 'عينة';
  st := st + ' ٤٥٦';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '١٢٣ ';
  st := st + 'عينة';
  st := st + ' Sample ';
  st := st + ' ٤٥٦';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '١٢٣ ';
  st := st + ' Sample ';
  st := st + 'عينة';
  st := st + ' ٤٥٦';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);
end;

the result had changed

image.thumb.png.f225d8ed94247e29028c06be0d3198e3.png

Another thing there is special char to control such sentences called Right-to-Left Mark https://en.wikipedia.org/wiki/Right-to-left_mark

You might want play and try to insert it between strings and see the effect in that page there is an example on how to add "!" at right place.

 

That was my 2 cents, and really it depends on you understanding when the problem occur and how to find workaround, as i doubt the existence of a complete fix.

  • Like 1

Share this post


Link to post

I found that adding RLM or ALM after words help building it right, it is not needed everywhere, but i wanted to find a simple rule to follow,

procedure TForm10.Button2Click(Sender: TObject);
const
  ALM=#$061c;
  RLM=#$200F;
var
  st: string;
begin
  st := '123 ';
  st := st + ' Sample ';
  st := st + RLM;
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + 'عينة';
  st := st + RLM;
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + 'عينة';
  st := st + RLM;
  st := st + ' Sample ';
  st := st + RLM;
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

  st := '123 ';
  st := st + ' Sample ';
  st := st + RLM;
  st := st + 'عينة';
  st := st + RLM;
  st := st + ' 456';
  Memo1.Lines.Add(st);
  Memo2.Lines.Add(st);

end;

image.png.5c1973e578424b958a951070dbd7f0da.png

Start there and see if you can build on that, but as i said i am trying things and don't know for sure if this is the right way to do it, if there is a way.

 

And good luck.

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×