Skip to content

Commit 74470b8

Browse files
committed
gh-1065: Continue fullwidth-aware rendering
1 parent d3a73f8 commit 74470b8

8 files changed

Lines changed: 77 additions & 59 deletions

File tree

far/changelog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
--------------------------------------------------------------------------------
2+
drkns 2026-01-21 00:46:34+00:00 - build 6636
3+
4+
1. gh-1065: Continue fullwidth-aware rendering.
5+
16
--------------------------------------------------------------------------------
27
zg 2026-01-18 20:23:30+02:00 - build 6635
38

far/char_width.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,24 @@ namespace
480480

481481
return codepoint_width::wide;
482482
}
483+
484+
[[nodiscard]]
485+
bool is_legacy_rendering()
486+
{
487+
DWORD Mode;
488+
static const auto IsRedirected = !console.GetMode(console.GetOutputHandle(), Mode);
489+
return !IsRedirected && !console.IsVtActive();
490+
}
483491
}
484492

485493
namespace char_width
486494
{
487495
[[nodiscard]]
488496
size_t get(codepoint const Codepoint)
489497
{
498+
if (!is_bmp(Codepoint) && is_legacy_rendering())
499+
return 2; // Classic grid mode, nothing we can do :(
500+
490501
switch (s_FullWidthState)
491502
{
492503
default:

far/filefilterparams.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -478,30 +478,30 @@ WARNING_POP()
478478

479479
const auto MaxMarkSize = 4;
480480

481-
const auto
482-
MarkAmpFix = visual_string_length(Mark) - HiStrlen(Mark),
483-
NameAmpFix = visual_string_length(Name) - HiStrlen(Name);
481+
const auto MarkAmpFix = visual_string_length(Mark) - HiStrlen(Mark);
482+
const auto AlignedMark = fit_to_left(Mark, MaxMarkSize + MarkAmpFix);
484483

485-
return far::format(L"{1:{2}.{2}} {0} {3:{4}.{4}} {0} {5} {6} {0} {7}"sv,
484+
const auto NameAmpFix = visual_string_length(Name) - HiStrlen(Name);
485+
const auto AlignedName = fit_to_left(string(Name), MaxNameSize + NameAmpFix);
486+
487+
return far::format(L"{1} {0} {2} {0} {3} {4} {0} {5}"sv,
486488
BoxSymbols[BS_V1],
487-
Mark,
488-
MaxMarkSize + MarkAmpFix,
489-
Name,
490-
MaxNameSize + NameAmpFix,
489+
AlignedMark,
490+
AlignedName,
491491
AttrStr,
492492
OtherFlags,
493493
Mask
494494
);
495495
}
496496

497497
const auto HotkeyStr = Hotkey? far::format(L"&{}. "sv, Hotkey) : bPanelType? L" "s : L""s;
498-
const auto AmpFix = Hotkey? 1 : visual_string_length(Name) - HiStrlen(Name);
498+
const auto NameAmpFix = Hotkey? 1 : visual_string_length(Name) - HiStrlen(Name);
499+
const auto AlignedName = fit_to_left(string(Name), MaxNameSize + NameAmpFix);
499500

500-
return far::format(L"{1}{2:{3}.{3}} {0} {4} {5} {0} {6}"sv,
501+
return far::format(L"{1}{2} {0} {3} {4} {0} {5}"sv,
501502
BoxSymbols[BS_V1],
502503
HotkeyStr,
503-
Name,
504-
MaxNameSize + AmpFix - HotkeyStr.size(),
504+
AlignedName,
505505
AttrStr,
506506
OtherFlags,
507507
Mask

far/hilight.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,9 +647,21 @@ void HighlightDlgUpdateUserControl(matrix_view<FAR_CHAR_INFO> const& VBufColorEx
647647

648648
if (!Colors.Mark.Mark.empty() && !Colors.Mark.Inherit)
649649
{
650-
Iterator->Char = Colors.Mark.Mark.front();
651-
Iterator->Attributes = BakedColors[ColorIndex].MarkColor;
652-
++Iterator;
650+
for (const auto& Cell: text_to_char_info(Colors.Mark.Mark, Row.size() - 2))
651+
{
652+
const auto Reserved0 = Cell.Reserved0;
653+
const auto Reserved1 = Cell.Reserved1;
654+
const auto RawAttributes = Cell.Attributes.Flags & FCF_RAWATTR_MASK;
655+
656+
Iterator->Char = Cell.Char;
657+
Iterator->Attributes = BakedColors[ColorIndex].MarkColor;
658+
659+
Iterator->Reserved0 = Reserved0;
660+
Iterator->Reserved1 = Reserved1;
661+
Iterator->Attributes.Flags |= RawAttributes;
662+
663+
++Iterator;
664+
}
653665
}
654666

655667
const std::span FileArea(Iterator, Row.end() - 1);

far/interf.cpp

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -868,35 +868,17 @@ static void string_to_cells_full_width_aware(string_view Str, size_t& CharsConsu
868868
if (Char[1])
869869
{
870870
// It's a surrogate pair that occupies one cell only. Here be dragons.
871-
if (console.IsVtActive())
872-
{
873-
std::visit(overload
874-
{
875-
[&](size_t&){},
876-
[&](std::vector<FAR_CHAR_INFO>& Buffer)
877-
{
878-
// Put *one* fake character:
879-
Buffer.back().Char = encoding::replace_char;
880-
// Stash the actual codepoint. The drawing code will restore it from here:
881-
Buffer.back().Reserved1 = Codepoint;
882-
}
883-
}, Cells);
884-
}
885-
else
871+
std::visit(overload
886872
{
887-
// Classic grid mode, nothing we can do :(
888-
// Expect the broken UI
889-
890-
if (get_cells_count() == CellsAvailable)
873+
[&](size_t&){},
874+
[&](std::vector<FAR_CHAR_INFO>& Buffer)
891875
{
892-
// No space left for the trailing char
893-
CharsConsumedNow = 0;
894-
pop_back();
895-
break;
876+
// Put *one* fake character:
877+
Buffer.back().Char = encoding::replace_char;
878+
// Stash the actual codepoint. The drawing code will restore it from here:
879+
Buffer.back().Reserved1 = Codepoint;
896880
}
897-
898-
push_back(Char[1]);
899-
}
881+
}, Cells);
900882
}
901883
else
902884
{
@@ -924,21 +906,24 @@ void chars_to_cells(string_view Str, size_t& CharsConsumed, size_t const CellsAv
924906
#endif
925907
}
926908

927-
size_t Text(string_view Str, size_t const CellsAvailable)
909+
std::vector<FAR_CHAR_INFO> text_to_char_info(string_view Str, size_t CellsAvailable)
928910
{
929-
if (Str.empty())
930-
return 0;
931-
932911
cells Cells;
933-
const auto& Buffer = Cells.emplace<1>();
912+
auto& Buffer = Cells.emplace<1>();
934913

935-
size_t CharsConsumed = 0;
914+
if (Str.empty())
915+
return Buffer;
936916

917+
size_t CharsConsumed = 0;
937918
string_to_cells(Str, CharsConsumed, Cells, CellsAvailable);
919+
return Buffer;
920+
}
938921

922+
size_t Text(string_view Str, size_t const CellsAvailable)
923+
{
924+
auto Buffer = text_to_char_info(Str, CellsAvailable);
939925
Global->ScrBuf->Write(CurX, CurY, Buffer);
940926
CurX += static_cast<int>(Buffer.size());
941-
942927
return Buffer.size();
943928
}
944929

@@ -1692,24 +1677,27 @@ size_t HiStrlen(string_view const Str)
16921677
{
16931678
if (encoding::utf16::is_high_surrogate(Char))
16941679
{
1680+
if (First)
1681+
++Result;
1682+
16951683
First = Char;
16961684
return true;
16971685
}
16981686

16991687
const auto IsLow = encoding::utf16::is_low_surrogate(Char);
1700-
if (!IsLow)
1701-
First.reset();
1688+
if (First && !IsLow)
1689+
++Result;
17021690

17031691
const auto Codepoint = First && IsLow? encoding::utf16::extract_codepoint(*First, Char) : Char;
1704-
17051692
Result += char_width::get(Codepoint);
1693+
1694+
First.reset();
1695+
17061696
return true;
17071697
});
17081698

17091699
if (First)
1710-
{
17111700
++Result;
1712-
}
17131701

17141702
return Result;
17151703
}

far/interf.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ void chars_to_cells(string_view Str, size_t& CharsConsumed, size_t CellsAvailabl
175175
bool is_valid_surrogate_pair(string_view Str);
176176
bool is_valid_surrogate_pair(wchar_t First, wchar_t Second);
177177

178+
std::vector<FAR_CHAR_INFO> text_to_char_info(string_view Str, size_t CellsAvailable);
179+
178180
void Text(point Where, const FarColor& Color, string_view Str);
179181

180182
size_t Text(string_view Str, size_t CellsAvailable);

far/strmix.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ void inplace::pad_right(std::wstring& Str, size_t const CellsAvailable, wchar_t
221221

222222
void inplace::fit_to_left(std::wstring& Str, size_t const CellsAvailable)
223223
{
224-
cut_right(Str, CellsAvailable);
224+
truncate_right(Str, CellsAvailable);
225225
pad_right(Str, CellsAvailable);
226226
}
227227

@@ -238,13 +238,13 @@ void inplace::fit_to_center(std::wstring& Str, size_t const CellsAvailable)
238238
}
239239
else
240240
{
241-
cut_right(Str, CellsAvailable);
241+
truncate_right(Str, CellsAvailable);
242242
}
243243
}
244244

245245
void inplace::fit_to_right(std::wstring& Str, size_t const CellsAvailable)
246246
{
247-
cut_right(Str, CellsAvailable);
247+
truncate_right(Str, CellsAvailable);
248248
pad_left(Str, CellsAvailable);
249249
}
250250

@@ -2039,8 +2039,8 @@ TEST_CASE("strmix.fit")
20392039
{ L"1"sv, 2, L"1 "sv, L"1 "sv, L" 1"sv, },
20402040

20412041
{ L"12345"sv, 0, {}, {}, {}, },
2042-
{ L"12345"sv, 1, L"1"sv, L"1"sv, L"1"sv, },
2043-
{ L"12345"sv, 3, L"123"sv, L"123"sv, L"123"sv, },
2042+
{ L"12345"sv, 1, L""sv, L""sv, L""sv, },
2043+
{ L"12345"sv, 3, L"12…"sv, L"12…"sv, L"12…"sv, },
20442044
{ L"12345"sv, 5, L"12345"sv, L"12345"sv, L"12345"sv, },
20452045
{ L"12345"sv, 7, L"12345 "sv, L" 12345 "sv, L" 12345"sv, },
20462046
};

far/vbuild.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6635
1+
6636

0 commit comments

Comments
 (0)