-
Notifications
You must be signed in to change notification settings - Fork 242
RTL (right-to-left) support #459
Comments
Seems the current version doesn't support the possibility. private const int SC_TECHNOLOGY_DEFAULT = 0;
private const int SC_TECHNOLOGY_DIRECTWRITE = 1;
private const int SC_TECHNOLOGY_DIRECTWRITERETAIN = 2;
private const int SC_TECHNOLOGY_DIRECTWRITEDC = 3;
private const int SC_BIDIRECTIONAL_DISABLED = 0;
private const int SC_BIDIRECTIONAL_L2R = 1;
private const int SC_BIDIRECTIONAL_R2L = 2;
private const int SCI_GETBIDIRECTIONAL = 2708;
private const int SCI_SETBIDIRECTIONAL = 2709; The actual code: // set the technology to direct write..
scintilla.Technology = Technology.DirectWrite;
// command the Scintilla to go the right-to-left mode..
scintilla.DirectMessage(SCI_SETBIDIRECTIONAL, new IntPtr(SC_BIDIRECTIONAL_R2L), IntPtr.Zero); |
Hi @VPKSoft, now that your latest unofficial build has an updated SciLexer dll, I was wondering if it would be possible to add support for RTL text? |
Not without more debugging it seems: /// <summary>
/// Gets or sets a value indicating whether control's elements are aligned to support locales using right-to-left fonts.
/// </summary>
/// <value>The right to left.</value>
[Category("Appearance")]
[Description("Indicates whether the component should drawn right-to-left for RTL languages.")]
public override RightToLeft RightToLeft
{
get => base.RightToLeft;
set
{
if (value != base.RightToLeft)
{
switch (value)
{
case RightToLeft.Yes:
DirectMessage(NativeMethods.SCI_SETBIDIRECTIONAL, new IntPtr(NativeMethods.SC_BIDIRECTIONAL_R2L));
break;
case RightToLeft.No:
DirectMessage(NativeMethods.SCI_SETBIDIRECTIONAL, new IntPtr(NativeMethods.SC_BIDIRECTIONAL_L2R));
break;
case RightToLeft.Inherit:
if (this.Parent?.RightToLeft == RightToLeft.Yes)
{
DirectMessage(NativeMethods.SCI_SETBIDIRECTIONAL, new IntPtr(NativeMethods.SC_BIDIRECTIONAL_R2L));
}
if (this.Parent?.RightToLeft == RightToLeft.No)
{
DirectMessage(NativeMethods.SCI_SETBIDIRECTIONAL, new IntPtr(NativeMethods.SC_BIDIRECTIONAL_L2R));
}
break;
}
base.RightToLeft = value;
}
}
} I'll probably have time in the next week or so... See also the documentation 👍 |
The System.AccessViolationException seems to come from messing with Control.RightToLeft. I was able to get the code below to correctly call SCI_SETBIDIRECTIONAL (as you can verify by calling SCI_GETBIDIRECTIONAL afterwards and it should return SC_BIDIRECTIONAL_R2L or SC_BIDIRECTIONAL_L2R). Note that from the documentation, SCI_SETTECHNOLOGY must first be set to one of SC_TECHNOLOGY_DIRECTWRITE, SC_TECHNOLOGY_DIRECTWRITEDC, or SC_TECHNOLOGY_DIRECTWRITERETAIN. While the code below runs, correctly sets the properties and doesn't throw any exceptions, it still shows the text as left-to-right. @VPKSoft any ideas?
|
The scrollbar visibility issue can be fixed by setting the following as per #10:
I also posted this issue in the Scintilla bug tracker to see if we can get some extra help: https://sourceforge.net/p/scintilla/bugs/2233/ |
@VPKSoft we got a response in the Scintilla bug tracker. First off, the Scintilla feature for bidirectional text does not right align the text like you would expect in a WinForms TextBox control. Instead it changes the behvior of the caret when the arrow keys are used when there is a mixture of left-to-right and right-to-left text like in the string "hello world in Hebrew: שלום עולם!". There are 3 different settings:
See this quote from the Scintilla issue tracker: So we should probably not call the property LeftToRight and should probably have something like this (and you would only want it to really be set to either Disabled or LeftToRight):
Now to get the text to right justify as it does in NotePad++, it was suggested to look at WS_EX_LAYOUTRTL. I checked the NotePad++ source and it indeed uses WS_EX_LAYOUTRTL, but I was unable to get the text to right justify and it seemed to instead just mess up the ScintillaNET control border. Here is what I have so far by looking at the NotePad++ code. Hopefully you have some ideas as to why this isn't working correctly.
|
after a bit more testing WS_EX_LAYOUTRTL will work and text will be right aligned when DirectWrite is not enabled, however it still messes up the border of the ScintillaNET control. The question is how can we get text right aligned when DirectWrite is enabled? I did find this link which may be of interest: https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_reading_direction |
Interesting and thank you for making the Scintilla ticket. I'll try to spare some time in the weekend to look into this. |
The border appearance is actually not an issue, it just looks weird with the default border style. You can't see it in your example because you have the control docked with DockStyle.Fill. The default border style is BorderStyle.Fixed3D and it looks weird reversed but it is not really an issue. If you used another border style like BorderStyle.FixedSingle or BorderStyle.None then it looks fine. In order to have true right-to-left support you would need both the bidirectional functionality where the keyboard keys type according to the bidi algorithm as well as right-aligned text. The easiest way to test this is with a WinForms TextBox control with RightToLeft enabled. You would also need to have some text that has right-to-left characters in it like Hebrew or Arabic. When there are right-to-left characters mixed in with left-to-right characters, the cursor position when you press the arrow keys or delete/backspace behaves differently than you would expect. I don't really understand how it all works but I suspect people who type on an Arabic keyboard are quite familiar with it. What NotePad++ has (using WS_EX_LAYOUTRTL) is just a right-to-left reading layout, but I suspect for someone who actually uses a right-to-left language, typing in it would be quite hard because it does not have bidirectional support. Instead this just makes it easier to read Arabic or Hebrew text. So for what we can currently acheive with the Scintilla control there are two options:
Unfortunately we cannot currently have both of those since WS_EX_LAYOUTRTL is incompatible with DirectWrite. There is a third option but it is not currently completed and potentially has been abandoned since the developer who implemented the bidirectional functionality in the Scintilla control ran out of time. With respect to DirectWrite, you asked if there was a specific need for it. I see two advantages
but with DirectWrite enabled, you can see the characters correctly in a left-to-right layout and they aren't as blurry and thick: I think DirectWrite handles fallback fonts a lot better than the default technology (GDI) which is why it seems to have much better support for rendering characters. Also see this bug I logged where Windows 7 and 8.1 couldn't render certain characters at all and instead showed them as white space when the default technology was used. Windows 10 probably has better fallback font support which is why it was able to render the characters. But with DirectWrite enabled, the characters rendered correctly on Windows 7/8.1 and 10. https://sourceforge.net/p/scintilla/bugs/2230/ So for the changes to ScintillaNET, I would recommend having two separate properties. One to change reading direction to acheive similar functionality to NotePad++ and the order to get bidirectional keyboard support. They both have their own advantages. Since there are two different properties, I am not sure it makes sense to use the RightToLeft name. Maybe property names like RightToLeftReadingLayout and BiDirectionality would be good property names. |
Okay - this is going to be a bit more difficult than I thought when suggesting this few years ago 🤔 I'd rather not touch the Scintilla core code so I think the third option is off the table. Not sure if a keyboard hack would work - i.e. through WndProc or such for the typing. |
I think the best we can do for now is to present the two RTL half measures and let the user decide which one they want to use based on their needs and which technologies they are using. I see big advantages to using DirectWrite (only compatible on Windows Vista and later) for its better character rendering. I am using .NET Framework for my development so DirectWrite is compatible, however if you are using .NET 5 and trying to make it cross platform then DirectWrite would not be an option whereas maybe WS_EX_LAYOUTRTL would work cross platform. I’m not sure but maybe .NET 5 may work with certain settings on Windows but not on other OSes, I don’t know if anyone has actually tried running it on a different OS. I didn’t know about DirectWrite before looking into this issue, but because I like it much more than the default rendering technology, it seems that the best international support I can have, at this time, on my ScintillaNet control is DirectWrite + SC_BIDIRECTIONAL_L2R. Best to wait for proper support for SC_BIDIRECTIONAL_R2L and SetReadingDirection to be implemented in Scintilla core if and when someone gets around to it. What do you think about the other, non-related, suggestion of overriding Scintilla.Font to use Scintilla.Styles[Style.Default].Font behind the scenes? I think that would be useful since the casual user won’t read the documentation too in depth and this would make it much easier to change the Font. Of course if someone wants to have multiple font styles then they would need to use Scintilla.Styles. |
I'm fine with the half-measure approach and with the naming you suggested. Overriding the font is also ok. I was wondering if #398, displaying binary data should also be made easier - the method of doing so seems to be quite difficult to find. I'm currently using Scintilla only with Windows and don't know much about the possible QT or GTK implementations. |
I will take a look at #398 in a bit. I have made some proposed changes (found in Scintilla_updated.cs.txt, please go over them by comparing to the original file Scintilla_v3.8.4.cs.txt) with WinMerge or some other diff tool. Please do any refactoring, xml comments etc that you feel is neccessary. I put everything in one file to make it easier to diff. The changes I propose are:
|
It would just be easier to fork the branch and make a PR, but I'll do the diff thing then 🙂 |
Hi, |
Hi,
I was wondering if there is a command to support right-to-left language with the Scintilla control.
There is the possibility to set the:
value, but the text alignment doesn't change the actual text layout. Notepad++ seems to support this feature, but is it custom build or can I issue a direct message to go to full right-to-left support by issuing a command such as:
The text was updated successfully, but these errors were encountered: