@@ -252,6 +252,8 @@ class ScreenBufferTests
252
252
TEST_METHOD(TestDeferredMainBufferResize);
253
253
254
254
TEST_METHOD(RectangularAreaOperations);
255
+
256
+ TEST_METHOD(DelayedWrapReset);
255
257
};
256
258
257
259
void ScreenBufferTests::SingleAlternateBufferCreationTest()
@@ -6266,48 +6268,55 @@ void ScreenBufferTests::CursorSaveRestore()
6266
6268
VERIFY_SUCCEEDED(si.SetViewportOrigin(true, til::point(0, 0), true));
6267
6269
6268
6270
Log::Comment(L"Restore after save.");
6269
- // Set the cursor position, attributes, and character set.
6271
+ // Set the cursor position, delayed wrap, attributes, and character set.
6270
6272
cursor.SetPosition({ 20, 10 });
6273
+ cursor.DelayEOLWrap();
6271
6274
si.SetAttributes(colorAttrs);
6272
6275
stateMachine.ProcessString(selectGraphicsChars);
6273
6276
// Save state.
6274
6277
stateMachine.ProcessString(saveCursor);
6275
- // Reset the cursor position, attributes, and character set.
6278
+ // Reset the cursor position, delayed wrap, attributes, and character set.
6276
6279
cursor.SetPosition({ 0, 0 });
6277
6280
si.SetAttributes(defaultAttrs);
6278
6281
stateMachine.ProcessString(selectAsciiChars);
6279
6282
// Restore state.
6280
6283
stateMachine.ProcessString(restoreCursor);
6281
- // Verify initial position, colors, and graphic character set.
6284
+ // Verify initial position, delayed wrap, colors, and graphic character set.
6282
6285
VERIFY_ARE_EQUAL(til::point(20, 10), cursor.GetPosition());
6286
+ VERIFY_IS_TRUE(cursor.IsDelayedEOLWrap());
6287
+ cursor.ResetDelayEOLWrap();
6283
6288
VERIFY_ARE_EQUAL(colorAttrs, si.GetAttributes());
6284
6289
stateMachine.ProcessString(asciiText);
6285
6290
VERIFY_IS_TRUE(_ValidateLineContains({ 20, 10 }, graphicText, colorAttrs));
6286
6291
6287
6292
Log::Comment(L"Restore again without save.");
6288
- // Reset the cursor position, attributes, and character set.
6293
+ // Reset the cursor position, delayed wrap, attributes, and character set.
6289
6294
cursor.SetPosition({ 0, 0 });
6290
6295
si.SetAttributes(defaultAttrs);
6291
6296
stateMachine.ProcessString(selectAsciiChars);
6292
6297
// Restore state.
6293
6298
stateMachine.ProcessString(restoreCursor);
6294
- // Verify initial saved position, colors, and graphic character set.
6299
+ // Verify initial saved position, delayed wrap, colors, and graphic character set.
6295
6300
VERIFY_ARE_EQUAL(til::point(20, 10), cursor.GetPosition());
6301
+ VERIFY_IS_TRUE(cursor.IsDelayedEOLWrap());
6302
+ cursor.ResetDelayEOLWrap();
6296
6303
VERIFY_ARE_EQUAL(colorAttrs, si.GetAttributes());
6297
6304
stateMachine.ProcessString(asciiText);
6298
6305
VERIFY_IS_TRUE(_ValidateLineContains({ 20, 10 }, graphicText, colorAttrs));
6299
6306
6300
6307
Log::Comment(L"Restore after reset.");
6301
6308
// Soft reset.
6302
6309
stateMachine.ProcessString(L"\x1b[!p");
6303
- // Set the cursor position, attributes, and character set.
6310
+ // Set the cursor position, delayed wrap, attributes, and character set.
6304
6311
cursor.SetPosition({ 20, 10 });
6312
+ cursor.DelayEOLWrap();
6305
6313
si.SetAttributes(colorAttrs);
6306
6314
stateMachine.ProcessString(selectGraphicsChars);
6307
6315
// Restore state.
6308
6316
stateMachine.ProcessString(restoreCursor);
6309
- // Verify home position, default attributes, and ascii character set.
6317
+ // Verify home position, no delayed wrap, default attributes, and ascii character set.
6310
6318
VERIFY_ARE_EQUAL(til::point(0, 0), cursor.GetPosition());
6319
+ VERIFY_IS_FALSE(cursor.IsDelayedEOLWrap());
6311
6320
VERIFY_ARE_EQUAL(defaultAttrs, si.GetAttributes());
6312
6321
stateMachine.ProcessString(asciiText);
6313
6322
VERIFY_IS_TRUE(_ValidateLineContains(til::point(0, 0), asciiText, defaultAttrs));
@@ -7538,3 +7547,99 @@ void ScreenBufferTests::RectangularAreaOperations()
7538
7547
VERIFY_IS_TRUE(_ValidateLinesContain(targetArea.top, targetArea.bottom, bufferChars, bufferAttr));
7539
7548
VERIFY_IS_TRUE(_ValidateLinesContain(targetArea.right, targetArea.top, targetArea.bottom, bufferChar, bufferAttr));
7540
7549
}
7550
+
7551
+ void ScreenBufferTests::DelayedWrapReset()
7552
+ {
7553
+ BEGIN_TEST_METHOD_PROPERTIES()
7554
+ TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
7555
+ TEST_METHOD_PROPERTY(L"Data:op", L"{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34}")
7556
+ END_TEST_METHOD_PROPERTIES();
7557
+
7558
+ int opIndex;
7559
+ VERIFY_SUCCEEDED(TestData::TryGetValue(L"op", opIndex));
7560
+
7561
+ auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
7562
+ auto& si = gci.GetActiveOutputBuffer().GetActiveBuffer();
7563
+ auto& stateMachine = si.GetStateMachine();
7564
+ const auto width = si.GetTextBuffer().GetSize().Width();
7565
+ const auto halfWidth = width / 2;
7566
+ WI_SetFlag(si.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING);
7567
+ WI_SetFlag(si.OutputMode, DISABLE_NEWLINE_AUTO_RETURN);
7568
+ stateMachine.ProcessString(L"\033[?40h"); // Make sure DECCOLM is allowed
7569
+
7570
+ const auto startRow = 5;
7571
+ const auto startCol = width - 1;
7572
+
7573
+ // The operations below are all those that the DEC STD 070 reference has
7574
+ // documented as needing to reset the Last Column Flag (see page D-13). The
7575
+ // only controls that we haven't included are HT and SUB, because most DEC
7576
+ // terminals did *not* trigger a reset after executing those sequences, and
7577
+ // most modern terminals also seem to have agreed that that is the correct
7578
+ // approach to take.
7579
+ const struct
7580
+ {
7581
+ std::wstring_view name;
7582
+ std::wstring_view sequence;
7583
+ til::point expectedPos = {};
7584
+ bool absolutePos = false;
7585
+ } ops[] = {
7586
+ { L"DECSTBM", L"\033[1;10r", { 0, 0 }, true },
7587
+ { L"DECSWL", L"\033#5" },
7588
+ { L"DECDWL", L"\033#6", { halfWidth - 1, startRow }, true },
7589
+ { L"DECDHL (top)", L"\033#3", { halfWidth - 1, startRow }, true },
7590
+ { L"DECDHL (bottom)", L"\033#4", { halfWidth - 1, startRow }, true },
7591
+ { L"DECCOLM set", L"\033[?3h", { 0, 0 }, true },
7592
+ { L"DECOM set", L"\033[?6h", { 0, 0 }, true },
7593
+ { L"DECCOLM set", L"\033[?3l", { 0, 0 }, true },
7594
+ { L"DECOM reset", L"\033[?6l", { 0, 0 }, true },
7595
+ { L"DECAWM reset", L"\033[?7l" },
7596
+ { L"CUU", L"\033[A", { 0, -1 } },
7597
+ { L"CUD", L"\033[B", { 0, 1 } },
7598
+ { L"CUF", L"\033[C" },
7599
+ { L"CUB", L"\033[D", { -1, 0 } },
7600
+ { L"CUP", L"\033[3;7H", { 6, 2 }, true },
7601
+ { L"HVP", L"\033[3;7f", { 6, 2 }, true },
7602
+ { L"BS", L"\b", { -1, 0 } },
7603
+ { L"LF", L"\n", { 0, 1 } },
7604
+ { L"VT", L"\v", { 0, 1 } },
7605
+ { L"FF", L"\f", { 0, 1 } },
7606
+ { L"CR", L"\r", { 0, startRow }, true },
7607
+ { L"IND", L"\033D", { 0, 1 } },
7608
+ { L"RI", L"\033M", { 0, -1 } },
7609
+ { L"NEL", L"\033E", { 0, startRow + 1 }, true },
7610
+ { L"ECH", L"\033[X" },
7611
+ { L"DCH", L"\033[P" },
7612
+ { L"ICH", L"\033[@" },
7613
+ { L"EL", L"\033[K" },
7614
+ { L"DECSEL", L"\033[?K" },
7615
+ { L"DL", L"\033[M", { 0, startRow }, true },
7616
+ { L"IL", L"\033[L", { 0, startRow }, true },
7617
+ { L"ED", L"\033[J" },
7618
+ { L"ED (all)", L"\033[2J" },
7619
+ { L"ED (scrollback)", L"\033[3J" },
7620
+ { L"DECSED", L"\033[?J" },
7621
+ };
7622
+ const auto& op = gsl::at(ops, opIndex);
7623
+
7624
+ Log::Comment(L"Writing a character at the end of the line should set delayed EOL wrap");
7625
+ const auto startPos = til::point{ startCol, startRow };
7626
+ si.GetTextBuffer().GetCursor().SetPosition(startPos);
7627
+ stateMachine.ProcessCharacter(L'X');
7628
+ {
7629
+ auto& cursor = si.GetTextBuffer().GetCursor();
7630
+ VERIFY_IS_TRUE(cursor.IsDelayedEOLWrap());
7631
+ VERIFY_ARE_EQUAL(startPos, cursor.GetPosition());
7632
+ }
7633
+
7634
+ Log::Comment(NoThrowString().Format(
7635
+ L"Executing a %s control should reset delayed EOL wrap",
7636
+ op.name.data()));
7637
+ const auto expectedPos = op.absolutePos ? op.expectedPos : startPos + op.expectedPos;
7638
+ stateMachine.ProcessString(op.sequence);
7639
+ {
7640
+ auto& cursor = si.GetTextBuffer().GetCursor();
7641
+ const auto actualPos = cursor.GetPosition() - si.GetViewport().Origin();
7642
+ VERIFY_IS_FALSE(cursor.IsDelayedEOLWrap());
7643
+ VERIFY_ARE_EQUAL(expectedPos, actualPos);
7644
+ }
7645
+ }
0 commit comments