e7a1a675af
This PR adds support for the ANSI _doubly underlined_ graphic rendition attribute, which is enabled by the `SGR 21` escape sequence. There was already an `ExtendedAttributes::DoublyUnderlined` flag in the `TextAttribute` class, but I needed to add `SetDoublyUnderlined` and `IsDoublyUnderlined` methods to access that flag, and update the `SetGraphicsRendition` methods of the two dispatchers to set the attribute on receipt of the `SGR 21` sequence. I also had to update the existing `SGR 24` handler to reset _DoublyUnderlined_ in addition to _Underlined_, since they share the same reset sequence. For the rendering, I've added a new grid line type, which essentially just draws an additional line with the same thickness as the regular underline, but slightly below it - I found a gap of around 0.05 "em" between the lines looked best. If there isn't enough space in the cell for that gap, the second line will be clamped to overlap the first, so you then just get a thicker line. If there isn't even enough space below for a thicker line, we move the offset _above_ the first line, but just enough to make it thicker. The only other complication was the update of the `Xterm256Engine` in the VT renderer. As mentioned above, the two underline attributes share the same reset sequence, so to forward that state over conpty we require a slightly more complicated process than with most other attributes (similar to _Bold_ and _Faint_). We first check whether either underline attribute needs to be turned off to send the reset sequence, and then check individually if each of them needs to be turned back on again. ## Validation Steps Performed For testing, I've extended the existing attribute tests in `AdapterTest`, `VTRendererTest`, and `ScreenBufferTests`, to make sure we're covering both the _Underlined_ and _DoublyUnderlined_ attributes. I've also manually tested the `SGR 21` sequence in conhost and Windows Terminal, with a variety of fonts and font sizes, to make sure the rendering was reasonably distinguishable from a single underline. Closes #2916
54 lines
2 KiB
C++
54 lines
2 KiB
C++
/*++
|
|
Copyright (c) Microsoft Corporation
|
|
Licensed under the MIT license.
|
|
--*/
|
|
#pragma once
|
|
|
|
#define FG_ATTRS (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
|
|
#define BG_ATTRS (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
|
|
#define META_ATTRS (COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE | COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_REVERSE_VIDEO | COMMON_LVB_UNDERSCORE)
|
|
|
|
enum class ExtendedAttributes : BYTE
|
|
{
|
|
Normal = 0x00,
|
|
Bold = 0x01,
|
|
Italics = 0x02,
|
|
Blinking = 0x04,
|
|
Invisible = 0x08,
|
|
CrossedOut = 0x10,
|
|
Underlined = 0x20,
|
|
DoublyUnderlined = 0x40,
|
|
Faint = 0x80,
|
|
};
|
|
DEFINE_ENUM_FLAG_OPERATORS(ExtendedAttributes);
|
|
|
|
WORD XtermToWindowsIndex(const size_t index) noexcept;
|
|
WORD Xterm256ToWindowsIndex(const size_t index) noexcept;
|
|
WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground);
|
|
|
|
const WORD WINDOWS_RED_ATTR = FOREGROUND_RED;
|
|
const WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN;
|
|
const WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE;
|
|
const WORD WINDOWS_BRIGHT_ATTR = FOREGROUND_INTENSITY;
|
|
|
|
const WORD XTERM_RED_ATTR = 0x01;
|
|
const WORD XTERM_GREEN_ATTR = 0x02;
|
|
const WORD XTERM_BLUE_ATTR = 0x04;
|
|
const WORD XTERM_BRIGHT_ATTR = 0x08;
|
|
|
|
enum class CursorType : unsigned int
|
|
{
|
|
Legacy = 0x0, // uses the cursor's height value to range from underscore-like to full box
|
|
VerticalBar = 0x1, // A single vertical line, '|'
|
|
Underscore = 0x2, // a single horizontal underscore, smaller that the min height legacy cursor.
|
|
EmptyBox = 0x3, // Just the outline of a full box
|
|
FullBox = 0x4 // a full box, similar to legacy with height=100%
|
|
};
|
|
|
|
// Valid COLORREFs are of the pattern 0x00bbggrr. -1 works as an invalid color,
|
|
// as the highest byte of a valid color is always 0.
|
|
constexpr COLORREF INVALID_COLOR = 0xffffffff;
|
|
|
|
constexpr WORD COLOR_TABLE_SIZE = 16;
|
|
constexpr WORD XTERM_COLOR_TABLE_SIZE = 256;
|