2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "TextAttribute.hpp"
|
|
|
|
#include "../../inc/conattrs.hpp"
|
|
|
|
|
|
|
|
bool TextAttribute::IsLegacy() const noexcept
|
|
|
|
{
|
|
|
|
return _foreground.IsLegacy() && _background.IsLegacy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Arguments:
|
|
|
|
// - None
|
|
|
|
// Return Value:
|
|
|
|
// - color that should be displayed as the foreground color
|
|
|
|
COLORREF TextAttribute::CalculateRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
|
|
|
COLORREF defaultFgColor,
|
2019-08-30 00:23:07 +02:00
|
|
|
COLORREF defaultBgColor) const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _IsReverseVideo() ? _GetRgbBackground(colorTable, defaultBgColor) : _GetRgbForeground(colorTable, defaultFgColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Routine Description:
|
|
|
|
// - Calculates rgb background color based off of current color table and active modification attributes
|
|
|
|
// Arguments:
|
|
|
|
// - None
|
|
|
|
// Return Value:
|
|
|
|
// - color that should be displayed as the background color
|
|
|
|
COLORREF TextAttribute::CalculateRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
|
|
|
COLORREF defaultFgColor,
|
2019-08-30 00:23:07 +02:00
|
|
|
COLORREF defaultBgColor) const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _IsReverseVideo() ? _GetRgbForeground(colorTable, defaultFgColor) : _GetRgbBackground(colorTable, defaultBgColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Routine Description:
|
|
|
|
// - gets rgb foreground color, possibly based off of current color table. Does not take active modification
|
|
|
|
// attributes into account
|
|
|
|
// Arguments:
|
|
|
|
// - None
|
|
|
|
// Return Value:
|
|
|
|
// - color that is stored as the foreground color
|
|
|
|
COLORREF TextAttribute::_GetRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
2019-08-30 00:23:07 +02:00
|
|
|
COLORREF defaultColor) const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
Add support for passing through extended text attributes, like… (#2917)
## Summary of the Pull Request
Adds support for Italics, Blinking, Invisible, CrossedOut text, THROUGH CONPTY. This does **NOT** add support for those styles to conhost or the terminal.
We will store these "Extended Text Attributes" in a `TextAttribute`. When we go to render a line, we'll see if the state has changed from our previous state, and if so, we'll appropriately toggle that state with VT. Boldness has been moved from a `bool` to a single bit in these flags.
Technically, now that these are stored in the buffer, we only need to make changes to the renderers to be able to support them. That's not being done as a part of this PR however.
## References
See also #2915 and #2916, which are some follow-up tasks from this fix. I thought them too risky for 20H1.
## PR Checklist
* [x] Closes #2554
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
<hr>
* store text with extended attributes too
* Plumb attributes through all the renderers
* parse extended attrs, though we're not renderering them right
* Render these states correctly
* Add a very extensive test
* Cleanup for PR
* a block of PR feedback
* add 512 test cases
* Fix the build
* Fix @carlos-zamora's suggestions
* @miniksa's PR feedback
2019-10-04 22:53:54 +02:00
|
|
|
return _foreground.GetColor(colorTable, defaultColor, IsBold());
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Routine Description:
|
|
|
|
// - gets rgb background color, possibly based off of current color table. Does not take active modification
|
|
|
|
// attributes into account
|
|
|
|
// Arguments:
|
|
|
|
// - None
|
|
|
|
// Return Value:
|
|
|
|
// - color that is stored as the background color
|
|
|
|
COLORREF TextAttribute::_GetRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
2019-08-30 00:23:07 +02:00
|
|
|
COLORREF defaultColor) const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return _background.GetColor(colorTable, defaultColor, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetMetaAttributes(const WORD wMeta) noexcept
|
|
|
|
{
|
|
|
|
WI_UpdateFlagsInMask(_wAttrLegacy, META_ATTRS, wMeta);
|
|
|
|
WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
|
|
|
|
}
|
|
|
|
|
|
|
|
WORD TextAttribute::GetMetaAttributes() const noexcept
|
|
|
|
{
|
|
|
|
WORD wMeta = _wAttrLegacy;
|
|
|
|
WI_ClearAllFlags(wMeta, FG_ATTRS);
|
|
|
|
WI_ClearAllFlags(wMeta, BG_ATTRS);
|
|
|
|
WI_ClearAllFlags(wMeta, COMMON_LVB_SBCSDBCS);
|
|
|
|
return wMeta;
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void TextAttribute::SetForeground(const COLORREF rgbForeground) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_foreground = TextColor(rgbForeground);
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void TextAttribute::SetBackground(const COLORREF rgbBackground) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_background = TextColor(rgbBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetFromLegacy(const WORD wLegacy) noexcept
|
|
|
|
{
|
2019-08-29 22:19:01 +02:00
|
|
|
_wAttrLegacy = gsl::narrow_cast<WORD>(wLegacy & META_ATTRS);
|
2019-05-03 00:29:04 +02:00
|
|
|
WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
|
2019-08-29 22:19:01 +02:00
|
|
|
const BYTE fgIndex = gsl::narrow_cast<BYTE>(wLegacy & FG_ATTRS);
|
|
|
|
const BYTE bgIndex = gsl::narrow_cast<BYTE>(wLegacy & BG_ATTRS) >> 4;
|
2019-05-03 00:29:04 +02:00
|
|
|
_foreground = TextColor(fgIndex);
|
|
|
|
_background = TextColor(bgIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetLegacyAttributes(const WORD attrs,
|
|
|
|
const bool setForeground,
|
|
|
|
const bool setBackground,
|
2019-08-30 00:23:07 +02:00
|
|
|
const bool setMeta) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
if (setForeground)
|
|
|
|
{
|
2019-08-29 21:45:16 +02:00
|
|
|
const BYTE fgIndex = gsl::narrow_cast<BYTE>(attrs & FG_ATTRS);
|
2019-05-03 00:29:04 +02:00
|
|
|
_foreground = TextColor(fgIndex);
|
|
|
|
}
|
|
|
|
if (setBackground)
|
|
|
|
{
|
2019-08-29 21:45:16 +02:00
|
|
|
const BYTE bgIndex = gsl::narrow_cast<BYTE>(attrs & BG_ATTRS) >> 4;
|
2019-05-03 00:29:04 +02:00
|
|
|
_background = TextColor(bgIndex);
|
|
|
|
}
|
|
|
|
if (setMeta)
|
|
|
|
{
|
|
|
|
SetMetaAttributes(attrs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets the foreground and/or background to a particular index in the 256color
|
|
|
|
// table. If either parameter is nullptr, it's ignored.
|
|
|
|
// This method can be used to set the colors to indexes in the range [0, 255],
|
|
|
|
// as opposed to SetLegacyAttributes, which clamps them to [0,15]
|
|
|
|
// Arguments:
|
|
|
|
// - foreground: nullptr if we should ignore this attr, else a pointer to a byte
|
|
|
|
// value to use as an index into the 256-color table.
|
|
|
|
// - background: nullptr if we should ignore this attr, else a pointer to a byte
|
|
|
|
// value to use as an index into the 256-color table.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TextAttribute::SetIndexedAttributes(const std::optional<const BYTE> foreground,
|
|
|
|
const std::optional<const BYTE> background) noexcept
|
|
|
|
{
|
|
|
|
if (foreground)
|
|
|
|
{
|
2019-08-29 20:27:39 +02:00
|
|
|
const BYTE fgIndex = (*foreground) & 0xFF;
|
2019-05-03 00:29:04 +02:00
|
|
|
_foreground = TextColor(fgIndex);
|
|
|
|
}
|
|
|
|
if (background)
|
|
|
|
{
|
2019-08-29 20:27:39 +02:00
|
|
|
const BYTE bgIndex = (*background) & 0xFF;
|
2019-05-03 00:29:04 +02:00
|
|
|
_background = TextColor(bgIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-30 00:23:07 +02:00
|
|
|
void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
if (fIsForeground)
|
|
|
|
{
|
|
|
|
SetForeground(rgbColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetBackground(rgbColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::_IsReverseVideo() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsLeadingByte() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_LEADING_BYTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsTrailingByte() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_LEADING_BYTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsTopHorizontalDisplayed() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsBottomHorizontalDisplayed() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_UNDERSCORE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsLeftVerticalDisplayed() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_LVERTICAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextAttribute::IsRightVerticalDisplayed() const noexcept
|
|
|
|
{
|
|
|
|
return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_RVERTICAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetLeftVerticalDisplayed(const bool isDisplayed) noexcept
|
|
|
|
{
|
|
|
|
WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_LVERTICAL, isDisplayed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetRightVerticalDisplayed(const bool isDisplayed) noexcept
|
|
|
|
{
|
|
|
|
WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_RVERTICAL, isDisplayed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::Embolden() noexcept
|
|
|
|
{
|
|
|
|
_SetBoldness(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::Debolden() noexcept
|
|
|
|
{
|
|
|
|
_SetBoldness(false);
|
|
|
|
}
|
|
|
|
|
Add support for passing through extended text attributes, like… (#2917)
## Summary of the Pull Request
Adds support for Italics, Blinking, Invisible, CrossedOut text, THROUGH CONPTY. This does **NOT** add support for those styles to conhost or the terminal.
We will store these "Extended Text Attributes" in a `TextAttribute`. When we go to render a line, we'll see if the state has changed from our previous state, and if so, we'll appropriately toggle that state with VT. Boldness has been moved from a `bool` to a single bit in these flags.
Technically, now that these are stored in the buffer, we only need to make changes to the renderers to be able to support them. That's not being done as a part of this PR however.
## References
See also #2915 and #2916, which are some follow-up tasks from this fix. I thought them too risky for 20H1.
## PR Checklist
* [x] Closes #2554
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
<hr>
* store text with extended attributes too
* Plumb attributes through all the renderers
* parse extended attrs, though we're not renderering them right
* Render these states correctly
* Add a very extensive test
* Cleanup for PR
* a block of PR feedback
* add 512 test cases
* Fix the build
* Fix @carlos-zamora's suggestions
* @miniksa's PR feedback
2019-10-04 22:53:54 +02:00
|
|
|
void TextAttribute::SetExtendedAttributes(const ExtendedAttributes attrs) noexcept
|
|
|
|
{
|
|
|
|
_extendedAttrs = attrs;
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Routine Description:
|
|
|
|
// - swaps foreground and background color
|
|
|
|
void TextAttribute::Invert() noexcept
|
|
|
|
{
|
|
|
|
WI_ToggleFlag(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::_SetBoldness(const bool isBold) noexcept
|
|
|
|
{
|
Add support for passing through extended text attributes, like… (#2917)
## Summary of the Pull Request
Adds support for Italics, Blinking, Invisible, CrossedOut text, THROUGH CONPTY. This does **NOT** add support for those styles to conhost or the terminal.
We will store these "Extended Text Attributes" in a `TextAttribute`. When we go to render a line, we'll see if the state has changed from our previous state, and if so, we'll appropriately toggle that state with VT. Boldness has been moved from a `bool` to a single bit in these flags.
Technically, now that these are stored in the buffer, we only need to make changes to the renderers to be able to support them. That's not being done as a part of this PR however.
## References
See also #2915 and #2916, which are some follow-up tasks from this fix. I thought them too risky for 20H1.
## PR Checklist
* [x] Closes #2554
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
<hr>
* store text with extended attributes too
* Plumb attributes through all the renderers
* parse extended attrs, though we're not renderering them right
* Render these states correctly
* Add a very extensive test
* Cleanup for PR
* a block of PR feedback
* add 512 test cases
* Fix the build
* Fix @carlos-zamora's suggestions
* @miniksa's PR feedback
2019-10-04 22:53:54 +02:00
|
|
|
WI_UpdateFlag(_extendedAttrs, ExtendedAttributes::Bold, isBold);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetDefaultForeground() noexcept
|
|
|
|
{
|
|
|
|
_foreground = TextColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextAttribute::SetDefaultBackground() noexcept
|
|
|
|
{
|
|
|
|
_background = TextColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2019-05-21 08:15:44 +02:00
|
|
|
// - Returns true if this attribute indicates its foreground is the "default"
|
|
|
|
// foreground. Its _rgbForeground will contain the actual value of the
|
2019-05-03 00:29:04 +02:00
|
|
|
// default foreground. If the default colors are ever changed, this method
|
|
|
|
// should be used to identify attributes with the default fg value, and
|
|
|
|
// update them accordingly.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff this attribute indicates it's the "default" foreground color.
|
|
|
|
bool TextAttribute::ForegroundIsDefault() const noexcept
|
|
|
|
{
|
|
|
|
return _foreground.IsDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2019-05-21 08:15:44 +02:00
|
|
|
// - Returns true if this attribute indicates its background is the "default"
|
|
|
|
// background. Its _rgbBackground will contain the actual value of the
|
2019-05-03 00:29:04 +02:00
|
|
|
// default background. If the default colors are ever changed, this method
|
|
|
|
// should be used to identify attributes with the default bg value, and
|
|
|
|
// update them accordingly.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff this attribute indicates it's the "default" background color.
|
|
|
|
bool TextAttribute::BackgroundIsDefault() const noexcept
|
|
|
|
{
|
|
|
|
return _background.IsDefault();
|
|
|
|
}
|