Repository: microsoft/terminal
File: src/renderer/vt/VtSequences.cpp (C++)

Code before:
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition16Color(const WORD wAttr,
                                                             const bool fIsForeground) noexcept
{
    // Always check using the foreground flags, because the bg flags constants
    //  are a higher byte
    // Foreground sequences are in [30,37] U [90,97]
    // Background sequences are in [40,47] U [100,107]
    // The "dark" sequences are in the first 7 values, the bright sequences in the second set.
    // Note that text brightness and boldness are different in VT. Boldness is
    //      handled by _SetGraphicsBoldness. Here, we can emit either bright or
    //      dark colors. For conhost as a terminal, it can't draw bold
    //      characters, so it displays "bold" as bright, and in fact most
    //      terminals display the bright color when displaying bolded text.
    // By specifying the boldness and brightness separately, we'll make sure the
    //      terminal has an accurate representation of our buffer.
    const int vtIndex = 30 +
                        (fIsForeground ? 0 : 10) +
                        ((WI_IsFlagSet(wAttr, FOREGROUND_INTENSITY)) ? 60 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_RED) ? 1 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_GREEN) ? 2 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_BLUE) ? 4 : 0);

    // An example string with max length would be "\x1b[100m", which has length = 6.
    char buf[6];
    char* end = fmt::format_to(std::begin(buf), FMT_COMPILE("\x1b[{}m"), vtIndex);
    return _Write({ buf, static_cast<std::string_view::size_type>(end - buf) });
}

// Method Description:
// - Formats and writes a sequence to change the current text attributes to an
//      indexed color from the 256-color table.
// Arguments:
// - wAttr: Windows color table index to emit as a VT sequence
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const WORD index,
                                                              const bool fIsForeground) noexcept
{
    // An example string with max length would be "\x1b[38;5;128m", which has length = 11.
    char buf[11];
    char* end = fmt::format_to(std::begin(buf), FMT_COMPILE("\x1b[{};5;{}m"), fIsForeground ? 38 : 48, ::Xterm256ToWindowsIndex(index));
    return _Write({ buf, static_cast<std::string_view::size_type>(end - buf) });
}

// Method Description:
// - Formats and writes a sequence to change the current text attributes to an
//      RGB color.

Review comment (suggestion):
Ideally this is expected. I wonder if we should have more spaces in buffer, just in case the arguments are not as small as we expected.

Code after:
{
    // Always check using the foreground flags, because the bg flags constants
    //  are a higher byte
    // Foreground sequences are in [30,37] U [90,97]
    // Background sequences are in [40,47] U [100,107]
    // The "dark" sequences are in the first 7 values, the bright sequences in the second set.
    // Note that text brightness and boldness are different in VT. Boldness is
    //      handled by _SetGraphicsBoldness. Here, we can emit either bright or
    //      dark colors. For conhost as a terminal, it can't draw bold
    //      characters, so it displays "bold" as bright, and in fact most
    //      terminals display the bright color when displaying bolded text.
    // By specifying the boldness and brightness separately, we'll make sure the
    //      terminal has an accurate representation of our buffer.
    const int vtIndex = 30 +
                        (fIsForeground ? 0 : 10) +
                        ((WI_IsFlagSet(wAttr, FOREGROUND_INTENSITY)) ? 60 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_RED) ? 1 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_GREEN) ? 2 : 0) +
                        (WI_IsFlagSet(wAttr, FOREGROUND_BLUE) ? 4 : 0);

    return _WriteFormatted(FMT_COMPILE("\x1b[{}m"), vtIndex);
}

// Method Description:
// - Formats and writes a sequence to change the current text attributes to an
//      indexed color from the 256-color table.
// Arguments:
// - wAttr: Windows color table index to emit as a VT sequence
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRendition256Color(const WORD index,
                                                              const bool fIsForeground) noexcept
{
    return _WriteFormatted(FMT_COMPILE("\x1b[{}8;5;{}m"), fIsForeground ? '3' : '4', ::Xterm256ToWindowsIndex(index));
}

// Method Description:
// - Formats and writes a sequence to change the current text attributes to an
//      RGB color.
// Arguments:
// - color: The color to emit a VT sequence for
// - fIsForeground: true if we should emit the foreground sequence, false for background
// Return Value:
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
[[nodiscard]] HRESULT VtEngine::_SetGraphicsRenditionRGBColor(const COLORREF color,
                                                              const bool fIsForeground) noexcept
{
    const uint8_t r = GetRValue(color);
    const uint8_t g = GetGValue(color);
    const uint8_t b = GetBValue(color);