fix: Auto-detect LTR / RTL in input

This commit is contained in:
rtw1x1
2025-12-31 20:56:02 +00:00
parent 73958b4f62
commit 85763c9f81
2 changed files with 20 additions and 8 deletions

16
extern/include/utf8.h vendored
View File

@@ -337,6 +337,12 @@ static inline ECharDir GetCharDirSmart(const wchar_t* s, int n, int i)
if (ch == L'(' || ch == L')')
return ECharDir::LTR;
// Common punctuation: treat as strong LTR to prevent jumping around in mixed text
// This makes "Hello + اختبار" and "اختبار + Hello" both keep punctuation in place
if (ch == L'+' || ch == L'-' || ch == L'=' || ch == L'*' || ch == L'/' ||
ch == L'<' || ch == L'>' || ch == L'&' || ch == L'|' || ch == L'@' || ch == L'#')
return ECharDir::LTR;
// Percentage sign: attach to numbers (scan nearby for digits/minus/plus)
// Handles: "%20", "20%", "-6%", "%d%%", etc.
if (ch == L'%')
@@ -755,8 +761,9 @@ static inline std::vector<wchar_t> BuildVisualChatMessage(
}
else
{
// Apply BiDi to message based on its content
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, msgHasRTL);
// Apply BiDi to message with auto-detection (don't force RTL)
// Let the BiDi algorithm detect base direction from first strong character
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, false);
visual.insert(visual.end(), msgVisual.begin(), msgVisual.end());
}
visual.push_back(L' ');
@@ -778,8 +785,9 @@ static inline std::vector<wchar_t> BuildVisualChatMessage(
}
else
{
// Apply BiDi to message based on its content
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, msgHasRTL);
// Apply BiDi to message with auto-detection (don't force RTL)
// Let the BiDi algorithm detect base direction from first strong character
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, false);
visual.insert(visual.end(), msgVisual.begin(), msgVisual.end());
}
}

View File

@@ -260,8 +260,9 @@ void CGraphicTextInstance::Update()
// Flush current segment with BiDi before changing color
if (!currentSegment.empty())
{
// Use auto-detection for BiDi (don't force RTL)
std::vector<wchar_t> visual = BuildVisualBidiText_Tagless(
currentSegment.data(), (int)currentSegment.size(), m_computedRTL);
currentSegment.data(), (int)currentSegment.size(), false);
for (size_t j = 0; j < visual.size(); ++j)
{
int w = __DrawCharacter(pFontTexture, visual[j], currentColor);
@@ -277,8 +278,9 @@ void CGraphicTextInstance::Update()
// Flush segment before restoring color
if (!currentSegment.empty())
{
// Use auto-detection for BiDi (don't force RTL)
std::vector<wchar_t> visual = BuildVisualBidiText_Tagless(
currentSegment.data(), (int)currentSegment.size(), m_computedRTL);
currentSegment.data(), (int)currentSegment.size(), false);
for (size_t j = 0; j < visual.size(); ++j)
{
int w = __DrawCharacter(pFontTexture, visual[j], currentColor);
@@ -303,8 +305,9 @@ void CGraphicTextInstance::Update()
// Flush any pending non-hyperlink segment first
if (!currentSegment.empty())
{
// Use auto-detection for BiDi (don't force RTL)
std::vector<wchar_t> visual = BuildVisualBidiText_Tagless(
currentSegment.data(), (int)currentSegment.size(), m_computedRTL);
currentSegment.data(), (int)currentSegment.size(), false);
for (size_t j = 0; j < visual.size(); ++j)
{
int w = __DrawCharacter(pFontTexture, visual[j], currentColor);
@@ -417,8 +420,9 @@ void CGraphicTextInstance::Update()
// Flush any remaining segment
if (!currentSegment.empty())
{
// Use auto-detection for BiDi (don't force RTL)
std::vector<wchar_t> visual = BuildVisualBidiText_Tagless(
currentSegment.data(), (int)currentSegment.size(), m_computedRTL);
currentSegment.data(), (int)currentSegment.size(), false);
for (size_t j = 0; j < visual.size(); ++j)
{
int w = __DrawCharacter(pFontTexture, visual[j], currentColor);