Skip to content

Commit f3b4d82

Browse files
committed
Address all of the things, mostly
1 parent f11137a commit f3b4d82

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1888
-1886
lines changed

.github/actions/spelling/expect/expect.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ changelists
179179
charinfo
180180
CHARSETINFO
181181
chh
182-
chonker
183182
chshdng
184183
CHT
185184
CLASSSTRING
@@ -1049,7 +1048,6 @@ mdmerge
10491048
MDs
10501049
MEASUREITEM
10511050
megamix
1052-
Meh
10531051
memallocator
10541052
meme
10551053
MENUCHAR
@@ -1988,6 +1986,7 @@ WCIW
19881986
WCSHELPER
19891987
wcsicmp
19901988
wcsrev
1989+
wcswidth
19911990
wddm
19921991
wddmcon
19931992
WDDMCONSOLECONTEXT
@@ -2142,6 +2141,7 @@ XFORM
21422141
XIn
21432142
XManifest
21442143
XMath
2144+
XNamespace
21452145
xorg
21462146
XPan
21472147
XResource

src/buffer/out/Row.cpp

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ void ROW::ReplaceAttributes(const til::CoordType beginIndex, const til::CoordTyp
566566
void ROW::ReplaceCharacters(til::CoordType columnBegin, til::CoordType width, const std::wstring_view& chars)
567567
try
568568
{
569+
assert(width >= 1 && width <= 2);
569570
WriteHelper h{ *this, columnBegin, _columnCount, chars };
570571
if (!h.IsValid())
571572
{
@@ -634,16 +635,17 @@ catch (...)
634635
throw;
635636
}
636637

637-
[[msvc::forceinline]] void ROW::WriteHelper::ReplaceText() noexcept
638+
void ROW::WriteHelper::ReplaceText() noexcept
638639
{
639640
// This function starts with a fast-pass for ASCII. ASCII is still predominant in technical areas.
640641
//
641642
// We can infer the "end" from the amount of columns we're given (colLimit - colBeg),
642643
// because ASCII is always 1 column wide per character.
643-
const auto len = std::min<size_t>(chars.size(), colLimit - colBeg);
644+
auto len = std::min<size_t>(chars.size(), colLimit - colEnd);
644645
size_t ch = chBeg;
646+
size_t off = 0;
645647

646-
for (size_t off = 0; off < len; ++off)
648+
for (; off < len; ++off)
647649
{
648650
if (chars[off] >= 0x80) [[unlikely]]
649651
{
@@ -660,27 +662,70 @@ catch (...)
660662
charsConsumed = ch - chBeg;
661663
}
662664

663-
[[msvc::forceinline]] void ROW::WriteHelper::_replaceTextUnicode(size_t ch, size_t off) noexcept
665+
void ROW::WriteHelper::_replaceTextUnicode(size_t ch, size_t off) noexcept
664666
{
665667
auto& cwd = CodepointWidthDetector::Singleton();
666668
const auto len = chars.size();
667669

668-
// The non-ASCII character we have encountered may be a combining mark, like "a^" which is then displayed as "â".
669-
// In order to recognize both characters as a single grapheme, we need to back up by 1 ASCII character
670-
// and let MeasureNext() find the next proper grapheme boundary.
671-
if (off != 0)
670+
// Check if the new text joins with the existing contents of the row to form a single grapheme cluster.
671+
if (off == 0)
672672
{
673+
auto colPrev = colBeg;
674+
while (colPrev > 0 && row._uncheckedIsTrailer(--colPrev))
675+
{
676+
}
677+
678+
const auto chPrev = row._uncheckedCharOffset(colPrev);
679+
const std::wstring_view charsPrev{ row._chars.data() + chPrev, ch - chPrev };
680+
681+
GraphemeState state;
682+
cwd.GraphemeNext(state, charsPrev);
683+
cwd.GraphemeNext(state, chars);
684+
685+
if (state.len > 0)
686+
{
687+
colBegDirty = colPrev;
688+
colEnd = colPrev;
689+
690+
const auto colEndNew = gsl::narrow_cast<uint16_t>(colEnd + state.width);
691+
if (colEndNew > colLimit)
692+
{
693+
colEndDirty = colLimit;
694+
charsConsumed = ch - chBeg;
695+
return;
696+
}
697+
698+
// Fill our char-offset buffer with 1 entry containing the mapping from the
699+
// current column (colEnd) to the start of the glyph in the string (ch)...
700+
til::at(row._charOffsets, colEnd++) = gsl::narrow_cast<uint16_t>(chPrev);
701+
// ...followed by 0-N entries containing an indication that the
702+
// columns are just a wide-glyph extension of the preceding one.
703+
while (colEnd < colEndNew)
704+
{
705+
til::at(row._charOffsets, colEnd++) = gsl::narrow_cast<uint16_t>(chPrev | CharOffsetsTrailer);
706+
}
707+
708+
ch += state.len;
709+
off += state.len;
710+
}
711+
}
712+
else
713+
{
714+
// The non-ASCII character we have encountered may be a combining mark, like "a^" which is then displayed as "â".
715+
// In order to recognize both characters as a single grapheme, we need to back up by 1 ASCII character
716+
// and let MeasureNext() find the next proper grapheme boundary.
673717
--colEnd;
674718
--ch;
675719
--off;
676720
}
677721

722+
GraphemeState state{ .beg = chars.data() + off };
723+
678724
while (off < len)
679725
{
680-
int width;
681-
const auto end = cwd.GraphemeNext(chars, off, &width);
726+
cwd.GraphemeNext(state, chars);
682727

683-
const auto colEndNew = gsl::narrow_cast<uint16_t>(colEnd + width);
728+
const auto colEndNew = gsl::narrow_cast<uint16_t>(colEnd + state.width);
684729
if (colEndNew > colLimit)
685730
{
686731
colEndDirty = colLimit;
@@ -698,8 +743,8 @@ catch (...)
698743
til::at(row._charOffsets, colEnd++) = gsl::narrow_cast<uint16_t>(ch | CharOffsetsTrailer);
699744
}
700745

701-
ch += end - off;
702-
off = end;
746+
ch += state.len;
747+
off += state.len;
703748
}
704749

705750
colEndDirty = colEnd;
@@ -804,7 +849,7 @@ catch (...)
804849
}
805850
#pragma warning(pop)
806851

807-
[[msvc::forceinline]] void ROW::WriteHelper::Finish()
852+
void ROW::WriteHelper::Finish()
808853
{
809854
colEndDirty = row._adjustForward(colEndDirty);
810855

src/buffer/out/textBuffer.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,18 @@ void TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute
409409
size_t TextBuffer::GraphemeNext(const std::wstring_view& chars, size_t position) noexcept
410410
{
411411
auto& cwd = CodepointWidthDetector::Singleton();
412-
return cwd.GraphemeNext(chars, position, nullptr);
412+
GraphemeState state{ .beg = chars.data() + position };
413+
cwd.GraphemeNext(state, chars);
414+
return position + state.len;
413415
}
414416

415417
// It's the counterpart to GraphemeNext. See GraphemeNext.
416418
size_t TextBuffer::GraphemePrev(const std::wstring_view& chars, size_t position) noexcept
417419
{
418420
auto& cwd = CodepointWidthDetector::Singleton();
419-
return cwd.GraphemePrev(chars, position, nullptr);
421+
GraphemeState state{ .beg = chars.data() + position };
422+
cwd.GraphemePrev(state, chars);
423+
return position - state.len;
420424
}
421425

422426
// Ever wondered how much space a piece of text needs before inserting it? This function will tell you!
@@ -465,11 +469,13 @@ size_t TextBuffer::FitTextIntoColumns(const std::wstring_view& chars, til::Coord
465469
col--;
466470
}
467471

472+
GraphemeState state{ .beg = chars.data() + dist };
473+
468474
while (dist < len)
469475
{
470-
int width;
471-
dist = cwd.GraphemeNext(chars, dist, &width);
472-
col += width;
476+
cwd.GraphemeNext(state, chars);
477+
dist += state.len;
478+
col += state.width;
473479

474480
// If we ran out of columns, we need to always return `columnLimit` and not `cols`,
475481
// because if we tried inserting a wide glyph into just 1 remaining column it will

src/cascadia/TerminalApp/AppLogic.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33

44
#include "pch.h"
55
#include "AppLogic.h"
6-
#include "../inc/WindowingBehavior.h"
7-
#include "AppLogic.g.cpp"
8-
#include "FindTargetWindowResult.g.cpp"
9-
#include "SettingsLoadEventArgs.h"
106

117
#include <LibraryResources.h>
128
#include <WtExeUtils.h>
139
#include <wil/token_helpers.h>
1410

11+
#include "SettingsLoadEventArgs.h"
12+
#include "../../types/inc/CodepointWidthDetector.hpp"
1513
#include "../../types/inc/utils.hpp"
14+
#include "../inc/WindowingBehavior.h"
15+
16+
#include "AppLogic.g.cpp"
17+
#include "FindTargetWindowResult.g.cpp"
1618

1719
using namespace winrt::Windows::ApplicationModel;
1820
using namespace winrt::Windows::ApplicationModel::DataTransfer;
@@ -433,13 +435,6 @@ namespace winrt::TerminalApp::implementation
433435
}
434436
}
435437

436-
if (initialLoad)
437-
{
438-
// Register for directory change notification.
439-
_RegisterSettingsChange();
440-
return;
441-
}
442-
443438
// Here, we successfully reloaded the settings, and created a new
444439
// TerminalSettings object.
445440

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,11 @@
44

55
#include "pch.h"
66
#include "TerminalPage.h"
7-
#include "TerminalPage.g.cpp"
8-
#include "RenameWindowRequestedArgs.g.cpp"
9-
#include "RequestMoveContentArgs.g.cpp"
10-
#include "RequestReceiveContentArgs.g.cpp"
11-
#include "LaunchPositionRequest.g.cpp"
12-
13-
#include <filesystem>
147

15-
#include <inc/WindowingBehavior.h>
168
#include <LibraryResources.h>
179
#include <TerminalCore/ControlKeyStates.hpp>
1810
#include <til/latch.h>
11+
#include <Utils.h>
1912

2013
#include "../../types/inc/utils.hpp"
2114
#include "App.h"
@@ -24,7 +17,12 @@
2417
#include "SettingsPaneContent.h"
2518
#include "ScratchpadContent.h"
2619
#include "TabRowControl.h"
27-
#include "Utils.h"
20+
21+
#include "TerminalPage.g.cpp"
22+
#include "RenameWindowRequestedArgs.g.cpp"
23+
#include "RequestMoveContentArgs.g.cpp"
24+
#include "RequestReceiveContentArgs.g.cpp"
25+
#include "LaunchPositionRequest.g.cpp"
2826

2927
using namespace winrt;
3028
using namespace winrt::Microsoft::Terminal::Control;
@@ -1211,6 +1209,26 @@ namespace winrt::TerminalApp::implementation
12111209
TerminalSettings settings,
12121210
const bool inheritCursor)
12131211
{
1212+
// The only way to create string references to literals in WinRT is through std::optional. Fun!
1213+
static std::optional<winrt::param::hstring> textMeasurement;
1214+
static const auto textMeasurementInit = [&]() {
1215+
switch (_settings.GlobalSettings().TextMeasurement())
1216+
{
1217+
case TextMeasurement::Graphemes:
1218+
textMeasurement.emplace(L"graphemes");
1219+
break;
1220+
case TextMeasurement::Wcswidth:
1221+
textMeasurement.emplace(L"wcswidth");
1222+
break;
1223+
case TextMeasurement::Console:
1224+
textMeasurement.emplace(L"console");
1225+
break;
1226+
default:
1227+
break;
1228+
}
1229+
return true;
1230+
}();
1231+
12141232
TerminalConnection::ITerminalConnection connection{ nullptr };
12151233

12161234
auto connectionType = profile.ConnectionType();
@@ -1282,6 +1300,11 @@ namespace winrt::TerminalApp::implementation
12821300
}
12831301
}
12841302

1303+
if (textMeasurement)
1304+
{
1305+
valueSet.Insert(L"textMeasurement", Windows::Foundation::PropertyValue::CreateString(*textMeasurement));
1306+
}
1307+
12851308
if (const auto id = settings.SessionId(); id != winrt::guid{})
12861309
{
12871310
valueSet.Insert(L"sessionId", Windows::Foundation::PropertyValue::CreateGuid(id));

src/cascadia/TerminalConnection/ConptyConnection.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "ConptyConnection.h"
66

77
#include <conpty-static.h>
8-
#include <til/string.h>
98
#include <winternl.h>
109

1110
#include "CTerminalHandoff.h"
@@ -259,11 +258,39 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
259258
_cols = unbox_prop_or<uint32_t>(settings, L"initialCols", _cols);
260259
_sessionId = unbox_prop_or<winrt::guid>(settings, L"sessionId", _sessionId);
261260
_environment = settings.TryLookup(L"environment").try_as<Windows::Foundation::Collections::ValueSet>();
262-
_inheritCursor = unbox_prop_or<bool>(settings, L"inheritCursor", _inheritCursor);
263261
_profileGuid = unbox_prop_or<winrt::guid>(settings, L"profileGuid", _profileGuid);
264262

265-
const auto& initialEnvironment{ unbox_prop_or<winrt::hstring>(settings, L"initialEnvironment", L"") };
263+
_flags = PSEUDOCONSOLE_RESIZE_QUIRK;
264+
265+
// If we're using an existing buffer, we want the new connection
266+
// to reuse the existing cursor. When not setting this flag, the
267+
// PseudoConsole sends a clear screen VT code which our renderer
268+
// interprets into making all the previous lines be outside the
269+
// current viewport.
270+
const auto inheritCursor = unbox_prop_or<bool>(settings, L"inheritCursor", false);
271+
if (inheritCursor)
272+
{
273+
_flags |= PSEUDOCONSOLE_INHERIT_CURSOR;
274+
}
275+
276+
const auto textMeasurement = unbox_prop_or<winrt::hstring>(settings, L"textMeasurement", winrt::hstring{});
277+
if (!textMeasurement.empty())
278+
{
279+
if (textMeasurement == L"graphemes")
280+
{
281+
_flags |= PSEUDOCONSOLE_GLYPH_WIDTH_GRAPHEMES;
282+
}
283+
else if (textMeasurement == L"wcswidth")
284+
{
285+
_flags |= PSEUDOCONSOLE_GLYPH_WIDTH_WCSWIDTH;
286+
}
287+
else if (textMeasurement == L"console")
288+
{
289+
_flags |= PSEUDOCONSOLE_GLYPH_WIDTH_CONSOLE;
290+
}
291+
}
266292

293+
const auto& initialEnvironment{ unbox_prop_or<winrt::hstring>(settings, L"initialEnvironment", L"") };
267294
const bool reloadEnvironmentVariables = unbox_prop_or<bool>(settings, L"reloadEnvironmentVariables", false);
268295

269296
if (reloadEnvironmentVariables)
@@ -318,19 +345,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
318345
// handoff from an already-started PTY process.
319346
if (!_inPipe)
320347
{
321-
DWORD flags = PSEUDOCONSOLE_RESIZE_QUIRK;
322-
323-
// If we're using an existing buffer, we want the new connection
324-
// to reuse the existing cursor. When not setting this flag, the
325-
// PseudoConsole sends a clear screen VT code which our renderer
326-
// interprets into making all the previous lines be outside the
327-
// current viewport.
328-
if (_inheritCursor)
329-
{
330-
flags |= PSEUDOCONSOLE_INHERIT_CURSOR;
331-
}
332-
333-
THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(til::unwrap_coord_size(dimensions), flags, &_inPipe, &_outPipe, &_hPC));
348+
THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(til::unwrap_coord_size(dimensions), _flags, &_inPipe, &_outPipe, &_hPC));
334349

335350
if (_initialParentHwnd != 0)
336351
{

src/cascadia/TerminalConnection/ConptyConnection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
9090
til::u8state _u8State{};
9191
std::wstring _u16Str{};
9292
std::array<char, 4096> _buffer{};
93-
bool _inheritCursor{ false };
93+
DWORD _flags{ 0 };
9494

9595
til::env _initialEnv{};
9696
guid _profileGuid{};

0 commit comments

Comments
 (0)