Merge pull request #2607 from microsoft/dev/miniksa/audit-a
Crank up static analysis audit
This commit is contained in:
commit
429af0e6fa
|
@ -1,11 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Console Rules" Description="These rules enforce static analysis on console code." ToolsVersion="15.0">
|
||||
|
||||
<Include Path="cppcorecheckrules.ruleset" Action="Default" />
|
||||
<Include Path="cppcorecheckrules.ruleset" Action="Error" />
|
||||
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
|
||||
<Rule Id="C6001" Action="Error" />
|
||||
<Rule Id="C6011" Action="Error" />
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
|
||||
<Rule Id="C6001" Action="Error" />
|
||||
<Rule Id="C6011" Action="Error" />
|
||||
<!-- We can't do dynamic cast because RTTI is off. -->
|
||||
<!-- RTTI is off because Windows OS policies believe RTTI has too much binary size impact for the value and is less portable than RTTI-off modules. -->
|
||||
<Rule Id="C26466" Action="None" />
|
||||
</Rules>
|
||||
|
||||
|
||||
</RuleSet>
|
||||
|
|
|
@ -46,7 +46,7 @@ void ATTR_ROW::Resize(const size_t newWidth)
|
|||
{
|
||||
// Get the attribute that covers the final column of old width.
|
||||
const auto runPos = FindAttrIndex(_cchRowWidth - 1, nullptr);
|
||||
auto& run = _list[runPos];
|
||||
auto& run = _list.at(runPos);
|
||||
|
||||
// Extend its length by the additional columns we're adding.
|
||||
run.SetLength(run.GetLength() + newWidth - _cchRowWidth);
|
||||
|
@ -60,7 +60,7 @@ void ATTR_ROW::Resize(const size_t newWidth)
|
|||
// Get the attribute that covers the final column of the new width
|
||||
size_t CountOfAttr = 0;
|
||||
const auto runPos = FindAttrIndex(newWidth - 1, &CountOfAttr);
|
||||
auto& run = _list[runPos];
|
||||
auto& run = _list.at(runPos);
|
||||
|
||||
// CountOfAttr was given to us as "how many columns left from this point forward are covered by the returned run"
|
||||
// So if the original run was B5 covering a 5 size OldWidth and we have a NewWidth of 3
|
||||
|
@ -108,7 +108,7 @@ TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column,
|
|||
{
|
||||
THROW_HR_IF(E_INVALIDARG, column >= _cchRowWidth);
|
||||
const auto runPos = FindAttrIndex(column, pApplies);
|
||||
return _list[runPos].GetAttributes();
|
||||
return _list.at(runPos).GetAttributes();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -290,10 +290,10 @@ void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAtt
|
|||
// two elements in our internal list.
|
||||
else if (_list.size() == 2 && newAttrs.at(0).GetLength() == 1)
|
||||
{
|
||||
auto left = _list.begin();
|
||||
const auto left = _list.begin();
|
||||
if (iStart == left->GetLength() && NewAttr == left->GetAttributes())
|
||||
{
|
||||
auto right = left + 1;
|
||||
const auto right = left + 1;
|
||||
left->IncrementLength();
|
||||
right->DecrementLength();
|
||||
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
#include "AttrRowIterator.hpp"
|
||||
#include "AttrRow.hpp"
|
||||
|
||||
AttrRowIterator AttrRowIterator::CreateEndIterator(const ATTR_ROW* const attrRow)
|
||||
AttrRowIterator AttrRowIterator::CreateEndIterator(const ATTR_ROW* const attrRow) noexcept
|
||||
{
|
||||
AttrRowIterator it{ attrRow };
|
||||
it._setToEnd();
|
||||
return it;
|
||||
}
|
||||
|
||||
AttrRowIterator::AttrRowIterator(const ATTR_ROW* const attrRow) :
|
||||
AttrRowIterator::AttrRowIterator(const ATTR_ROW* const attrRow) noexcept :
|
||||
_pAttrRow{ attrRow },
|
||||
_run{ attrRow->_list.cbegin() },
|
||||
_currentAttributeIndex{ 0 }
|
||||
{
|
||||
}
|
||||
|
||||
AttrRowIterator::operator bool() const noexcept
|
||||
AttrRowIterator::operator bool() const
|
||||
{
|
||||
return _run < _pAttrRow->_list.cend();
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ void AttrRowIterator::_decrement(size_t count)
|
|||
|
||||
// Routine Description:
|
||||
// - sets fields on the iterator to describe the end() state of the ATTR_ROW
|
||||
void AttrRowIterator::_setToEnd()
|
||||
void AttrRowIterator::_setToEnd() noexcept
|
||||
{
|
||||
_run = _pAttrRow->_list.cend();
|
||||
_currentAttributeIndex = 0;
|
||||
|
|
|
@ -29,11 +29,11 @@ public:
|
|||
using pointer = TextAttribute*;
|
||||
using reference = TextAttribute&;
|
||||
|
||||
static AttrRowIterator CreateEndIterator(const ATTR_ROW* const attrRow);
|
||||
static AttrRowIterator CreateEndIterator(const ATTR_ROW* const attrRow) noexcept;
|
||||
|
||||
AttrRowIterator(const ATTR_ROW* const attrRow);
|
||||
AttrRowIterator(const ATTR_ROW* const attrRow) noexcept;
|
||||
|
||||
operator bool() const noexcept;
|
||||
operator bool() const;
|
||||
|
||||
bool operator==(const AttrRowIterator& it) const;
|
||||
bool operator!=(const AttrRowIterator& it) const;
|
||||
|
@ -57,5 +57,5 @@ private:
|
|||
|
||||
void _increment(size_t count);
|
||||
void _decrement(size_t count);
|
||||
void _setToEnd();
|
||||
void _setToEnd() noexcept;
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ size_t CharRow::size() const noexcept
|
|||
// - sRowWidth - The width of the row.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CharRow::Reset()
|
||||
void CharRow::Reset() noexcept
|
||||
{
|
||||
for (auto& cell : _data)
|
||||
{
|
||||
|
@ -209,7 +209,7 @@ const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
|
|||
// Note: will throw exception if column is out of bounds
|
||||
DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
|
||||
{
|
||||
return const_cast<DbcsAttribute&>(static_cast<const CharRow* const>(this)->DbcsAttrAt(column));
|
||||
return _data.at(column).DbcsAttr();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -250,29 +250,6 @@ CharRow::reference CharRow::GlyphAt(const size_t column)
|
|||
return { *this, column };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - returns string containing text data exactly how it's stored internally, including doubling of
|
||||
// leading/trailing cells.
|
||||
// Arguments:
|
||||
// - none
|
||||
// Return Value:
|
||||
// - text stored in char row
|
||||
// - Note: will throw exception if out of memory
|
||||
std::wstring CharRow::GetTextRaw() const
|
||||
{
|
||||
std::wstring wstr;
|
||||
wstr.reserve(_data.size());
|
||||
for (size_t i = 0; i < _data.size(); ++i)
|
||||
{
|
||||
auto glyph = GlyphAt(i);
|
||||
for (auto it = glyph.begin(); it != glyph.end(); ++it)
|
||||
{
|
||||
wstr.push_back(*it);
|
||||
}
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
|
||||
std::wstring CharRow::GetText() const
|
||||
{
|
||||
std::wstring wstr;
|
||||
|
@ -280,24 +257,24 @@ std::wstring CharRow::GetText() const
|
|||
|
||||
for (size_t i = 0; i < _data.size(); ++i)
|
||||
{
|
||||
auto glyph = GlyphAt(i);
|
||||
const auto glyph = GlyphAt(i);
|
||||
if (!DbcsAttrAt(i).IsTrailing())
|
||||
{
|
||||
for (auto it = glyph.begin(); it != glyph.end(); ++it)
|
||||
for (const auto wch : glyph)
|
||||
{
|
||||
wstr.push_back(*it);
|
||||
wstr.push_back(wch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
|
||||
UnicodeStorage& CharRow::GetUnicodeStorage()
|
||||
UnicodeStorage& CharRow::GetUnicodeStorage() noexcept
|
||||
{
|
||||
return _pParent->GetUnicodeStorage();
|
||||
}
|
||||
|
||||
const UnicodeStorage& CharRow::GetUnicodeStorage() const
|
||||
const UnicodeStorage& CharRow::GetUnicodeStorage() const noexcept
|
||||
{
|
||||
return _pParent->GetUnicodeStorage();
|
||||
}
|
||||
|
@ -308,7 +285,7 @@ const UnicodeStorage& CharRow::GetUnicodeStorage() const
|
|||
// - column - the column to generate the key for
|
||||
// Return Value:
|
||||
// - the COORD key for data access from UnicodeStorage for the column
|
||||
COORD CharRow::GetStorageKey(const size_t column) const
|
||||
COORD CharRow::GetStorageKey(const size_t column) const noexcept
|
||||
{
|
||||
return { gsl::narrow<SHORT>(column), _pParent->GetId() };
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
void SetDoubleBytePadded(const bool doubleBytePadded) noexcept;
|
||||
bool WasDoubleBytePadded() const noexcept;
|
||||
size_t size() const noexcept;
|
||||
void Reset();
|
||||
void Reset() noexcept;
|
||||
[[nodiscard]] HRESULT Resize(const size_t newSize) noexcept;
|
||||
size_t MeasureLeft() const;
|
||||
size_t MeasureRight() const noexcept;
|
||||
|
@ -64,9 +64,6 @@ public:
|
|||
void ClearGlyph(const size_t column);
|
||||
std::wstring GetText() const;
|
||||
|
||||
// other functions implemented at the template class level
|
||||
std::wstring GetTextRaw() const;
|
||||
|
||||
// working with glyphs
|
||||
const reference GlyphAt(const size_t column) const;
|
||||
reference GlyphAt(const size_t column);
|
||||
|
@ -78,9 +75,9 @@ public:
|
|||
iterator end() noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
UnicodeStorage& GetUnicodeStorage();
|
||||
const UnicodeStorage& GetUnicodeStorage() const;
|
||||
COORD GetStorageKey(const size_t column) const;
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
COORD GetStorageKey(const size_t column) const noexcept;
|
||||
|
||||
void UpdateParent(ROW* const pParent) noexcept;
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
// default glyph value, used for reseting the character data portion of a cell
|
||||
static constexpr wchar_t DefaultValue = UNICODE_SPACE;
|
||||
|
||||
CharRowCell::CharRowCell() :
|
||||
CharRowCell::CharRowCell() noexcept :
|
||||
_wch{ DefaultValue },
|
||||
_attr{}
|
||||
{
|
||||
}
|
||||
|
||||
CharRowCell::CharRowCell(const wchar_t wch, const DbcsAttribute attr) :
|
||||
CharRowCell::CharRowCell(const wchar_t wch, const DbcsAttribute attr) noexcept :
|
||||
_wch{ wch },
|
||||
_attr{ attr }
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ CharRowCell::CharRowCell(const wchar_t wch, const DbcsAttribute attr) :
|
|||
|
||||
// Routine Description:
|
||||
// - "erases" the glyph. really sets it back to the default "empty" value
|
||||
void CharRowCell::EraseChars()
|
||||
void CharRowCell::EraseChars() noexcept
|
||||
{
|
||||
if (_attr.IsGlyphStored())
|
||||
{
|
||||
|
|
|
@ -27,10 +27,10 @@ Author(s):
|
|||
class CharRowCell final
|
||||
{
|
||||
public:
|
||||
CharRowCell();
|
||||
CharRowCell(const wchar_t wch, const DbcsAttribute attr);
|
||||
CharRowCell() noexcept;
|
||||
CharRowCell(const wchar_t wch, const DbcsAttribute attr) noexcept;
|
||||
|
||||
void EraseChars();
|
||||
void EraseChars() noexcept;
|
||||
void Reset() noexcept;
|
||||
|
||||
bool IsSpace() const noexcept;
|
||||
|
|
|
@ -91,6 +91,9 @@ CharRowCellReference::const_iterator CharRowCellReference::begin() const
|
|||
// - get read-only iterator to the end of the glyph data
|
||||
// Return Value:
|
||||
// - end iterator of the glyph data
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26481)
|
||||
// TODO GH 2672: eliminate using pointers raw as begin/end markers in this class
|
||||
CharRowCellReference::const_iterator CharRowCellReference::end() const
|
||||
{
|
||||
if (_cellData().DbcsAttr().IsGlyphStored())
|
||||
|
@ -103,6 +106,7 @@ CharRowCellReference::const_iterator CharRowCellReference::end() const
|
|||
return &_cellData().Char() + 1;
|
||||
}
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
bool operator==(const CharRowCellReference& ref, const std::vector<wchar_t>& glyph)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ class CharRowCellReference final
|
|||
public:
|
||||
using const_iterator = const wchar_t*;
|
||||
|
||||
CharRowCellReference(CharRow& parent, const size_t index) :
|
||||
CharRowCellReference(CharRow& parent, const size_t index) noexcept :
|
||||
_parent{ parent },
|
||||
_index{ index }
|
||||
{
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
return _glyphStored;
|
||||
}
|
||||
|
||||
void SetGlyphStored(const bool stored)
|
||||
void SetGlyphStored(const bool stored) noexcept
|
||||
{
|
||||
_glyphStored = stored;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
|
||||
|
||||
OutputCell::OutputCell() :
|
||||
OutputCell::OutputCell() noexcept :
|
||||
_text{},
|
||||
_dbcsAttribute{},
|
||||
_textAttribute{ InvalidTextAttribute },
|
||||
|
@ -111,7 +111,5 @@ void OutputCell::_setFromOutputCellView(const OutputCellView& cell)
|
|||
_dbcsAttribute = cell.DbcsAttr();
|
||||
_textAttribute = cell.TextAttr();
|
||||
_behavior = cell.TextAttrBehavior();
|
||||
|
||||
const auto& view = cell.Chars();
|
||||
_text = view;
|
||||
_text = cell.Chars();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ Author:
|
|||
|
||||
class InvalidCharInfoConversionException : public std::exception
|
||||
{
|
||||
const char* what() const noexcept
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "Cannot convert to CHAR_INFO without explicit TextAttribute";
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class InvalidCharInfoConversionException : public std::exception
|
|||
class OutputCell final
|
||||
{
|
||||
public:
|
||||
OutputCell();
|
||||
OutputCell() noexcept;
|
||||
|
||||
OutputCell(const std::wstring_view charData,
|
||||
const DbcsAttribute dbcsAttribute,
|
||||
|
|
|
@ -17,7 +17,7 @@ static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLO
|
|||
// Arguments:
|
||||
// - wch - The character to use for filling
|
||||
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
|
||||
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const size_t fillLimit) :
|
||||
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const size_t fillLimit) noexcept :
|
||||
_mode(Mode::Fill),
|
||||
_currentView(s_GenerateView(wch)),
|
||||
_run(),
|
||||
|
@ -33,7 +33,7 @@ OutputCellIterator::OutputCellIterator(const wchar_t& wch, const size_t fillLimi
|
|||
// Arguments:
|
||||
// - attr - The color attribute to use for filling
|
||||
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
|
||||
OutputCellIterator::OutputCellIterator(const TextAttribute& attr, const size_t fillLimit) :
|
||||
OutputCellIterator::OutputCellIterator(const TextAttribute& attr, const size_t fillLimit) noexcept :
|
||||
_mode(Mode::Fill),
|
||||
_currentView(s_GenerateView(attr)),
|
||||
_run(),
|
||||
|
@ -50,7 +50,7 @@ OutputCellIterator::OutputCellIterator(const TextAttribute& attr, const size_t f
|
|||
// - wch - The character to use for filling
|
||||
// - attr - The color attribute to use for filling
|
||||
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
|
||||
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit) :
|
||||
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit) noexcept :
|
||||
_mode(Mode::Fill),
|
||||
_currentView(s_GenerateView(wch, attr)),
|
||||
_run(),
|
||||
|
@ -66,7 +66,7 @@ OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute&
|
|||
// Arguments:
|
||||
// - charInfo - The legacy character and color data to use for fililng (uses Unicode portion of text data)
|
||||
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
|
||||
OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit) :
|
||||
OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit) noexcept :
|
||||
_mode(Mode::Fill),
|
||||
_currentView(s_GenerateView(charInfo)),
|
||||
_run(),
|
||||
|
@ -116,7 +116,12 @@ OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const
|
|||
// razzle cannot distinguish between a std::wstring_view and a std::basic_string_view<WORD>
|
||||
// NOTE: This one internally casts to wchar_t because Razzle sees WORD and wchar_t as the same type
|
||||
// despite that Visual Studio build can tell the difference.
|
||||
OutputCellIterator::OutputCellIterator(const std::basic_string_view<WORD> legacyAttrs, const bool /*unused*/) :
|
||||
#pragma warning(push)
|
||||
#pragma warning(suppress : 26490)
|
||||
// Suppresses reinterpret_cast. We're only doing this because Windows doesn't understand the type difference between wchar_t and DWORD.
|
||||
// It is not worth trying to separate that out further or risking performance over this particular warning here.
|
||||
// TODO GH 2673 - Investigate real wchar_t flag in Windows and resolve this audit issue
|
||||
OutputCellIterator::OutputCellIterator(const std::basic_string_view<WORD> legacyAttrs, const bool /*unused*/) noexcept :
|
||||
_mode(Mode::LegacyAttr),
|
||||
_currentView(s_GenerateViewLegacyAttr(legacyAttrs.at(0))),
|
||||
_run(std::wstring_view(reinterpret_cast<const wchar_t*>(legacyAttrs.data()), legacyAttrs.size())),
|
||||
|
@ -126,12 +131,13 @@ OutputCellIterator::OutputCellIterator(const std::basic_string_view<WORD> legacy
|
|||
_fillLimit(0)
|
||||
{
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
// Routine Description:
|
||||
// - This is an iterator over legacy cell data. We will use the unicode text and the legacy color attribute.
|
||||
// Arguments:
|
||||
// - charInfos - Multiple cell with unicode text and legacy color data.
|
||||
OutputCellIterator::OutputCellIterator(const std::basic_string_view<CHAR_INFO> charInfos) :
|
||||
OutputCellIterator::OutputCellIterator(const std::basic_string_view<CHAR_INFO> charInfos) noexcept :
|
||||
_mode(Mode::CharInfo),
|
||||
_currentView(s_GenerateView(charInfos.at(0))),
|
||||
_run(charInfos),
|
||||
|
@ -315,7 +321,7 @@ OutputCellIterator OutputCellIterator::operator++(int)
|
|||
// - Reference the view to fully-formed output cell data representing the underlying data source.
|
||||
// Return Value:
|
||||
// - Reference to the view
|
||||
const OutputCellView& OutputCellIterator::operator*() const
|
||||
const OutputCellView& OutputCellIterator::operator*() const noexcept
|
||||
{
|
||||
return _currentView;
|
||||
}
|
||||
|
@ -324,7 +330,7 @@ const OutputCellView& OutputCellIterator::operator*() const
|
|||
// - Get pointer to the view to fully-formed output cell data representing the underlying data source.
|
||||
// Return Value:
|
||||
// - Pointer to the view
|
||||
const OutputCellView* OutputCellIterator::operator->() const
|
||||
const OutputCellView* OutputCellIterator::operator->() const noexcept
|
||||
{
|
||||
return &_currentView;
|
||||
}
|
||||
|
@ -338,7 +344,7 @@ const OutputCellView* OutputCellIterator::operator->() const
|
|||
// - True if we just turned a lead half into a trailing half (and caller doesn't
|
||||
// need to further update the view).
|
||||
// - False if this wasn't applicable and the caller should update the view.
|
||||
bool OutputCellIterator::_TryMoveTrailing()
|
||||
bool OutputCellIterator::_TryMoveTrailing() noexcept
|
||||
{
|
||||
if (_currentView.DbcsAttr().IsLeading())
|
||||
{
|
||||
|
@ -421,7 +427,7 @@ OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
|
|||
// - wch - View representing a single UTF-16 character (that can be represented without surrogates)
|
||||
// Return Value:
|
||||
// - Object representing the view into this cell
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch)
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch) noexcept
|
||||
{
|
||||
const auto glyph = std::wstring_view(&wch, 1);
|
||||
|
||||
|
@ -443,7 +449,7 @@ OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch)
|
|||
// - attr - View representing a single color
|
||||
// Return Value:
|
||||
// - Object representing the view into this cell
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const TextAttribute& attr)
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const TextAttribute& attr) noexcept
|
||||
{
|
||||
return OutputCellView({}, {}, attr, TextAttributeBehavior::StoredOnly);
|
||||
}
|
||||
|
@ -458,7 +464,7 @@ OutputCellView OutputCellIterator::s_GenerateView(const TextAttribute& attr)
|
|||
// - attr - View representing a single color
|
||||
// Return Value:
|
||||
// - Object representing the view into this cell
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch, const TextAttribute& attr)
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch, const TextAttribute& attr) noexcept
|
||||
{
|
||||
const auto glyph = std::wstring_view(&wch, 1);
|
||||
|
||||
|
@ -480,12 +486,12 @@ OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch, const Text
|
|||
// - legacyAttr - View representing a single legacy color
|
||||
// Return Value:
|
||||
// - Object representing the view into this cell
|
||||
OutputCellView OutputCellIterator::s_GenerateViewLegacyAttr(const WORD& legacyAttr)
|
||||
OutputCellView OutputCellIterator::s_GenerateViewLegacyAttr(const WORD& legacyAttr) noexcept
|
||||
{
|
||||
WORD cleanAttr = legacyAttr;
|
||||
WI_ClearAllFlags(cleanAttr, COMMON_LVB_SBCSDBCS); // don't use legacy lead/trailing byte flags for colors
|
||||
|
||||
TextAttribute attr(cleanAttr);
|
||||
const TextAttribute attr(cleanAttr);
|
||||
return s_GenerateView(attr);
|
||||
}
|
||||
|
||||
|
@ -498,7 +504,7 @@ OutputCellView OutputCellIterator::s_GenerateViewLegacyAttr(const WORD& legacyAt
|
|||
// - charInfo - character and attribute pair representing a single cell
|
||||
// Return Value:
|
||||
// - Object representing the view into this cell
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const CHAR_INFO& charInfo)
|
||||
OutputCellView OutputCellIterator::s_GenerateView(const CHAR_INFO& charInfo) noexcept
|
||||
{
|
||||
const auto glyph = std::wstring_view(&charInfo.Char.UnicodeChar, 1);
|
||||
|
||||
|
|
|
@ -33,14 +33,14 @@ public:
|
|||
using pointer = OutputCellView*;
|
||||
using reference = OutputCellView&;
|
||||
|
||||
OutputCellIterator(const wchar_t& wch, const size_t fillLimit = 0);
|
||||
OutputCellIterator(const TextAttribute& attr, const size_t fillLimit = 0);
|
||||
OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit = 0);
|
||||
OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0);
|
||||
OutputCellIterator(const wchar_t& wch, const size_t fillLimit = 0) noexcept;
|
||||
OutputCellIterator(const TextAttribute& attr, const size_t fillLimit = 0) noexcept;
|
||||
OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit = 0) noexcept;
|
||||
OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0) noexcept;
|
||||
OutputCellIterator(const std::wstring_view utf16Text);
|
||||
OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute);
|
||||
OutputCellIterator(const std::basic_string_view<WORD> legacyAttributes, const bool unused);
|
||||
OutputCellIterator(const std::basic_string_view<CHAR_INFO> charInfos);
|
||||
OutputCellIterator(const std::basic_string_view<WORD> legacyAttributes, const bool unused) noexcept;
|
||||
OutputCellIterator(const std::basic_string_view<CHAR_INFO> charInfos) noexcept;
|
||||
OutputCellIterator(const std::basic_string_view<OutputCell> cells);
|
||||
~OutputCellIterator() = default;
|
||||
|
||||
|
@ -55,8 +55,8 @@ public:
|
|||
OutputCellIterator& operator++();
|
||||
OutputCellIterator operator++(int);
|
||||
|
||||
const OutputCellView& operator*() const;
|
||||
const OutputCellView* operator->() const;
|
||||
const OutputCellView& operator*() const noexcept;
|
||||
const OutputCellView* operator->() const noexcept;
|
||||
|
||||
private:
|
||||
enum class Mode
|
||||
|
@ -97,7 +97,7 @@ private:
|
|||
|
||||
TextAttribute _attr;
|
||||
|
||||
bool _TryMoveTrailing();
|
||||
bool _TryMoveTrailing() noexcept;
|
||||
|
||||
static OutputCellView s_GenerateView(const std::wstring_view view);
|
||||
|
||||
|
@ -108,11 +108,11 @@ private:
|
|||
const TextAttribute attr,
|
||||
const TextAttributeBehavior behavior);
|
||||
|
||||
static OutputCellView s_GenerateView(const wchar_t& wch);
|
||||
static OutputCellView s_GenerateViewLegacyAttr(const WORD& legacyAttr);
|
||||
static OutputCellView s_GenerateView(const TextAttribute& attr);
|
||||
static OutputCellView s_GenerateView(const wchar_t& wch, const TextAttribute& attr);
|
||||
static OutputCellView s_GenerateView(const CHAR_INFO& charInfo);
|
||||
static OutputCellView s_GenerateView(const wchar_t& wch) noexcept;
|
||||
static OutputCellView s_GenerateViewLegacyAttr(const WORD& legacyAttr) noexcept;
|
||||
static OutputCellView s_GenerateView(const TextAttribute& attr) noexcept;
|
||||
static OutputCellView s_GenerateView(const wchar_t& wch, const TextAttribute& attr) noexcept;
|
||||
static OutputCellView s_GenerateView(const CHAR_INFO& charInfo) noexcept;
|
||||
|
||||
static OutputCellView s_GenerateView(const OutputCell& cell);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
// Routine Description:
|
||||
// - Constucts an empty in-memory region for holding output buffer cell data.
|
||||
OutputCellRect::OutputCellRect() :
|
||||
OutputCellRect::OutputCellRect() noexcept :
|
||||
_rows(0),
|
||||
_cols(0)
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ OutputCellIterator OutputCellRect::GetRowIter(const size_t row) const
|
|||
// - Pointer to the location in the rectangle that represents the start of the requested row.
|
||||
OutputCell* OutputCellRect::_FindRowOffset(const size_t row)
|
||||
{
|
||||
return (_storage.data() + (row * _cols));
|
||||
return &_storage.at(row * _cols);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -76,7 +76,7 @@ OutputCell* OutputCellRect::_FindRowOffset(const size_t row)
|
|||
// - Pointer to the location in the rectangle that represents the start of the requested row.
|
||||
const OutputCell* OutputCellRect::_FindRowOffset(const size_t row) const
|
||||
{
|
||||
return (_storage.data() + (row * _cols));
|
||||
return &_storage.at(row * _cols);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
|
|
@ -29,7 +29,7 @@ Revision History:
|
|||
class OutputCellRect final
|
||||
{
|
||||
public:
|
||||
OutputCellRect();
|
||||
OutputCellRect() noexcept;
|
||||
OutputCellRect(const size_t rows, const size_t cols);
|
||||
|
||||
gsl::span<OutputCell> GetRow(const size_t row);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
OutputCellView::OutputCellView(const std::wstring_view view,
|
||||
const DbcsAttribute dbcsAttr,
|
||||
const TextAttribute textAttr,
|
||||
const TextAttributeBehavior behavior) :
|
||||
const TextAttributeBehavior behavior) noexcept :
|
||||
_view(view),
|
||||
_dbcsAttr(dbcsAttr),
|
||||
_textAttr(textAttr),
|
||||
|
@ -27,7 +27,9 @@ OutputCellView::OutputCellView(const std::wstring_view view,
|
|||
// - Returns reference to view over text data
|
||||
// Return Value:
|
||||
// - Reference to UTF-16 character data
|
||||
const std::wstring_view& OutputCellView::Chars() const noexcept
|
||||
// C26445 - suppressed to enable the `TextBufferTextIterator::operator->` method which needs a non-temporary memory location holding the wstring_view.
|
||||
// TODO: GH 2681 - remove this suppression by reconciling the probably bad design of the iterators that leads to this being required.
|
||||
[[gsl::suppress(26445)]] const std::wstring_view& OutputCellView::Chars() const noexcept
|
||||
{
|
||||
return _view;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
OutputCellView(const std::wstring_view view,
|
||||
const DbcsAttribute dbcsAttr,
|
||||
const TextAttribute textAttr,
|
||||
const TextAttributeBehavior behavior);
|
||||
const TextAttributeBehavior behavior) noexcept;
|
||||
|
||||
const std::wstring_view& Chars() const noexcept;
|
||||
size_t Columns() const noexcept;
|
||||
|
|
|
@ -30,14 +30,14 @@ size_t ROW::size() const noexcept
|
|||
return _rowWidth;
|
||||
}
|
||||
|
||||
const CharRow& ROW::GetCharRow() const
|
||||
const CharRow& ROW::GetCharRow() const noexcept
|
||||
{
|
||||
return _charRow;
|
||||
}
|
||||
|
||||
CharRow& ROW::GetCharRow()
|
||||
CharRow& ROW::GetCharRow() noexcept
|
||||
{
|
||||
return const_cast<CharRow&>(static_cast<const ROW* const>(this)->GetCharRow());
|
||||
return _charRow;
|
||||
}
|
||||
|
||||
const ATTR_ROW& ROW::GetAttrRow() const noexcept
|
||||
|
@ -47,7 +47,7 @@ const ATTR_ROW& ROW::GetAttrRow() const noexcept
|
|||
|
||||
ATTR_ROW& ROW::GetAttrRow() noexcept
|
||||
{
|
||||
return const_cast<ATTR_ROW&>(static_cast<const ROW* const>(this)->GetAttrRow());
|
||||
return _attrRow;
|
||||
}
|
||||
|
||||
SHORT ROW::GetId() const noexcept
|
||||
|
@ -132,12 +132,12 @@ RowCellIterator ROW::AsCellIter(const size_t startIndex, const size_t count) con
|
|||
return RowCellIterator(*this, startIndex, count);
|
||||
}
|
||||
|
||||
UnicodeStorage& ROW::GetUnicodeStorage()
|
||||
UnicodeStorage& ROW::GetUnicodeStorage() noexcept
|
||||
{
|
||||
return _pParent->GetUnicodeStorage();
|
||||
}
|
||||
|
||||
const UnicodeStorage& ROW::GetUnicodeStorage() const
|
||||
const UnicodeStorage& ROW::GetUnicodeStorage() const noexcept
|
||||
{
|
||||
return _pParent->GetUnicodeStorage();
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
|
||||
size_t size() const noexcept;
|
||||
|
||||
const CharRow& GetCharRow() const;
|
||||
CharRow& GetCharRow();
|
||||
const CharRow& GetCharRow() const noexcept;
|
||||
CharRow& GetCharRow() noexcept;
|
||||
|
||||
const ATTR_ROW& GetAttrRow() const noexcept;
|
||||
ATTR_ROW& GetAttrRow() noexcept;
|
||||
|
@ -54,8 +54,8 @@ public:
|
|||
RowCellIterator AsCellIter(const size_t startIndex) const;
|
||||
RowCellIterator AsCellIter(const size_t startIndex, const size_t count) const;
|
||||
|
||||
UnicodeStorage& GetUnicodeStorage();
|
||||
const UnicodeStorage& GetUnicodeStorage() const;
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
|
||||
OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const bool setWrap, std::optional<size_t> limitRight = std::nullopt);
|
||||
|
||||
|
|
|
@ -37,38 +37,38 @@ bool RowCellIterator::operator!=(const RowCellIterator& it) const noexcept
|
|||
return !(*this == it);
|
||||
}
|
||||
|
||||
RowCellIterator& RowCellIterator::operator+=(const ptrdiff_t& movement)
|
||||
RowCellIterator& RowCellIterator::operator+=(const ptrdiff_t& movement) noexcept
|
||||
{
|
||||
_pos += movement;
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
RowCellIterator& RowCellIterator::operator++()
|
||||
RowCellIterator& RowCellIterator::operator++() noexcept
|
||||
{
|
||||
return this->operator+=(1);
|
||||
}
|
||||
|
||||
RowCellIterator RowCellIterator::operator++(int)
|
||||
RowCellIterator RowCellIterator::operator++(int) noexcept
|
||||
{
|
||||
auto temp(*this);
|
||||
operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
RowCellIterator RowCellIterator::operator+(const ptrdiff_t& movement)
|
||||
RowCellIterator RowCellIterator::operator+(const ptrdiff_t& movement) noexcept
|
||||
{
|
||||
auto temp(*this);
|
||||
temp += movement;
|
||||
return temp;
|
||||
}
|
||||
|
||||
const OutputCellView& RowCellIterator::operator*() const
|
||||
const OutputCellView& RowCellIterator::operator*() const noexcept
|
||||
{
|
||||
return _view;
|
||||
}
|
||||
|
||||
const OutputCellView* RowCellIterator::operator->() const
|
||||
const OutputCellView* RowCellIterator::operator->() const noexcept
|
||||
{
|
||||
return &_view;
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ public:
|
|||
bool operator==(const RowCellIterator& it) const noexcept;
|
||||
bool operator!=(const RowCellIterator& it) const noexcept;
|
||||
|
||||
RowCellIterator& operator+=(const ptrdiff_t& movement);
|
||||
RowCellIterator& operator++();
|
||||
RowCellIterator operator++(int);
|
||||
RowCellIterator operator+(const ptrdiff_t& movement);
|
||||
RowCellIterator& operator+=(const ptrdiff_t& movement) noexcept;
|
||||
RowCellIterator& operator++() noexcept;
|
||||
RowCellIterator operator++(int) noexcept;
|
||||
RowCellIterator operator+(const ptrdiff_t& movement) noexcept;
|
||||
|
||||
const OutputCellView& operator*() const;
|
||||
const OutputCellView* operator->() const;
|
||||
const OutputCellView& operator*() const noexcept;
|
||||
const OutputCellView* operator->() const noexcept;
|
||||
|
||||
private:
|
||||
const ROW& _row;
|
||||
|
|
|
@ -16,7 +16,7 @@ bool TextAttribute::IsLegacy() const noexcept
|
|||
// - color that should be displayed as the foreground color
|
||||
COLORREF TextAttribute::CalculateRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultFgColor,
|
||||
COLORREF defaultBgColor) const
|
||||
COLORREF defaultBgColor) const noexcept
|
||||
{
|
||||
return _IsReverseVideo() ? _GetRgbBackground(colorTable, defaultBgColor) : _GetRgbForeground(colorTable, defaultFgColor);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ COLORREF TextAttribute::CalculateRgbForeground(std::basic_string_view<COLORREF>
|
|||
// - color that should be displayed as the background color
|
||||
COLORREF TextAttribute::CalculateRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultFgColor,
|
||||
COLORREF defaultBgColor) const
|
||||
COLORREF defaultBgColor) const noexcept
|
||||
{
|
||||
return _IsReverseVideo() ? _GetRgbForeground(colorTable, defaultFgColor) : _GetRgbBackground(colorTable, defaultBgColor);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ COLORREF TextAttribute::CalculateRgbBackground(std::basic_string_view<COLORREF>
|
|||
// Return Value:
|
||||
// - color that is stored as the foreground color
|
||||
COLORREF TextAttribute::_GetRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultColor) const
|
||||
COLORREF defaultColor) const noexcept
|
||||
{
|
||||
return _foreground.GetColor(colorTable, defaultColor, _isBold);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ COLORREF TextAttribute::_GetRgbForeground(std::basic_string_view<COLORREF> color
|
|||
// Return Value:
|
||||
// - color that is stored as the background color
|
||||
COLORREF TextAttribute::_GetRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultColor) const
|
||||
COLORREF defaultColor) const noexcept
|
||||
{
|
||||
return _background.GetColor(colorTable, defaultColor, false);
|
||||
}
|
||||
|
@ -75,22 +75,22 @@ WORD TextAttribute::GetMetaAttributes() const noexcept
|
|||
return wMeta;
|
||||
}
|
||||
|
||||
void TextAttribute::SetForeground(const COLORREF rgbForeground)
|
||||
void TextAttribute::SetForeground(const COLORREF rgbForeground) noexcept
|
||||
{
|
||||
_foreground = TextColor(rgbForeground);
|
||||
}
|
||||
|
||||
void TextAttribute::SetBackground(const COLORREF rgbBackground)
|
||||
void TextAttribute::SetBackground(const COLORREF rgbBackground) noexcept
|
||||
{
|
||||
_background = TextColor(rgbBackground);
|
||||
}
|
||||
|
||||
void TextAttribute::SetFromLegacy(const WORD wLegacy) noexcept
|
||||
{
|
||||
_wAttrLegacy = static_cast<WORD>(wLegacy & META_ATTRS);
|
||||
_wAttrLegacy = gsl::narrow_cast<WORD>(wLegacy & META_ATTRS);
|
||||
WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
|
||||
BYTE fgIndex = static_cast<BYTE>(wLegacy & FG_ATTRS);
|
||||
BYTE bgIndex = static_cast<BYTE>(wLegacy & BG_ATTRS) >> 4;
|
||||
const BYTE fgIndex = gsl::narrow_cast<BYTE>(wLegacy & FG_ATTRS);
|
||||
const BYTE bgIndex = gsl::narrow_cast<BYTE>(wLegacy & BG_ATTRS) >> 4;
|
||||
_foreground = TextColor(fgIndex);
|
||||
_background = TextColor(bgIndex);
|
||||
}
|
||||
|
@ -98,16 +98,16 @@ void TextAttribute::SetFromLegacy(const WORD wLegacy) noexcept
|
|||
void TextAttribute::SetLegacyAttributes(const WORD attrs,
|
||||
const bool setForeground,
|
||||
const bool setBackground,
|
||||
const bool setMeta)
|
||||
const bool setMeta) noexcept
|
||||
{
|
||||
if (setForeground)
|
||||
{
|
||||
BYTE fgIndex = (BYTE)(attrs & FG_ATTRS);
|
||||
const BYTE fgIndex = gsl::narrow_cast<BYTE>(attrs & FG_ATTRS);
|
||||
_foreground = TextColor(fgIndex);
|
||||
}
|
||||
if (setBackground)
|
||||
{
|
||||
BYTE bgIndex = (BYTE)(attrs & BG_ATTRS) >> 4;
|
||||
const BYTE bgIndex = gsl::narrow_cast<BYTE>(attrs & BG_ATTRS) >> 4;
|
||||
_background = TextColor(bgIndex);
|
||||
}
|
||||
if (setMeta)
|
||||
|
@ -133,17 +133,17 @@ void TextAttribute::SetIndexedAttributes(const std::optional<const BYTE> foregro
|
|||
{
|
||||
if (foreground)
|
||||
{
|
||||
BYTE fgIndex = (*foreground) & 0xFF;
|
||||
const BYTE fgIndex = (*foreground) & 0xFF;
|
||||
_foreground = TextColor(fgIndex);
|
||||
}
|
||||
if (background)
|
||||
{
|
||||
BYTE bgIndex = (*background) & 0xFF;
|
||||
const BYTE bgIndex = (*background) & 0xFF;
|
||||
_background = TextColor(bgIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground)
|
||||
void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept
|
||||
{
|
||||
if (fIsForeground)
|
||||
{
|
||||
|
|
|
@ -39,9 +39,9 @@ public:
|
|||
}
|
||||
|
||||
constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
|
||||
_wAttrLegacy{ static_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
||||
_foreground{ static_cast<BYTE>(wLegacyAttr & FG_ATTRS) },
|
||||
_background{ static_cast<BYTE>((wLegacyAttr & BG_ATTRS) >> 4) },
|
||||
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
||||
_foreground{ gsl::narrow_cast<BYTE>(wLegacyAttr & FG_ATTRS) },
|
||||
_background{ gsl::narrow_cast<BYTE>((wLegacyAttr & BG_ATTRS) >> 4) },
|
||||
_isBold{ false }
|
||||
{
|
||||
// If we're given lead/trailing byte information with the legacy color, strip it.
|
||||
|
@ -59,9 +59,9 @@ public:
|
|||
|
||||
constexpr WORD GetLegacyAttributes() const noexcept
|
||||
{
|
||||
BYTE fg = (_foreground.GetIndex() & FG_ATTRS);
|
||||
BYTE bg = (_background.GetIndex() << 4) & BG_ATTRS;
|
||||
WORD meta = (_wAttrLegacy & META_ATTRS);
|
||||
const BYTE fg = (_foreground.GetIndex() & FG_ATTRS);
|
||||
const BYTE bg = (_background.GetIndex() << 4) & BG_ATTRS;
|
||||
const WORD meta = (_wAttrLegacy & META_ATTRS);
|
||||
return (fg | bg | meta) | (_isBold ? FOREGROUND_INTENSITY : 0);
|
||||
}
|
||||
|
||||
|
@ -80,20 +80,20 @@ public:
|
|||
constexpr WORD GetLegacyAttributes(const BYTE defaultFgIndex,
|
||||
const BYTE defaultBgIndex) const noexcept
|
||||
{
|
||||
BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex;
|
||||
BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex;
|
||||
BYTE fg = (fgIndex & FG_ATTRS);
|
||||
BYTE bg = (bgIndex << 4) & BG_ATTRS;
|
||||
WORD meta = (_wAttrLegacy & META_ATTRS);
|
||||
const BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex;
|
||||
const BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex;
|
||||
const BYTE fg = (fgIndex & FG_ATTRS);
|
||||
const BYTE bg = (bgIndex << 4) & BG_ATTRS;
|
||||
const WORD meta = (_wAttrLegacy & META_ATTRS);
|
||||
return (fg | bg | meta) | (_isBold ? FOREGROUND_INTENSITY : 0);
|
||||
}
|
||||
|
||||
COLORREF CalculateRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultFgColor,
|
||||
COLORREF defaultBgColor) const;
|
||||
COLORREF defaultBgColor) const noexcept;
|
||||
COLORREF CalculateRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultFgColor,
|
||||
COLORREF defaultBgColor) const;
|
||||
COLORREF defaultBgColor) const noexcept;
|
||||
|
||||
bool IsLeadingByte() const noexcept;
|
||||
bool IsTrailingByte() const noexcept;
|
||||
|
@ -110,7 +110,7 @@ public:
|
|||
void SetLegacyAttributes(const WORD attrs,
|
||||
const bool setForeground,
|
||||
const bool setBackground,
|
||||
const bool setMeta);
|
||||
const bool setMeta) noexcept;
|
||||
|
||||
void SetIndexedAttributes(const std::optional<const BYTE> foreground,
|
||||
const std::optional<const BYTE> background) noexcept;
|
||||
|
@ -133,9 +133,9 @@ public:
|
|||
bool IsLegacy() const noexcept;
|
||||
bool IsBold() const noexcept;
|
||||
|
||||
void SetForeground(const COLORREF rgbForeground);
|
||||
void SetBackground(const COLORREF rgbBackground);
|
||||
void SetColor(const COLORREF rgbColor, const bool fIsForeground);
|
||||
void SetForeground(const COLORREF rgbForeground) noexcept;
|
||||
void SetBackground(const COLORREF rgbBackground) noexcept;
|
||||
void SetColor(const COLORREF rgbColor, const bool fIsForeground) noexcept;
|
||||
|
||||
void SetDefaultForeground() noexcept;
|
||||
void SetDefaultBackground() noexcept;
|
||||
|
@ -150,9 +150,9 @@ public:
|
|||
|
||||
private:
|
||||
COLORREF _GetRgbForeground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultColor) const;
|
||||
COLORREF defaultColor) const noexcept;
|
||||
COLORREF _GetRgbBackground(std::basic_string_view<COLORREF> colorTable,
|
||||
COLORREF defaultColor) const;
|
||||
COLORREF defaultColor) const noexcept;
|
||||
bool _IsReverseVideo() const noexcept;
|
||||
void _SetBoldness(const bool isBold) noexcept;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// - rgbColor: the COLORREF containing the color information for this TextColor
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TextColor::SetColor(const COLORREF rgbColor)
|
||||
void TextColor::SetColor(const COLORREF rgbColor) noexcept
|
||||
{
|
||||
_meta = ColorType::IsRgb;
|
||||
_red = GetRValue(rgbColor);
|
||||
|
@ -25,7 +25,7 @@ void TextColor::SetColor(const COLORREF rgbColor)
|
|||
// - index: the index of the colortable we should use for this TextColor.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TextColor::SetIndex(const BYTE index)
|
||||
void TextColor::SetIndex(const BYTE index) noexcept
|
||||
{
|
||||
_meta = ColorType::IsIndex;
|
||||
_index = index;
|
||||
|
@ -38,7 +38,7 @@ void TextColor::SetIndex(const BYTE index)
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TextColor::SetDefault()
|
||||
void TextColor::SetDefault() noexcept
|
||||
{
|
||||
_meta = ColorType::IsDefault;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ void TextColor::SetDefault()
|
|||
// - a COLORREF containing the real value of this TextColor.
|
||||
COLORREF TextColor::GetColor(std::basic_string_view<COLORREF> colorTable,
|
||||
const COLORREF defaultColor,
|
||||
bool brighten) const
|
||||
bool brighten) const noexcept
|
||||
{
|
||||
if (IsDefault())
|
||||
{
|
||||
|
@ -81,9 +81,9 @@ COLORREF TextColor::GetColor(std::basic_string_view<COLORREF> colorTable,
|
|||
// If we find a match, return instead the bright version of this color
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (colorTable[i] == defaultColor)
|
||||
if (colorTable.at(i) == defaultColor)
|
||||
{
|
||||
return colorTable[i + 8];
|
||||
return colorTable.at(i + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,12 +102,12 @@ COLORREF TextColor::GetColor(std::basic_string_view<COLORREF> colorTable,
|
|||
if (brighten && _index < 8)
|
||||
{
|
||||
FAIL_FAST_IF(colorTable.size() < 16);
|
||||
FAIL_FAST_IF((size_t)(_index + 8) > (size_t)(colorTable.size()));
|
||||
return colorTable[_index + 8];
|
||||
FAIL_FAST_IF(gsl::narrow_cast<size_t>(_index) + 8 > colorTable.size());
|
||||
return colorTable.at(gsl::narrow_cast<size_t>(_index) + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
return colorTable[_index];
|
||||
return colorTable.at(_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ COLORREF TextColor::GetColor(std::basic_string_view<COLORREF> colorTable,
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - a COLORREF containing our stored value
|
||||
COLORREF TextColor::_GetRGB() const
|
||||
COLORREF TextColor::_GetRGB() const noexcept
|
||||
{
|
||||
return RGB(_red, _green, _blue);
|
||||
}
|
||||
|
|
|
@ -91,13 +91,13 @@ public:
|
|||
return _meta == ColorType::IsRgb;
|
||||
}
|
||||
|
||||
void SetColor(const COLORREF rgbColor);
|
||||
void SetIndex(const BYTE index);
|
||||
void SetDefault();
|
||||
void SetColor(const COLORREF rgbColor) noexcept;
|
||||
void SetIndex(const BYTE index) noexcept;
|
||||
void SetDefault() noexcept;
|
||||
|
||||
COLORREF GetColor(std::basic_string_view<COLORREF> colorTable,
|
||||
const COLORREF defaultColor,
|
||||
const bool brighten) const;
|
||||
const bool brighten) const noexcept;
|
||||
|
||||
constexpr BYTE GetIndex() const noexcept
|
||||
{
|
||||
|
@ -113,7 +113,7 @@ private:
|
|||
BYTE _green;
|
||||
BYTE _blue;
|
||||
|
||||
COLORREF _GetRGB() const;
|
||||
COLORREF _GetRGB() const noexcept;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TextBufferTests;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "precomp.h"
|
||||
#include "UnicodeStorage.hpp"
|
||||
|
||||
UnicodeStorage::UnicodeStorage() :
|
||||
UnicodeStorage::UnicodeStorage() noexcept :
|
||||
_map{}
|
||||
{
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ void UnicodeStorage::StoreGlyph(const key_type key, const mapped_type& glyph)
|
|||
// - erases key and its associated data from the storage
|
||||
// Arguments:
|
||||
// - key - the key to remove
|
||||
void UnicodeStorage::Erase(const key_type key) noexcept
|
||||
void UnicodeStorage::Erase(const key_type key)
|
||||
{
|
||||
_map.erase(key);
|
||||
}
|
||||
|
|
|
@ -47,13 +47,13 @@ public:
|
|||
using key_type = typename COORD;
|
||||
using mapped_type = typename std::vector<wchar_t>;
|
||||
|
||||
UnicodeStorage();
|
||||
UnicodeStorage() noexcept;
|
||||
|
||||
const mapped_type& GetText(const key_type key) const;
|
||||
|
||||
void StoreGlyph(const key_type key, const mapped_type& glyph);
|
||||
|
||||
void Erase(const key_type key) noexcept;
|
||||
void Erase(const key_type key);
|
||||
|
||||
void Remap(const std::map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// - Constructor to set default properties for Cursor
|
||||
// Arguments:
|
||||
// - ulSize - The height of the cursor within this buffer
|
||||
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) :
|
||||
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
||||
_parentBuffer{ parentBuffer },
|
||||
_cPosition{ 0 },
|
||||
_fHasMoved(false),
|
||||
|
@ -87,36 +87,36 @@ ULONG Cursor::GetSize() const noexcept
|
|||
return _ulSize;
|
||||
}
|
||||
|
||||
void Cursor::SetHasMoved(const bool fHasMoved)
|
||||
void Cursor::SetHasMoved(const bool fHasMoved) noexcept
|
||||
{
|
||||
_fHasMoved = fHasMoved;
|
||||
}
|
||||
|
||||
void Cursor::SetIsVisible(const bool fIsVisible)
|
||||
void Cursor::SetIsVisible(const bool fIsVisible) noexcept
|
||||
{
|
||||
_fIsVisible = fIsVisible;
|
||||
_RedrawCursor();
|
||||
}
|
||||
|
||||
void Cursor::SetIsOn(const bool fIsOn)
|
||||
void Cursor::SetIsOn(const bool fIsOn) noexcept
|
||||
{
|
||||
_fIsOn = fIsOn;
|
||||
_RedrawCursorAlways();
|
||||
}
|
||||
|
||||
void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed)
|
||||
void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed) noexcept
|
||||
{
|
||||
_fBlinkingAllowed = fBlinkingAllowed;
|
||||
_RedrawCursorAlways();
|
||||
}
|
||||
|
||||
void Cursor::SetIsDouble(const bool fIsDouble)
|
||||
void Cursor::SetIsDouble(const bool fIsDouble) noexcept
|
||||
{
|
||||
_fIsDouble = fIsDouble;
|
||||
_RedrawCursor();
|
||||
}
|
||||
|
||||
void Cursor::SetIsConversionArea(const bool fIsConversionArea)
|
||||
void Cursor::SetIsConversionArea(const bool fIsConversionArea) noexcept
|
||||
{
|
||||
// Functionally the same as "Hide cursor"
|
||||
// Never called with TRUE, it's only used in the creation of a
|
||||
|
@ -125,19 +125,19 @@ void Cursor::SetIsConversionArea(const bool fIsConversionArea)
|
|||
_RedrawCursorAlways();
|
||||
}
|
||||
|
||||
void Cursor::SetIsPopupShown(const bool fIsPopupShown)
|
||||
void Cursor::SetIsPopupShown(const bool fIsPopupShown) noexcept
|
||||
{
|
||||
// Functionally the same as "Hide cursor"
|
||||
_fIsPopupShown = fIsPopupShown;
|
||||
_RedrawCursorAlways();
|
||||
}
|
||||
|
||||
void Cursor::SetDelay(const bool fDelay)
|
||||
void Cursor::SetDelay(const bool fDelay) noexcept
|
||||
{
|
||||
_fDelay = fDelay;
|
||||
}
|
||||
|
||||
void Cursor::SetSize(const ULONG ulSize)
|
||||
void Cursor::SetSize(const ULONG ulSize) noexcept
|
||||
{
|
||||
_ulSize = ulSize;
|
||||
_RedrawCursor();
|
||||
|
@ -195,7 +195,7 @@ void Cursor::_RedrawCursorAlways() noexcept
|
|||
CATCH_LOG();
|
||||
}
|
||||
|
||||
void Cursor::SetPosition(const COORD cPosition)
|
||||
void Cursor::SetPosition(const COORD cPosition) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X = cPosition.X;
|
||||
|
@ -204,50 +204,50 @@ void Cursor::SetPosition(const COORD cPosition)
|
|||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::SetXPosition(const int NewX)
|
||||
void Cursor::SetXPosition(const int NewX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X = (SHORT)NewX;
|
||||
_cPosition.X = gsl::narrow<SHORT>(NewX);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::SetYPosition(const int NewY)
|
||||
void Cursor::SetYPosition(const int NewY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y = (SHORT)NewY;
|
||||
_cPosition.Y = gsl::narrow<SHORT>(NewY);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::IncrementXPosition(const int DeltaX)
|
||||
void Cursor::IncrementXPosition(const int DeltaX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X += (SHORT)DeltaX;
|
||||
_cPosition.X += gsl::narrow<SHORT>(DeltaX);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::IncrementYPosition(const int DeltaY)
|
||||
void Cursor::IncrementYPosition(const int DeltaY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y += (SHORT)DeltaY;
|
||||
_cPosition.Y += gsl::narrow<SHORT>(DeltaY);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::DecrementXPosition(const int DeltaX)
|
||||
void Cursor::DecrementXPosition(const int DeltaX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X -= (SHORT)DeltaX;
|
||||
_cPosition.X -= gsl::narrow<SHORT>(DeltaX);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::DecrementYPosition(const int DeltaY)
|
||||
void Cursor::DecrementYPosition(const int DeltaY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y -= (SHORT)DeltaY;
|
||||
_cPosition.Y -= gsl::narrow<SHORT>(DeltaY);
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ void Cursor::DecrementYPosition(const int DeltaY)
|
|||
// - OtherCursor - The cursor to copy properties from
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Cursor::CopyProperties(const Cursor& OtherCursor)
|
||||
void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
||||
{
|
||||
// We shouldn't copy the position as it will be already rearranged by the resize operation.
|
||||
//_cPosition = pOtherCursor->_cPosition;
|
||||
|
@ -288,34 +288,34 @@ void Cursor::CopyProperties(const Cursor& OtherCursor)
|
|||
_color = OtherCursor._color;
|
||||
}
|
||||
|
||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt)
|
||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||
{
|
||||
_coordDelayedAt = coordDelayedAt;
|
||||
_fDelayedEolWrap = true;
|
||||
}
|
||||
|
||||
void Cursor::ResetDelayEOLWrap()
|
||||
void Cursor::ResetDelayEOLWrap() noexcept
|
||||
{
|
||||
_coordDelayedAt = { 0 };
|
||||
_fDelayedEolWrap = false;
|
||||
}
|
||||
|
||||
COORD Cursor::GetDelayedAtPosition() const
|
||||
COORD Cursor::GetDelayedAtPosition() const noexcept
|
||||
{
|
||||
return _coordDelayedAt;
|
||||
}
|
||||
|
||||
bool Cursor::IsDelayedEOLWrap() const
|
||||
bool Cursor::IsDelayedEOLWrap() const noexcept
|
||||
{
|
||||
return _fDelayedEolWrap;
|
||||
}
|
||||
|
||||
void Cursor::StartDeferDrawing()
|
||||
void Cursor::StartDeferDrawing() noexcept
|
||||
{
|
||||
_fDeferCursorRedraw = true;
|
||||
}
|
||||
|
||||
void Cursor::EndDeferDrawing()
|
||||
void Cursor::EndDeferDrawing() noexcept
|
||||
{
|
||||
if (_fHaveDeferredCursorRedraw)
|
||||
{
|
||||
|
@ -325,27 +325,27 @@ void Cursor::EndDeferDrawing()
|
|||
_fDeferCursorRedraw = FALSE;
|
||||
}
|
||||
|
||||
const CursorType Cursor::GetType() const
|
||||
const CursorType Cursor::GetType() const noexcept
|
||||
{
|
||||
return _cursorType;
|
||||
}
|
||||
|
||||
const bool Cursor::IsUsingColor() const
|
||||
const bool Cursor::IsUsingColor() const noexcept
|
||||
{
|
||||
return GetColor() != INVALID_COLOR;
|
||||
}
|
||||
|
||||
const COLORREF Cursor::GetColor() const
|
||||
const COLORREF Cursor::GetColor() const noexcept
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void Cursor::SetColor(const unsigned int color)
|
||||
void Cursor::SetColor(const unsigned int color) noexcept
|
||||
{
|
||||
_color = (COLORREF)color;
|
||||
_color = gsl::narrow_cast<COLORREF>(color);
|
||||
}
|
||||
|
||||
void Cursor::SetType(const CursorType type)
|
||||
void Cursor::SetType(const CursorType type) noexcept
|
||||
{
|
||||
_cursorType = type;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class Cursor final
|
|||
public:
|
||||
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
|
||||
|
||||
Cursor(const ULONG ulSize, TextBuffer& parentBuffer);
|
||||
Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept;
|
||||
|
||||
~Cursor();
|
||||
|
||||
|
@ -50,41 +50,41 @@ public:
|
|||
ULONG GetSize() const noexcept;
|
||||
COORD GetPosition() const noexcept;
|
||||
|
||||
const CursorType GetType() const;
|
||||
const bool IsUsingColor() const;
|
||||
const COLORREF GetColor() const;
|
||||
const CursorType GetType() const noexcept;
|
||||
const bool IsUsingColor() const noexcept;
|
||||
const COLORREF GetColor() const noexcept;
|
||||
|
||||
void StartDeferDrawing();
|
||||
void EndDeferDrawing();
|
||||
void StartDeferDrawing() noexcept;
|
||||
void EndDeferDrawing() noexcept;
|
||||
|
||||
void SetHasMoved(const bool fHasMoved);
|
||||
void SetIsVisible(const bool fIsVisible);
|
||||
void SetIsOn(const bool fIsOn);
|
||||
void SetBlinkingAllowed(const bool fIsOn);
|
||||
void SetIsDouble(const bool fIsDouble);
|
||||
void SetIsConversionArea(const bool fIsConversionArea);
|
||||
void SetIsPopupShown(const bool fIsPopupShown);
|
||||
void SetDelay(const bool fDelay);
|
||||
void SetSize(const ULONG ulSize);
|
||||
void SetHasMoved(const bool fHasMoved) noexcept;
|
||||
void SetIsVisible(const bool fIsVisible) noexcept;
|
||||
void SetIsOn(const bool fIsOn) noexcept;
|
||||
void SetBlinkingAllowed(const bool fIsOn) noexcept;
|
||||
void SetIsDouble(const bool fIsDouble) noexcept;
|
||||
void SetIsConversionArea(const bool fIsConversionArea) noexcept;
|
||||
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
|
||||
void SetDelay(const bool fDelay) noexcept;
|
||||
void SetSize(const ULONG ulSize) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
|
||||
|
||||
void SetPosition(const COORD cPosition);
|
||||
void SetXPosition(const int NewX);
|
||||
void SetYPosition(const int NewY);
|
||||
void IncrementXPosition(const int DeltaX);
|
||||
void IncrementYPosition(const int DeltaY);
|
||||
void DecrementXPosition(const int DeltaX);
|
||||
void DecrementYPosition(const int DeltaY);
|
||||
void SetPosition(const COORD cPosition) noexcept;
|
||||
void SetXPosition(const int NewX) noexcept;
|
||||
void SetYPosition(const int NewY) noexcept;
|
||||
void IncrementXPosition(const int DeltaX) noexcept;
|
||||
void IncrementYPosition(const int DeltaY) noexcept;
|
||||
void DecrementXPosition(const int DeltaX) noexcept;
|
||||
void DecrementYPosition(const int DeltaY) noexcept;
|
||||
|
||||
void CopyProperties(const Cursor& OtherCursor);
|
||||
void CopyProperties(const Cursor& OtherCursor) noexcept;
|
||||
|
||||
void DelayEOLWrap(const COORD coordDelayedAt);
|
||||
void ResetDelayEOLWrap();
|
||||
COORD GetDelayedAtPosition() const;
|
||||
bool IsDelayedEOLWrap() const;
|
||||
void DelayEOLWrap(const COORD coordDelayedAt) noexcept;
|
||||
void ResetDelayEOLWrap() noexcept;
|
||||
COORD GetDelayedAtPosition() const noexcept;
|
||||
bool IsDelayedEOLWrap() const noexcept;
|
||||
|
||||
void SetColor(const unsigned int color);
|
||||
void SetType(const CursorType type);
|
||||
void SetColor(const unsigned int color) noexcept;
|
||||
void SetType(const CursorType type) noexcept;
|
||||
|
||||
private:
|
||||
TextBuffer& _parentBuffer;
|
||||
|
|
|
@ -49,7 +49,7 @@ TextBuffer::TextBuffer(const COORD screenBufferSize,
|
|||
// - OtherBuffer - The text buffer to copy properties from
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer)
|
||||
void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer) noexcept
|
||||
{
|
||||
GetCursor().CopyProperties(OtherBuffer.GetCursor());
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer)
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - Total number of rows in the buffer
|
||||
UINT TextBuffer::TotalRowCount() const
|
||||
UINT TextBuffer::TotalRowCount() const noexcept
|
||||
{
|
||||
return static_cast<UINT>(_storage.size());
|
||||
return gsl::narrow<UINT>(_storage.size());
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -78,7 +78,7 @@ const ROW& TextBuffer::GetRowByOffset(const size_t index) const
|
|||
|
||||
// Rows are stored circularly, so the index you ask for is offset by the start position and mod the total of rows.
|
||||
const size_t offsetIndex = (_firstRow + index) % totalRows;
|
||||
return _storage[offsetIndex];
|
||||
return _storage.at(offsetIndex);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -90,7 +90,11 @@ const ROW& TextBuffer::GetRowByOffset(const size_t index) const
|
|||
// - reference to the requested row. Asserts if out of bounds.
|
||||
ROW& TextBuffer::GetRowByOffset(const size_t index)
|
||||
{
|
||||
return const_cast<ROW&>(static_cast<const TextBuffer*>(this)->GetRowByOffset(index));
|
||||
const size_t totalRows = TotalRowCount();
|
||||
|
||||
// Rows are stored circularly, so the index you ask for is offset by the start position and mod the total of rows.
|
||||
const size_t offsetIndex = (_firstRow + index) % totalRows;
|
||||
return _storage.at(offsetIndex);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -542,7 +546,7 @@ bool TextBuffer::IncrementCircularBuffer()
|
|||
_renderTarget.TriggerCircling();
|
||||
|
||||
// First, clean out the old "first row" as it will become the "last row" of the buffer after the circle is performed.
|
||||
bool fSuccess = _storage.at(_firstRow).Reset(_currentAttributes);
|
||||
const bool fSuccess = _storage.at(_firstRow).Reset(_currentAttributes);
|
||||
if (fSuccess)
|
||||
{
|
||||
// Now proceed to increment.
|
||||
|
@ -584,9 +588,9 @@ COORD TextBuffer::GetLastNonSpaceCharacter(const Microsoft::Console::Types::View
|
|||
// Search the given viewport by starting at the bottom.
|
||||
coordEndOfText.Y = viewport.BottomInclusive();
|
||||
|
||||
const ROW* pCurrRow = &GetRowByOffset(coordEndOfText.Y);
|
||||
const auto& currRow = GetRowByOffset(coordEndOfText.Y);
|
||||
// The X position of the end of the valid text is the Right draw boundary (which is one beyond the final valid character)
|
||||
coordEndOfText.X = static_cast<short>(pCurrRow->GetCharRow().MeasureRight()) - 1;
|
||||
coordEndOfText.X = gsl::narrow<short>(currRow.GetCharRow().MeasureRight()) - 1;
|
||||
|
||||
// If the X coordinate turns out to be -1, the row was empty, we need to search backwards for the real end of text.
|
||||
const auto viewportTop = viewport.Top();
|
||||
|
@ -594,10 +598,10 @@ COORD TextBuffer::GetLastNonSpaceCharacter(const Microsoft::Console::Types::View
|
|||
while (fDoBackUp)
|
||||
{
|
||||
coordEndOfText.Y--;
|
||||
pCurrRow = &GetRowByOffset(coordEndOfText.Y);
|
||||
const auto& backupRow = GetRowByOffset(coordEndOfText.Y);
|
||||
// We need to back up to the previous row if this line is empty, AND there are more rows
|
||||
|
||||
coordEndOfText.X = static_cast<short>(pCurrRow->GetCharRow().MeasureRight()) - 1;
|
||||
coordEndOfText.X = gsl::narrow<short>(backupRow.GetCharRow().MeasureRight()) - 1;
|
||||
fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > viewportTop);
|
||||
}
|
||||
|
||||
|
@ -640,7 +644,7 @@ COORD TextBuffer::_GetPreviousFromCursor() const
|
|||
return coordPosition;
|
||||
}
|
||||
|
||||
const SHORT TextBuffer::GetFirstRowIndex() const
|
||||
const SHORT TextBuffer::GetFirstRowIndex() const noexcept
|
||||
{
|
||||
return _firstRow;
|
||||
}
|
||||
|
@ -649,7 +653,7 @@ const Viewport TextBuffer::GetSize() const
|
|||
return Viewport::FromDimensions({ 0, 0 }, { gsl::narrow<SHORT>(_storage.at(0).size()), gsl::narrow<SHORT>(_storage.size()) });
|
||||
}
|
||||
|
||||
void TextBuffer::_SetFirstRowIndex(const SHORT FirstRowIndex)
|
||||
void TextBuffer::_SetFirstRowIndex(const SHORT FirstRowIndex) noexcept
|
||||
{
|
||||
_firstRow = FirstRowIndex;
|
||||
}
|
||||
|
@ -755,12 +759,12 @@ void TextBuffer::ScrollRows(const SHORT firstRow, const SHORT size, const SHORT
|
|||
_RefreshRowIDs(std::nullopt);
|
||||
}
|
||||
|
||||
Cursor& TextBuffer::GetCursor()
|
||||
Cursor& TextBuffer::GetCursor() noexcept
|
||||
{
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
const Cursor& TextBuffer::GetCursor() const
|
||||
const Cursor& TextBuffer::GetCursor() const noexcept
|
||||
{
|
||||
return _cursor;
|
||||
}
|
||||
|
@ -795,7 +799,7 @@ void TextBuffer::Reset()
|
|||
// - newSize - new size of screen.
|
||||
// Return Value:
|
||||
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const COORD newSize) noexcept
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const COORD newSize)
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
|
||||
|
||||
|
@ -812,7 +816,7 @@ void TextBuffer::Reset()
|
|||
// rotate rows until the top row is at index 0
|
||||
try
|
||||
{
|
||||
const ROW& newTopRow = _storage[TopRowIndex];
|
||||
const ROW& newTopRow = _storage.at(TopRowIndex);
|
||||
while (&newTopRow != &_storage.front())
|
||||
{
|
||||
_storage.push_back(std::move(_storage.front()));
|
||||
|
@ -843,12 +847,12 @@ void TextBuffer::Reset()
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
const UnicodeStorage& TextBuffer::GetUnicodeStorage() const
|
||||
const UnicodeStorage& TextBuffer::GetUnicodeStorage() const noexcept
|
||||
{
|
||||
return _unicodeStorage;
|
||||
}
|
||||
|
||||
UnicodeStorage& TextBuffer::GetUnicodeStorage()
|
||||
UnicodeStorage& TextBuffer::GetUnicodeStorage() noexcept
|
||||
{
|
||||
return _unicodeStorage;
|
||||
}
|
||||
|
@ -923,7 +927,7 @@ ROW& TextBuffer::_GetPrevRowNoWrap(const ROW& Row)
|
|||
}
|
||||
|
||||
THROW_HR_IF(E_FAIL, Row.GetId() == _firstRow);
|
||||
return _storage[prevRowIndex];
|
||||
return _storage.at(prevRowIndex);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -932,7 +936,7 @@ ROW& TextBuffer::_GetPrevRowNoWrap(const ROW& Row)
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - This buffer's current render target.
|
||||
Microsoft::Console::Render::IRenderTarget& TextBuffer::GetRenderTarget()
|
||||
Microsoft::Console::Render::IRenderTarget& TextBuffer::GetRenderTarget() noexcept
|
||||
{
|
||||
return _renderTarget;
|
||||
}
|
||||
|
@ -977,9 +981,9 @@ const TextBuffer::TextAndColor TextBuffer::GetTextForClipboard(const bool lineSe
|
|||
std::vector<COLORREF> selectionBkAttr;
|
||||
|
||||
// preallocate to avoid reallocs
|
||||
selectionText.reserve(highlight.Width() + 2); // + 2 for \r\n if we munged it
|
||||
selectionFgAttr.reserve(highlight.Width() + 2);
|
||||
selectionBkAttr.reserve(highlight.Width() + 2);
|
||||
selectionText.reserve(gsl::narrow<size_t>(highlight.Width()) + 2); // + 2 for \r\n if we munged it
|
||||
selectionFgAttr.reserve(gsl::narrow<size_t>(highlight.Width()) + 2);
|
||||
selectionBkAttr.reserve(gsl::narrow<size_t>(highlight.Width()) + 2);
|
||||
|
||||
// copy char data into the string buffer, skipping trailing bytes
|
||||
while (it)
|
||||
|
@ -998,6 +1002,8 @@ const TextBuffer::TextAndColor TextBuffer::GetTextForClipboard(const bool lineSe
|
|||
selectionBkAttr.push_back(CellBkAttr);
|
||||
}
|
||||
}
|
||||
#pragma warning(suppress : 26444)
|
||||
// TODO GH 2675: figure out why there's custom construction/destruction happening here
|
||||
it++;
|
||||
}
|
||||
|
||||
|
@ -1059,6 +1065,10 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows, const int fontHeightPo
|
|||
{
|
||||
try
|
||||
{
|
||||
// TODO: GH 602 the font name needs to be passed and stored around as an actual bounded type, not an implicit bounds on LF_FACESIZE
|
||||
const auto faceLength = wcsnlen_s(fontFaceName, LF_FACESIZE);
|
||||
const std::wstring_view faceNameView{ fontFaceName, faceLength };
|
||||
|
||||
std::ostringstream htmlBuilder;
|
||||
|
||||
// First we have to add some standard
|
||||
|
@ -1084,12 +1094,9 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows, const int fontHeightPo
|
|||
htmlBuilder << ";";
|
||||
|
||||
htmlBuilder << "font-family:";
|
||||
if (fontFaceName[0] != '\0')
|
||||
{
|
||||
htmlBuilder << "'";
|
||||
htmlBuilder << ConvertToA(CP_UTF8, fontFaceName);
|
||||
htmlBuilder << "',";
|
||||
}
|
||||
htmlBuilder << "'";
|
||||
htmlBuilder << ConvertToA(CP_UTF8, faceNameView);
|
||||
htmlBuilder << "',";
|
||||
// even with different font, add monospace as fallback
|
||||
htmlBuilder << "monospace;";
|
||||
|
||||
|
@ -1109,7 +1116,7 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows, const int fontHeightPo
|
|||
bool hasWrittenAnyText = false;
|
||||
std::optional<COLORREF> fgColor = std::nullopt;
|
||||
std::optional<COLORREF> bkColor = std::nullopt;
|
||||
for (UINT row = 0; row < rows.text.size(); row++)
|
||||
for (size_t row = 0; row < rows.text.size(); row++)
|
||||
{
|
||||
size_t startOffset = 0;
|
||||
|
||||
|
@ -1118,25 +1125,25 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows, const int fontHeightPo
|
|||
htmlBuilder << "<BR>";
|
||||
}
|
||||
|
||||
for (UINT col = 0; col < rows.text[row].length(); col++)
|
||||
for (size_t col = 0; col < rows.text.at(row).length(); col++)
|
||||
{
|
||||
// do not include \r nor \n as they don't have attributes
|
||||
// and are not HTML friendly. For line break use '<BR>' instead.
|
||||
bool isLastCharInRow =
|
||||
col == rows.text[row].length() - 1 ||
|
||||
rows.text[row][col + 1] == '\r' ||
|
||||
rows.text[row][col + 1] == '\n';
|
||||
const bool isLastCharInRow =
|
||||
col == rows.text.at(row).length() - 1 ||
|
||||
rows.text.at(row).at(col + 1) == '\r' ||
|
||||
rows.text.at(row).at(col + 1) == '\n';
|
||||
|
||||
bool colorChanged = false;
|
||||
if (!fgColor.has_value() || rows.FgAttr[row][col] != fgColor.value())
|
||||
if (!fgColor.has_value() || rows.FgAttr.at(row).at(col) != fgColor.value())
|
||||
{
|
||||
fgColor = rows.FgAttr[row][col];
|
||||
fgColor = rows.FgAttr.at(row).at(col);
|
||||
colorChanged = true;
|
||||
}
|
||||
|
||||
if (!bkColor.has_value() || rows.BkAttr[row][col] != bkColor.value())
|
||||
if (!bkColor.has_value() || rows.BkAttr.at(row).at(col) != bkColor.value())
|
||||
{
|
||||
bkColor = rows.BkAttr[row][col];
|
||||
bkColor = rows.BkAttr.at(row).at(col);
|
||||
colorChanged = true;
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1152,7 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows, const int fontHeightPo
|
|||
{
|
||||
// note: this should be escaped (for '<', '>', and '&'),
|
||||
// however MS Word doesn't appear to support HTML entities
|
||||
htmlBuilder << ConvertToA(CP_UTF8, std::wstring_view(rows.text[row].data() + startOffset, col - startOffset + includeCurrent));
|
||||
htmlBuilder << ConvertToA(CP_UTF8, std::wstring_view(rows.text.at(row)).substr(startOffset, col - startOffset + includeCurrent));
|
||||
startOffset = col;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
~TextBuffer() = default;
|
||||
|
||||
// Used for duplicating properties to another text buffer
|
||||
void CopyProperties(const TextBuffer& OtherBuffer);
|
||||
void CopyProperties(const TextBuffer& OtherBuffer) noexcept;
|
||||
|
||||
// row manipulation
|
||||
const ROW& GetRowByOffset(const size_t index) const;
|
||||
|
@ -107,16 +107,16 @@ public:
|
|||
COORD GetLastNonSpaceCharacter() const;
|
||||
COORD GetLastNonSpaceCharacter(const Microsoft::Console::Types::Viewport viewport) const;
|
||||
|
||||
Cursor& GetCursor();
|
||||
const Cursor& GetCursor() const;
|
||||
Cursor& GetCursor() noexcept;
|
||||
const Cursor& GetCursor() const noexcept;
|
||||
|
||||
const SHORT GetFirstRowIndex() const;
|
||||
const SHORT GetFirstRowIndex() const noexcept;
|
||||
|
||||
const Microsoft::Console::Types::Viewport GetSize() const;
|
||||
|
||||
void ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta);
|
||||
|
||||
UINT TotalRowCount() const;
|
||||
UINT TotalRowCount() const noexcept;
|
||||
|
||||
[[nodiscard]] TextAttribute GetCurrentAttributes() const noexcept;
|
||||
|
||||
|
@ -124,12 +124,12 @@ public:
|
|||
|
||||
void Reset();
|
||||
|
||||
[[nodiscard]] HRESULT ResizeTraditional(const COORD newSize) noexcept;
|
||||
[[nodiscard]] HRESULT ResizeTraditional(const COORD newSize);
|
||||
|
||||
const UnicodeStorage& GetUnicodeStorage() const;
|
||||
UnicodeStorage& GetUnicodeStorage();
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
|
||||
Microsoft::Console::Render::IRenderTarget& GetRenderTarget();
|
||||
Microsoft::Console::Render::IRenderTarget& GetRenderTarget() noexcept;
|
||||
|
||||
class TextAndColor
|
||||
{
|
||||
|
@ -165,7 +165,7 @@ private:
|
|||
|
||||
Microsoft::Console::Render::IRenderTarget& _renderTarget;
|
||||
|
||||
void _SetFirstRowIndex(const SHORT FirstRowIndex);
|
||||
void _SetFirstRowIndex(const SHORT FirstRowIndex) noexcept;
|
||||
|
||||
COORD _GetPreviousFromCursor() const;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ TextBufferCellIterator::operator bool() const noexcept
|
|||
// - it - The other iterator to compare to this one.
|
||||
// Return Value:
|
||||
// - True if it's the same text buffer and same cell position. False otherwise.
|
||||
bool TextBufferCellIterator::operator==(const TextBufferCellIterator& it) const noexcept
|
||||
bool TextBufferCellIterator::operator==(const TextBufferCellIterator& it) const
|
||||
{
|
||||
return _pos == it._pos &&
|
||||
&_buffer == &it._buffer &&
|
||||
|
@ -81,7 +81,7 @@ bool TextBufferCellIterator::operator==(const TextBufferCellIterator& it) const
|
|||
// - it - The other iterator to compare to this one.
|
||||
// Return Value:
|
||||
// - True if it's the same text buffer and different cell position or if they're different buffers. False otherwise.
|
||||
bool TextBufferCellIterator::operator!=(const TextBufferCellIterator& it) const noexcept
|
||||
bool TextBufferCellIterator::operator!=(const TextBufferCellIterator& it) const
|
||||
{
|
||||
return !(*this == it);
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ void TextBufferCellIterator::_SetPos(const COORD newPos)
|
|||
|
||||
if (newPos.X != _pos.X)
|
||||
{
|
||||
const ptrdiff_t diff = newPos.X - _pos.X;
|
||||
const auto diff = gsl::narrow_cast<ptrdiff_t>(newPos.X) - gsl::narrow_cast<ptrdiff_t>(_pos.X);
|
||||
_attrIter += diff;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,12 +28,10 @@ public:
|
|||
TextBufferCellIterator(const TextBuffer& buffer, COORD pos);
|
||||
TextBufferCellIterator(const TextBuffer& buffer, COORD pos, const Microsoft::Console::Types::Viewport limits);
|
||||
|
||||
~TextBufferCellIterator() = default;
|
||||
|
||||
operator bool() const noexcept;
|
||||
|
||||
bool operator==(const TextBufferCellIterator& it) const noexcept;
|
||||
bool operator!=(const TextBufferCellIterator& it) const noexcept;
|
||||
bool operator==(const TextBufferCellIterator& it) const;
|
||||
bool operator!=(const TextBufferCellIterator& it) const;
|
||||
|
||||
TextBufferCellIterator& operator+=(const ptrdiff_t& movement);
|
||||
TextBufferCellIterator& operator-=(const ptrdiff_t& movement);
|
||||
|
|
|
@ -16,7 +16,7 @@ using namespace Microsoft::Console::Types;
|
|||
// - Narrows the view of a cell iterator into a text only iterator.
|
||||
// Arguments:
|
||||
// - A cell iterator
|
||||
TextBufferTextIterator::TextBufferTextIterator(const TextBufferCellIterator& cellIt) :
|
||||
TextBufferTextIterator::TextBufferTextIterator(const TextBufferCellIterator& cellIt) noexcept :
|
||||
TextBufferCellIterator(cellIt)
|
||||
{
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ TextBufferTextIterator::TextBufferTextIterator(const TextBufferCellIterator& cel
|
|||
// - Returns the text information from the text buffer position addressed by this iterator.
|
||||
// Return Value:
|
||||
// - Read only UTF-16 text data
|
||||
const std::wstring_view TextBufferTextIterator::operator*() const
|
||||
// TODO GH 2682, fix design so this doesn't have to be suppressed.
|
||||
[[gsl::suppress(26434)]] const std::wstring_view TextBufferTextIterator::operator*() const noexcept
|
||||
{
|
||||
return _view.Chars();
|
||||
}
|
||||
|
@ -34,7 +35,8 @@ const std::wstring_view TextBufferTextIterator::operator*() const
|
|||
// - Returns the text information from the text buffer position addressed by this iterator.
|
||||
// Return Value:
|
||||
// - Read only UTF-16 text data
|
||||
const std::wstring_view* TextBufferTextIterator::operator->() const
|
||||
// TODO GH 2682, fix design so this doesn't have to be suppressed.
|
||||
[[gsl::suppress(26434)]] const std::wstring_view* TextBufferTextIterator::operator->() const noexcept
|
||||
{
|
||||
return &_view.Chars();
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ class SCREEN_INFORMATION;
|
|||
class TextBufferTextIterator final : public TextBufferCellIterator
|
||||
{
|
||||
public:
|
||||
TextBufferTextIterator(const TextBufferCellIterator& cellIter);
|
||||
TextBufferTextIterator(const TextBufferCellIterator& cellIter) noexcept;
|
||||
|
||||
const std::wstring_view operator*() const;
|
||||
const std::wstring_view* operator->() const;
|
||||
const std::wstring_view operator*() const noexcept;
|
||||
const std::wstring_view* operator->() const noexcept;
|
||||
|
||||
protected:
|
||||
#if UNIT_TESTING
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<application>
|
||||
<!-- Windows 10 1903 -->
|
||||
<!-- See https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands -->
|
||||
<!-- "maxversiontested" is CASE SENSITIVE. Do not change this.-->
|
||||
<maxversiontested Id="10.0.18362.0"/>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
|
|
|
@ -26,6 +26,10 @@ constexpr COLORREF DEFAULT_BACKGROUND_WITH_ALPHA = OPACITY_OPAQUE | DEFAULT_BACK
|
|||
constexpr COLORREF POWERSHELL_BLUE = RGB(1, 36, 86);
|
||||
|
||||
constexpr short DEFAULT_HISTORY_SIZE = 9001;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26426)
|
||||
// TODO GH 2674, don't disable this warning, move to std::wstring_view or something like that.
|
||||
const std::wstring DEFAULT_FONT_FACE{ L"Consolas" };
|
||||
constexpr int DEFAULT_FONT_SIZE = 12;
|
||||
|
||||
|
@ -39,3 +43,4 @@ constexpr COLORREF DEFAULT_CURSOR_COLOR = COLOR_WHITE;
|
|||
constexpr COLORREF DEFAULT_CURSOR_HEIGHT = 25;
|
||||
|
||||
const std::wstring DEFAULT_WORD_DELIMITERS{ L" ./\\()\"'-:,.;<>~!@#$%^&*|+=[]{}~?\u2502" };
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<ClInclude Include="..\..\inc\IRenderData.hpp" />
|
||||
<ClInclude Include="..\..\inc\IRenderEngine.hpp" />
|
||||
<ClInclude Include="..\..\inc\IRenderer.hpp" />
|
||||
<ClInclude Include="..\..\inc\IRenderTarget.hpp" />
|
||||
<ClInclude Include="..\..\inc\RenderEngineBase.hpp" />
|
||||
<ClInclude Include="..\precomp.h" />
|
||||
<ClInclude Include="..\renderer.hpp" />
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
<ClInclude Include="..\..\inc\Cluster.hpp">
|
||||
<Filter>Header Files\inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\inc\IRenderTarget.hpp">
|
||||
<Filter>Header Files\inc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
|
|
|
@ -20,16 +20,16 @@ using namespace Microsoft::Console::Render;
|
|||
// - font - The DirectWrite font face to use while calculating layout (by default, will fallback if necessary)
|
||||
// - clusters - From the backing buffer, the text to be displayed clustered by the columns it should consume.
|
||||
// - width - The count of pixels available per column (the expected pixel width of every column)
|
||||
CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
||||
IDWriteTextAnalyzer1* const analyzer,
|
||||
IDWriteTextFormat* const format,
|
||||
IDWriteFontFace1* const font,
|
||||
CustomTextLayout::CustomTextLayout(gsl::not_null<IDWriteFactory1*> const factory,
|
||||
gsl::not_null<IDWriteTextAnalyzer1*> const analyzer,
|
||||
gsl::not_null<IDWriteTextFormat*> const format,
|
||||
gsl::not_null<IDWriteFontFace1*> const font,
|
||||
std::basic_string_view<Cluster> const clusters,
|
||||
size_t const width) :
|
||||
_factory{ factory },
|
||||
_analyzer{ analyzer },
|
||||
_format{ format },
|
||||
_font{ font },
|
||||
_factory{ factory.get() },
|
||||
_analyzer{ analyzer.get() },
|
||||
_format{ format.get() },
|
||||
_font{ font.get() },
|
||||
_localeName{},
|
||||
_numberSubstitution{},
|
||||
_readingDirection{ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT },
|
||||
|
@ -39,7 +39,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
_width{ width }
|
||||
{
|
||||
// Fetch the locale name out once now from the format
|
||||
_localeName.resize(format->GetLocaleNameLength() + 1); // +1 for null
|
||||
_localeName.resize(gsl::narrow_cast<size_t>(format->GetLocaleNameLength()) + 1); // +1 for null
|
||||
THROW_IF_FAILED(format->GetLocaleName(_localeName.data(), gsl::narrow<UINT32>(_localeName.size())));
|
||||
|
||||
for (const auto& cluster : clusters)
|
||||
|
@ -58,6 +58,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - S_OK or suitable DirectX/DirectWrite/Direct2D result code.
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE CustomTextLayout::GetColumns(_Out_ UINT32* columns)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, columns);
|
||||
*columns = 0;
|
||||
|
||||
RETURN_IF_FAILED(_AnalyzeRuns());
|
||||
|
@ -88,7 +89,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
[[nodiscard]] HRESULT STDMETHODCALLTYPE CustomTextLayout::Draw(_In_opt_ void* clientDrawingContext,
|
||||
_In_ IDWriteTextRenderer* renderer,
|
||||
FLOAT originX,
|
||||
FLOAT originY)
|
||||
FLOAT originY) noexcept
|
||||
{
|
||||
RETURN_IF_FAILED(_AnalyzeRuns());
|
||||
RETURN_IF_FAILED(_ShapeGlyphRuns());
|
||||
|
@ -146,7 +147,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
}
|
||||
|
||||
// Resequence the resulting runs in order before returning to caller.
|
||||
size_t totalRuns = _runs.size();
|
||||
const size_t totalRuns = _runs.size();
|
||||
std::vector<LinkedRun> runs;
|
||||
runs.resize(totalRuns);
|
||||
|
||||
|
@ -178,7 +179,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
const auto textLength = gsl::narrow<UINT32>(_text.size());
|
||||
|
||||
// Estimate the maximum number of glyph indices needed to hold a string.
|
||||
UINT32 estimatedGlyphCount = _EstimateGlyphCount(textLength);
|
||||
const UINT32 estimatedGlyphCount = _EstimateGlyphCount(textLength);
|
||||
|
||||
_glyphIndices.resize(estimatedGlyphCount);
|
||||
_glyphOffsets.resize(estimatedGlyphCount);
|
||||
|
@ -230,9 +231,9 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// will shape as if the line is not broken.
|
||||
|
||||
Run& run = _runs.at(runIndex);
|
||||
UINT32 textStart = run.textStart;
|
||||
UINT32 textLength = run.textLength;
|
||||
UINT32 maxGlyphCount = static_cast<UINT32>(_glyphIndices.size() - glyphStart);
|
||||
const UINT32 textStart = run.textStart;
|
||||
const UINT32 textLength = run.textLength;
|
||||
UINT32 maxGlyphCount = gsl::narrow<UINT32>(_glyphIndices.size() - glyphStart);
|
||||
UINT32 actualGlyphCount = 0;
|
||||
|
||||
run.glyphStart = glyphStart;
|
||||
|
@ -268,7 +269,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
do
|
||||
{
|
||||
hr = _analyzer->GetGlyphs(
|
||||
&_text[textStart],
|
||||
&_text.at(textStart),
|
||||
textLength,
|
||||
run.fontFace.Get(),
|
||||
run.isSideways, // isSideways,
|
||||
|
@ -280,10 +281,10 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
nullptr, // featureLengths
|
||||
0, // featureCount
|
||||
maxGlyphCount, // maxGlyphCount
|
||||
&_glyphClusters[textStart],
|
||||
&textProps[0],
|
||||
&_glyphIndices[glyphStart],
|
||||
&glyphProps[0],
|
||||
&_glyphClusters.at(textStart),
|
||||
&textProps.at(0),
|
||||
&_glyphIndices.at(glyphStart),
|
||||
&glyphProps.at(0),
|
||||
&actualGlyphCount);
|
||||
tries++;
|
||||
|
||||
|
@ -291,7 +292,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
{
|
||||
// Try again using a larger buffer.
|
||||
maxGlyphCount = _EstimateGlyphCount(maxGlyphCount);
|
||||
UINT32 totalGlyphsArrayCount = glyphStart + maxGlyphCount;
|
||||
const UINT32 totalGlyphsArrayCount = glyphStart + maxGlyphCount;
|
||||
|
||||
glyphProps.resize(maxGlyphCount);
|
||||
_glyphIndices.resize(totalGlyphsArrayCount);
|
||||
|
@ -306,19 +307,19 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
|
||||
// Get the placement of the all the glyphs.
|
||||
|
||||
_glyphAdvances.resize(std::max(static_cast<size_t>(glyphStart + actualGlyphCount), _glyphAdvances.size()));
|
||||
_glyphOffsets.resize(std::max(static_cast<size_t>(glyphStart + actualGlyphCount), _glyphOffsets.size()));
|
||||
_glyphAdvances.resize(std::max(gsl::narrow_cast<size_t>(glyphStart) + gsl::narrow_cast<size_t>(actualGlyphCount), _glyphAdvances.size()));
|
||||
_glyphOffsets.resize(std::max(gsl::narrow_cast<size_t>(glyphStart) + gsl::narrow_cast<size_t>(actualGlyphCount), _glyphOffsets.size()));
|
||||
|
||||
const auto fontSizeFormat = _format->GetFontSize();
|
||||
const auto fontSize = fontSizeFormat * run.fontScale;
|
||||
|
||||
hr = _analyzer->GetGlyphPlacements(
|
||||
&_text[textStart],
|
||||
&_glyphClusters[textStart],
|
||||
&textProps[0],
|
||||
&_text.at(textStart),
|
||||
&_glyphClusters.at(textStart),
|
||||
&textProps.at(0),
|
||||
textLength,
|
||||
&_glyphIndices[glyphStart],
|
||||
&glyphProps[0],
|
||||
&_glyphIndices.at(glyphStart),
|
||||
&glyphProps.at(0),
|
||||
actualGlyphCount,
|
||||
run.fontFace.Get(),
|
||||
fontSize,
|
||||
|
@ -329,8 +330,8 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
NULL, // features
|
||||
NULL, // featureRangeLengths
|
||||
0, // featureRanges
|
||||
&_glyphAdvances[glyphStart],
|
||||
&_glyphOffsets[glyphStart]);
|
||||
&_glyphAdvances.at(glyphStart),
|
||||
&_glyphOffsets.at(glyphStart));
|
||||
|
||||
RETURN_IF_FAILED(hr);
|
||||
|
||||
|
@ -391,13 +392,13 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
for (auto i = run.glyphStart; i < (run.glyphStart + run.glyphCount); i++)
|
||||
{
|
||||
// Advance is how wide in pixels the glyph is
|
||||
auto& advance = _glyphAdvances[i];
|
||||
auto& advance = _glyphAdvances.at(i);
|
||||
|
||||
// Offsets is how far to move the origin (in pixels) from where it is
|
||||
auto& offset = _glyphOffsets[i];
|
||||
auto& offset = _glyphOffsets.at(i);
|
||||
|
||||
// Get how many columns we expected the glyph to have and mutiply into pixels.
|
||||
const auto columns = _textClusterColumns[i];
|
||||
const auto columns = _textClusterColumns.at(i);
|
||||
const auto advanceExpected = static_cast<float>(columns * _width);
|
||||
|
||||
// If what we expect is bigger than what we have... pad it out.
|
||||
|
@ -419,7 +420,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// We need to retrieve the design information for this specific glyph so we can figure out the appropriate
|
||||
// height proportional to the width that we desire.
|
||||
INT32 advanceInDesignUnits;
|
||||
RETURN_IF_FAILED(run.fontFace->GetDesignGlyphAdvances(1, &_glyphIndices[i], &advanceInDesignUnits));
|
||||
RETURN_IF_FAILED(run.fontFace->GetDesignGlyphAdvances(1, &_glyphIndices.at(i), &advanceInDesignUnits));
|
||||
|
||||
// When things are drawn, we want the font size (as specified in the base font in the original format)
|
||||
// to be scaled by some factor.
|
||||
|
@ -467,6 +468,8 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
IDWriteTextRenderer* renderer,
|
||||
const D2D_POINT_2F origin) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, renderer);
|
||||
|
||||
try
|
||||
{
|
||||
// We're going to start from the origin given and walk to the right for each
|
||||
|
@ -477,21 +480,21 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
for (UINT32 runIndex = 0; runIndex < _runs.size(); ++runIndex)
|
||||
{
|
||||
// Get the run
|
||||
Run& run = _runs.at(runIndex);
|
||||
const Run& run = _runs.at(runIndex);
|
||||
|
||||
// Prepare the glyph run and description objects by converting our
|
||||
// internal storage representation into something that matches DWrite's structures.
|
||||
DWRITE_GLYPH_RUN glyphRun = { 0 };
|
||||
DWRITE_GLYPH_RUN glyphRun;
|
||||
glyphRun.bidiLevel = run.bidiLevel;
|
||||
glyphRun.fontEmSize = _format->GetFontSize() * run.fontScale;
|
||||
glyphRun.fontFace = run.fontFace.Get();
|
||||
glyphRun.glyphAdvances = _glyphAdvances.data() + run.glyphStart;
|
||||
glyphRun.glyphAdvances = &_glyphAdvances.at(run.glyphStart);
|
||||
glyphRun.glyphCount = run.glyphCount;
|
||||
glyphRun.glyphIndices = _glyphIndices.data() + run.glyphStart;
|
||||
glyphRun.glyphOffsets = _glyphOffsets.data() + run.glyphStart;
|
||||
glyphRun.glyphIndices = &_glyphIndices.at(run.glyphStart);
|
||||
glyphRun.glyphOffsets = &_glyphOffsets.at(run.glyphStart);
|
||||
glyphRun.isSideways = false;
|
||||
|
||||
DWRITE_GLYPH_RUN_DESCRIPTION glyphRunDescription = { 0 };
|
||||
DWRITE_GLYPH_RUN_DESCRIPTION glyphRunDescription;
|
||||
glyphRunDescription.clusterMap = _glyphClusters.data();
|
||||
glyphRunDescription.localeName = _localeName.data();
|
||||
glyphRunDescription.string = _text.data();
|
||||
|
@ -539,7 +542,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// Return Value:
|
||||
// - An estimate of how many glyph spaces may be required in the shaping arrays
|
||||
// to hold the data from a string of the given length.
|
||||
[[nodiscard]] UINT32 CustomTextLayout::_EstimateGlyphCount(const UINT32 textLength) noexcept
|
||||
[[nodiscard]] constexpr UINT32 CustomTextLayout::_EstimateGlyphCount(const UINT32 textLength) noexcept
|
||||
{
|
||||
// This formula is from https://docs.microsoft.com/en-us/windows/desktop/api/dwrite/nf-dwrite-idwritetextanalyzer-getglyphs
|
||||
// and is the recommended formula for estimating buffer size for glyph count.
|
||||
|
@ -561,12 +564,15 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textString);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textLength);
|
||||
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
|
||||
if (textPosition < _text.size())
|
||||
{
|
||||
*textString = _text.data() + textPosition;
|
||||
*textString = &_text.at(textPosition);
|
||||
*textLength = gsl::narrow<UINT32>(_text.size()) - textPosition;
|
||||
}
|
||||
|
||||
|
@ -585,8 +591,11 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - S_OK or appropriate STL/GSL failure code.
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE CustomTextLayout::GetTextBeforePosition(UINT32 textPosition,
|
||||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength)
|
||||
_Out_ UINT32* textLength) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textString);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textLength);
|
||||
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
|
||||
|
@ -606,7 +615,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - The reading direction held for this layout from construction
|
||||
[[nodiscard]] DWRITE_READING_DIRECTION STDMETHODCALLTYPE CustomTextLayout::GetParagraphReadingDirection()
|
||||
[[nodiscard]] DWRITE_READING_DIRECTION STDMETHODCALLTYPE CustomTextLayout::GetParagraphReadingDirection() noexcept
|
||||
{
|
||||
return _readingDirection;
|
||||
}
|
||||
|
@ -622,8 +631,11 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - S_OK or appropriate STL/GSL failure code.
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE CustomTextLayout::GetLocaleName(UINT32 textPosition,
|
||||
_Out_ UINT32* textLength,
|
||||
_Outptr_result_z_ WCHAR const** localeName)
|
||||
_Outptr_result_z_ WCHAR const** localeName) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textLength);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, localeName);
|
||||
|
||||
*localeName = _localeName.data();
|
||||
*textLength = gsl::narrow<UINT32>(_text.size()) - textPosition;
|
||||
|
||||
|
@ -641,8 +653,11 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - S_OK or appropriate STL/GSL failure code.
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE CustomTextLayout::GetNumberSubstitution(UINT32 textPosition,
|
||||
_Out_ UINT32* textLength,
|
||||
_COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution)
|
||||
_COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textLength);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, numberSubstitution);
|
||||
|
||||
*numberSubstitution = nullptr;
|
||||
*textLength = gsl::narrow<UINT32>(_text.size()) - textPosition;
|
||||
|
||||
|
@ -799,7 +814,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
RETURN_IF_FAILED(format1->GetFontCollection(&collection));
|
||||
|
||||
std::wstring familyName;
|
||||
familyName.resize(format1->GetFontFamilyNameLength() + 1);
|
||||
familyName.resize(gsl::narrow_cast<size_t>(format1->GetFontFamilyNameLength()) + 1);
|
||||
RETURN_IF_FAILED(format1->GetFontFamilyName(familyName.data(), gsl::narrow<UINT32>(familyName.size())));
|
||||
|
||||
const auto weight = format1->GetFontWeight();
|
||||
|
@ -912,7 +927,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
if (textLength < runTextLength)
|
||||
{
|
||||
runTextLength = textLength; // Limit to what's actually left.
|
||||
UINT32 runTextStart = run.textStart;
|
||||
const UINT32 runTextStart = run.textStart;
|
||||
|
||||
_SplitCurrentRun(runTextStart + runTextLength);
|
||||
}
|
||||
|
@ -940,12 +955,12 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
|
|||
// - <none> - Updates internal state
|
||||
void CustomTextLayout::_SetCurrentRun(const UINT32 textPosition)
|
||||
{
|
||||
if (_runIndex < _runs.size() && _runs[_runIndex].ContainsTextPosition(textPosition))
|
||||
if (_runIndex < _runs.size() && _runs.at(_runIndex).ContainsTextPosition(textPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_runIndex = static_cast<UINT32>(
|
||||
_runIndex = gsl::narrow<UINT32>(
|
||||
std::find(_runs.begin(), _runs.end(), textPosition) - _runs.begin());
|
||||
}
|
||||
|
||||
|
@ -957,13 +972,13 @@ void CustomTextLayout::_SetCurrentRun(const UINT32 textPosition)
|
|||
// - <none> - Updates internal state, the back half will be selected after running
|
||||
void CustomTextLayout::_SplitCurrentRun(const UINT32 splitPosition)
|
||||
{
|
||||
UINT32 runTextStart = _runs.at(_runIndex).textStart;
|
||||
const UINT32 runTextStart = _runs.at(_runIndex).textStart;
|
||||
|
||||
if (splitPosition <= runTextStart)
|
||||
return; // no change
|
||||
|
||||
// Grow runs by one.
|
||||
size_t totalRuns = _runs.size();
|
||||
const size_t totalRuns = _runs.size();
|
||||
try
|
||||
{
|
||||
_runs.resize(totalRuns + 1);
|
||||
|
@ -974,16 +989,16 @@ void CustomTextLayout::_SplitCurrentRun(const UINT32 splitPosition)
|
|||
}
|
||||
|
||||
// Copy the old run to the end.
|
||||
LinkedRun& frontHalf = _runs[_runIndex];
|
||||
LinkedRun& frontHalf = _runs.at(_runIndex);
|
||||
LinkedRun& backHalf = _runs.back();
|
||||
backHalf = frontHalf;
|
||||
|
||||
// Adjust runs' text positions and lengths.
|
||||
UINT32 splitPoint = splitPosition - runTextStart;
|
||||
const UINT32 splitPoint = splitPosition - runTextStart;
|
||||
backHalf.textStart += splitPoint;
|
||||
backHalf.textLength -= splitPoint;
|
||||
frontHalf.textLength = splitPoint;
|
||||
frontHalf.nextRunIndex = static_cast<UINT32>(totalRuns);
|
||||
_runIndex = static_cast<UINT32>(totalRuns);
|
||||
frontHalf.nextRunIndex = gsl::narrow<UINT32>(totalRuns);
|
||||
_runIndex = gsl::narrow<UINT32>(totalRuns);
|
||||
}
|
||||
#pragma endregion
|
||||
|
|
|
@ -19,10 +19,10 @@ namespace Microsoft::Console::Render
|
|||
public:
|
||||
// Based on the Windows 7 SDK sample at https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomLayout
|
||||
|
||||
CustomTextLayout(IDWriteFactory1* const factory,
|
||||
IDWriteTextAnalyzer1* const analyzer,
|
||||
IDWriteTextFormat* const format,
|
||||
IDWriteFontFace1* const font,
|
||||
CustomTextLayout(gsl::not_null<IDWriteFactory1*> const factory,
|
||||
gsl::not_null<IDWriteTextAnalyzer1*> const analyzer,
|
||||
gsl::not_null<IDWriteTextFormat*> const format,
|
||||
gsl::not_null<IDWriteFontFace1*> const font,
|
||||
const std::basic_string_view<::Microsoft::Console::Render::Cluster> clusters,
|
||||
size_t const width);
|
||||
|
||||
|
@ -32,43 +32,43 @@ namespace Microsoft::Console::Render
|
|||
[[nodiscard]] HRESULT STDMETHODCALLTYPE Draw(_In_opt_ void* clientDrawingContext,
|
||||
_In_ IDWriteTextRenderer* renderer,
|
||||
FLOAT originX,
|
||||
FLOAT originY);
|
||||
FLOAT originY) noexcept;
|
||||
|
||||
// IDWriteTextAnalysisSource methods
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 textPosition,
|
||||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength) override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 textPosition,
|
||||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength) override;
|
||||
[[nodiscard]] virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 textPosition,
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 textPosition,
|
||||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 textPosition,
|
||||
_Outptr_result_buffer_(*textLength) WCHAR const** textString,
|
||||
_Out_ UINT32* textLength) noexcept override;
|
||||
[[nodiscard]] DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() noexcept override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 textPosition,
|
||||
_Out_ UINT32* textLength,
|
||||
_Outptr_result_z_ WCHAR const** localeName) noexcept override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetNumberSubstitution(UINT32 textPosition,
|
||||
_Out_ UINT32* textLength,
|
||||
_Outptr_result_z_ WCHAR const** localeName) override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution(UINT32 textPosition,
|
||||
_Out_ UINT32* textLength,
|
||||
_COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution) override;
|
||||
_COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution) noexcept override;
|
||||
|
||||
// IDWriteTextAnalysisSink methods
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE SetScriptAnalysis(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE SetLineBreakpoints(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_reads_(textLength) DWRITE_LINE_BREAKPOINT const* lineBreakpoints) override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE SetBidiLevel(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
UINT8 explicitLevel,
|
||||
UINT8 resolvedLevel) override;
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE SetNumberSubstitution(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_ IDWriteNumberSubstitution* numberSubstitution) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE SetScriptAnalysis(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE SetLineBreakpoints(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_reads_(textLength) DWRITE_LINE_BREAKPOINT const* lineBreakpoints) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE SetBidiLevel(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
UINT8 explicitLevel,
|
||||
UINT8 resolvedLevel) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE SetNumberSubstitution(UINT32 textPosition,
|
||||
UINT32 textLength,
|
||||
_In_ IDWriteNumberSubstitution* numberSubstitution) override;
|
||||
|
||||
protected:
|
||||
// A single contiguous run of characters containing the same analysis results.
|
||||
struct Run
|
||||
{
|
||||
Run() :
|
||||
Run() noexcept :
|
||||
textStart(),
|
||||
textLength(),
|
||||
glyphStart(),
|
||||
|
@ -93,12 +93,12 @@ namespace Microsoft::Console::Render
|
|||
::Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace;
|
||||
FLOAT fontScale;
|
||||
|
||||
inline bool ContainsTextPosition(UINT32 desiredTextPosition) const
|
||||
inline bool ContainsTextPosition(UINT32 desiredTextPosition) const noexcept
|
||||
{
|
||||
return desiredTextPosition >= textStart && desiredTextPosition < textStart + textLength;
|
||||
}
|
||||
|
||||
inline bool operator==(UINT32 desiredTextPosition) const
|
||||
inline bool operator==(UINT32 desiredTextPosition) const noexcept
|
||||
{
|
||||
// Search by text position using std::find
|
||||
return ContainsTextPosition(desiredTextPosition);
|
||||
|
@ -108,7 +108,7 @@ namespace Microsoft::Console::Render
|
|||
// Single text analysis run, which points to the next run.
|
||||
struct LinkedRun : Run
|
||||
{
|
||||
LinkedRun() :
|
||||
LinkedRun() noexcept :
|
||||
nextRunIndex(0)
|
||||
{
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace Microsoft::Console::Render
|
|||
IDWriteTextRenderer* renderer,
|
||||
const D2D_POINT_2F origin) noexcept;
|
||||
|
||||
[[nodiscard]] static UINT32 _EstimateGlyphCount(const UINT32 textLength) noexcept;
|
||||
[[nodiscard]] static constexpr UINT32 _EstimateGlyphCount(const UINT32 textLength) noexcept;
|
||||
|
||||
private:
|
||||
const ::Microsoft::WRL::ComPtr<IDWriteFactory1> _factory;
|
||||
|
|
|
@ -21,8 +21,10 @@ using namespace Microsoft::Console::Render;
|
|||
// Return Value:
|
||||
// - S_OK
|
||||
[[nodiscard]] HRESULT CustomTextRenderer::IsPixelSnappingDisabled(void* /*clientDrawingContext*/,
|
||||
_Out_ BOOL* isDisabled)
|
||||
_Out_ BOOL* isDisabled) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, isDisabled);
|
||||
|
||||
*isDisabled = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -38,9 +40,12 @@ using namespace Microsoft::Console::Render;
|
|||
// Return Value:
|
||||
// - S_OK
|
||||
[[nodiscard]] HRESULT CustomTextRenderer::GetPixelsPerDip(void* clientDrawingContext,
|
||||
_Out_ FLOAT* pixelsPerDip)
|
||||
_Out_ FLOAT* pixelsPerDip) noexcept
|
||||
{
|
||||
DrawingContext* drawingContext = static_cast<DrawingContext*>(clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pixelsPerDip);
|
||||
|
||||
const DrawingContext* drawingContext = static_cast<DrawingContext*>(clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, drawingContext);
|
||||
|
||||
float dpiX, dpiY;
|
||||
drawingContext->renderTarget->GetDpi(&dpiX, &dpiY);
|
||||
|
@ -58,12 +63,24 @@ using namespace Microsoft::Console::Render;
|
|||
// Return Value:
|
||||
// - S_OK
|
||||
[[nodiscard]] HRESULT CustomTextRenderer::GetCurrentTransform(void* clientDrawingContext,
|
||||
DWRITE_MATRIX* transform)
|
||||
DWRITE_MATRIX* transform) noexcept
|
||||
{
|
||||
DrawingContext* drawingContext = static_cast<DrawingContext*>(clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, transform);
|
||||
|
||||
const DrawingContext* drawingContext = static_cast<DrawingContext*>(clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, drawingContext);
|
||||
|
||||
// Retrieve as D2D1 matrix then copy into DWRITE matrix.
|
||||
D2D1_MATRIX_3X2_F d2d1Matrix{ 0 };
|
||||
drawingContext->renderTarget->GetTransform(&d2d1Matrix);
|
||||
|
||||
transform->dx = d2d1Matrix.dx;
|
||||
transform->dy = d2d1Matrix.dy;
|
||||
transform->m11 = d2d1Matrix.m11;
|
||||
transform->m12 = d2d1Matrix.m12;
|
||||
transform->m21 = d2d1Matrix.m21;
|
||||
transform->m22 = d2d1Matrix.m22;
|
||||
|
||||
// Matrix structures are defined identically
|
||||
drawingContext->renderTarget->GetTransform((D2D1_MATRIX_3X2_F*)transform);
|
||||
return S_OK;
|
||||
}
|
||||
#pragma endregion
|
||||
|
@ -88,17 +105,16 @@ using namespace Microsoft::Console::Render;
|
|||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_UNDERLINE* underline,
|
||||
IUnknown* clientDrawingEffect)
|
||||
IUnknown* clientDrawingEffect) noexcept
|
||||
{
|
||||
_FillRectangle(clientDrawingContext,
|
||||
clientDrawingEffect,
|
||||
baselineOriginX,
|
||||
baselineOriginY + underline->offset,
|
||||
underline->width,
|
||||
underline->thickness,
|
||||
underline->readingDirection,
|
||||
underline->flowDirection);
|
||||
return S_OK;
|
||||
return _FillRectangle(clientDrawingContext,
|
||||
clientDrawingEffect,
|
||||
baselineOriginX,
|
||||
baselineOriginY + underline->offset,
|
||||
underline->width,
|
||||
underline->thickness,
|
||||
underline->readingDirection,
|
||||
underline->flowDirection);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -120,17 +136,16 @@ using namespace Microsoft::Console::Render;
|
|||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_STRIKETHROUGH* strikethrough,
|
||||
IUnknown* clientDrawingEffect)
|
||||
IUnknown* clientDrawingEffect) noexcept
|
||||
{
|
||||
_FillRectangle(clientDrawingContext,
|
||||
clientDrawingEffect,
|
||||
baselineOriginX,
|
||||
baselineOriginY + strikethrough->offset,
|
||||
strikethrough->width,
|
||||
strikethrough->thickness,
|
||||
strikethrough->readingDirection,
|
||||
strikethrough->flowDirection);
|
||||
return S_OK;
|
||||
return _FillRectangle(clientDrawingContext,
|
||||
clientDrawingEffect,
|
||||
baselineOriginX,
|
||||
baselineOriginY + strikethrough->offset,
|
||||
strikethrough->width,
|
||||
strikethrough->thickness,
|
||||
strikethrough->readingDirection,
|
||||
strikethrough->flowDirection);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -146,16 +161,17 @@ using namespace Microsoft::Console::Render;
|
|||
// - flowDirection - textual flow information that could affect the rectangle
|
||||
// Return Value:
|
||||
// - S_OK
|
||||
void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
||||
IUnknown* clientDrawingEffect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float thickness,
|
||||
DWRITE_READING_DIRECTION /*readingDirection*/,
|
||||
DWRITE_FLOW_DIRECTION /*flowDirection*/)
|
||||
[[nodiscard]] HRESULT CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
||||
IUnknown* clientDrawingEffect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float thickness,
|
||||
DWRITE_READING_DIRECTION /*readingDirection*/,
|
||||
DWRITE_FLOW_DIRECTION /*flowDirection*/) noexcept
|
||||
{
|
||||
DrawingContext* drawingContext = static_cast<DrawingContext*>(clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, drawingContext);
|
||||
|
||||
// Get brush
|
||||
ID2D1Brush* brush = drawingContext->foregroundBrush;
|
||||
|
@ -165,8 +181,10 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
brush = static_cast<ID2D1Brush*>(clientDrawingEffect);
|
||||
}
|
||||
|
||||
D2D1_RECT_F rect = D2D1::RectF(x, y, x + width, y + thickness);
|
||||
const D2D1_RECT_F rect = D2D1::RectF(x, y, x + width, y + thickness);
|
||||
drawingContext->renderTarget->FillRectangle(&rect, brush);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -189,8 +207,10 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
IDWriteInlineObject* inlineObject,
|
||||
BOOL isSideways,
|
||||
BOOL isRightToLeft,
|
||||
IUnknown* clientDrawingEffect)
|
||||
IUnknown* clientDrawingEffect) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, inlineObject);
|
||||
|
||||
return inlineObject->Draw(clientDrawingContext,
|
||||
this,
|
||||
originX,
|
||||
|
@ -233,12 +253,11 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
|
||||
// Since we've delegated the drawing of the background of the text into this function, the origin passed in isn't actually the baseline.
|
||||
// It's the top left corner. Save that off first.
|
||||
D2D1_POINT_2F origin = D2D1::Point2F(baselineOriginX, baselineOriginY);
|
||||
const D2D1_POINT_2F origin = D2D1::Point2F(baselineOriginX, baselineOriginY);
|
||||
|
||||
// Then make a copy for the baseline origin (which is part way down the left side of the text, not the top or bottom).
|
||||
// We'll use this baseline Origin for drawing the actual text.
|
||||
D2D1_POINT_2F baselineOrigin = origin;
|
||||
baselineOrigin.y += drawingContext->spacing.baseline;
|
||||
const D2D1_POINT_2F baselineOrigin{ origin.x, origin.y + drawingContext->spacing.baseline };
|
||||
|
||||
::Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2dContext;
|
||||
RETURN_IF_FAILED(drawingContext->renderTarget->QueryInterface(d2dContext.GetAddressOf()));
|
||||
|
@ -249,11 +268,9 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
rect.bottom = rect.top + drawingContext->cellSize.height;
|
||||
rect.left = origin.x;
|
||||
rect.right = rect.left;
|
||||
const auto advancesSpan = gsl::make_span(glyphRun->glyphAdvances, glyphRun->glyphCount);
|
||||
|
||||
for (UINT32 i = 0; i < glyphRun->glyphCount; i++)
|
||||
{
|
||||
rect.right += glyphRun->glyphAdvances[i];
|
||||
}
|
||||
rect.right = std::accumulate(advancesSpan.cbegin(), advancesSpan.cend(), rect.right);
|
||||
|
||||
d2dContext->FillRectangle(rect, drawingContext->backgroundBrush);
|
||||
|
||||
|
@ -270,7 +287,7 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
RETURN_IF_FAILED(drawingContext->dwriteFactory->QueryInterface(dwriteFactory4.GetAddressOf()));
|
||||
|
||||
// The list of glyph image formats this renderer is prepared to support.
|
||||
DWRITE_GLYPH_IMAGE_FORMATS supportedFormats =
|
||||
const DWRITE_GLYPH_IMAGE_FORMATS supportedFormats =
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_CFF |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_COLR |
|
||||
|
@ -283,14 +300,14 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
// Determine whether there are any color glyph runs within glyphRun. If
|
||||
// there are, glyphRunEnumerator can be used to iterate through them.
|
||||
::Microsoft::WRL::ComPtr<IDWriteColorGlyphRunEnumerator1> glyphRunEnumerator;
|
||||
HRESULT hr = dwriteFactory4->TranslateColorGlyphRun(baselineOrigin,
|
||||
glyphRun,
|
||||
glyphRunDescription,
|
||||
supportedFormats,
|
||||
measuringMode,
|
||||
nullptr,
|
||||
0,
|
||||
&glyphRunEnumerator);
|
||||
const HRESULT hr = dwriteFactory4->TranslateColorGlyphRun(baselineOrigin,
|
||||
glyphRun,
|
||||
glyphRunDescription,
|
||||
supportedFormats,
|
||||
measuringMode,
|
||||
nullptr,
|
||||
0,
|
||||
&glyphRunEnumerator);
|
||||
|
||||
// If the analysis found no color glyphs in the run, just draw normally.
|
||||
if (hr == DWRITE_E_NOCOLOR)
|
||||
|
@ -320,7 +337,7 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
DWRITE_COLOR_GLYPH_RUN1 const* colorRun;
|
||||
RETURN_IF_FAILED(glyphRunEnumerator->GetCurrentRun(&colorRun));
|
||||
|
||||
D2D1_POINT_2F currentBaselineOrigin = D2D1::Point2F(colorRun->baselineOriginX, colorRun->baselineOriginY);
|
||||
const D2D1_POINT_2F currentBaselineOrigin = D2D1::Point2F(colorRun->baselineOriginX, colorRun->baselineOriginY);
|
||||
|
||||
switch (colorRun->glyphImageFormat)
|
||||
{
|
||||
|
@ -357,7 +374,7 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
// This run is solid-color outlines, either from non-color
|
||||
// glyphs or from COLR glyph layers. Use Direct2D to draw them.
|
||||
|
||||
ID2D1Brush* layerBrush;
|
||||
ID2D1Brush* layerBrush{ nullptr };
|
||||
// The rule is "if 0xffff, use current brush." See:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/dwrite_2/ns-dwrite_2-dwrite_color_glyph_run
|
||||
if (colorRun->paletteIndex == 0xFFFF)
|
||||
|
@ -414,6 +431,11 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
|
||||
ID2D1Brush* brush)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, glyphRun);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, glyphRunDescription);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, brush);
|
||||
|
||||
::Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2dContext;
|
||||
RETURN_IF_FAILED(clientDrawingContext->renderTarget->QueryInterface(d2dContext.GetAddressOf()));
|
||||
|
||||
|
@ -433,8 +455,11 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
D2D1_POINT_2F baselineOrigin,
|
||||
DWRITE_MEASURING_MODE /*measuringMode*/,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/)
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, glyphRun);
|
||||
|
||||
// This is regular text but manually
|
||||
::Microsoft::WRL::ComPtr<ID2D1Factory> d2dFactory;
|
||||
clientDrawingContext->renderTarget->GetFactory(d2dFactory.GetAddressOf());
|
||||
|
@ -473,8 +498,11 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
|
|||
D2D1_POINT_2F baselineOrigin,
|
||||
DWRITE_MEASURING_MODE /*measuringMode*/,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/)
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, clientDrawingContext);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, glyphRun);
|
||||
|
||||
// This is glow text manually
|
||||
::Microsoft::WRL::ComPtr<ID2D1Factory> d2dFactory;
|
||||
clientDrawingContext->renderTarget->GetFactory(d2dFactory.GetAddressOf());
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Microsoft::Console::Render
|
|||
IDWriteFactory* dwriteFactory,
|
||||
const DWRITE_LINE_SPACING spacing,
|
||||
const D2D_SIZE_F cellSize,
|
||||
const D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE)
|
||||
const D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE) noexcept
|
||||
{
|
||||
this->renderTarget = renderTarget;
|
||||
this->foregroundBrush = foregroundBrush;
|
||||
|
@ -42,53 +42,53 @@ namespace Microsoft::Console::Render
|
|||
// https://docs.microsoft.com/en-us/windows/desktop/DirectWrite/how-to-implement-a-custom-text-renderer
|
||||
|
||||
// IDWritePixelSnapping methods
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(void* clientDrawingContext,
|
||||
_Out_ BOOL* isDisabled) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(void* clientDrawingContext,
|
||||
_Out_ BOOL* isDisabled) noexcept override;
|
||||
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(void* clientDrawingContext,
|
||||
_Out_ FLOAT* pixelsPerDip) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetPixelsPerDip(void* clientDrawingContext,
|
||||
_Out_ FLOAT* pixelsPerDip) noexcept override;
|
||||
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(void* clientDrawingContext,
|
||||
_Out_ DWRITE_MATRIX* transform) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetCurrentTransform(void* clientDrawingContext,
|
||||
_Out_ DWRITE_MATRIX* transform) noexcept override;
|
||||
|
||||
// IDWriteTextRenderer methods
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawGlyphRun(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect) override;
|
||||
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawUnderline(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_UNDERLINE* underline,
|
||||
IUnknown* clientDrawingEffect) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawUnderline(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_UNDERLINE* underline,
|
||||
IUnknown* clientDrawingEffect) noexcept override;
|
||||
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_STRIKETHROUGH* strikethrough,
|
||||
IUnknown* clientDrawingEffect) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawStrikethrough(void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
_In_ const DWRITE_STRIKETHROUGH* strikethrough,
|
||||
IUnknown* clientDrawingEffect) noexcept override;
|
||||
|
||||
[[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL isSideways,
|
||||
BOOL isRightToLeft,
|
||||
IUnknown* clientDrawingEffect) override;
|
||||
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawInlineObject(void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL isSideways,
|
||||
BOOL isRightToLeft,
|
||||
IUnknown* clientDrawingEffect) noexcept override;
|
||||
|
||||
private:
|
||||
void _FillRectangle(void* clientDrawingContext,
|
||||
IUnknown* clientDrawingEffect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float thickness,
|
||||
DWRITE_READING_DIRECTION readingDirection,
|
||||
DWRITE_FLOW_DIRECTION flowDirection);
|
||||
[[nodiscard]] HRESULT _FillRectangle(void* clientDrawingContext,
|
||||
IUnknown* clientDrawingEffect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float thickness,
|
||||
DWRITE_READING_DIRECTION readingDirection,
|
||||
DWRITE_FLOW_DIRECTION flowDirection) noexcept;
|
||||
|
||||
[[nodiscard]] HRESULT _DrawBasicGlyphRun(DrawingContext* clientDrawingContext,
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
|
@ -101,12 +101,12 @@ namespace Microsoft::Console::Render
|
|||
D2D1_POINT_2F baselineOrigin,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription);
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription) noexcept;
|
||||
|
||||
[[nodiscard]] HRESULT _DrawGlowGlyphRun(DrawingContext* clientDrawingContext,
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
_In_ const DWRITE_GLYPH_RUN* glyphRun,
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription);
|
||||
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription) noexcept;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#pragma hdrstop
|
||||
|
||||
static constexpr float POINTS_PER_INCH = 72.0f;
|
||||
static std::wstring FALLBACK_FONT_FACE = L"Consolas";
|
||||
static constexpr std::wstring_view FALLBACK_FONT_FACE = L"Consolas";
|
||||
static constexpr std::wstring_view FALLBACK_LOCALE = L"en-us";
|
||||
|
||||
using namespace Microsoft::Console::Render;
|
||||
|
@ -24,6 +24,8 @@ using namespace Microsoft::Console::Types;
|
|||
// Routine Description:
|
||||
// - Constructs a DirectX-based renderer for console text
|
||||
// which primarily uses DirectWrite on a Direct2D surface
|
||||
#pragma warning(suppress : 26455)
|
||||
// TODO GH 2683: The default constructor should not throw.
|
||||
DxEngine::DxEngine() :
|
||||
RenderEngineBase(),
|
||||
_isInvalidUsed{ false },
|
||||
|
@ -129,7 +131,7 @@ DxEngine::~DxEngine()
|
|||
_ReleaseDeviceResources();
|
||||
}
|
||||
|
||||
auto freeOnFail = wil::scope_exit([&] { _ReleaseDeviceResources(); });
|
||||
auto freeOnFail = wil::scope_exit([&]() noexcept { _ReleaseDeviceResources(); });
|
||||
|
||||
RETURN_IF_FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&_dxgiFactory2)));
|
||||
|
||||
|
@ -147,39 +149,37 @@ DxEngine::~DxEngine()
|
|||
// D3D11_CREATE_DEVICE_DEBUG |
|
||||
D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
|
||||
D3D_FEATURE_LEVEL FeatureLevels[] = {
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
D3D_FEATURE_LEVEL_9_1,
|
||||
};
|
||||
const std::array<D3D_FEATURE_LEVEL, 5> FeatureLevels{ D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
D3D_FEATURE_LEVEL_9_1 };
|
||||
|
||||
// Trying hardware first for maximum performance, then trying WARP (software) renderer second
|
||||
// in case we're running inside a downlevel VM where hardware passthrough isn't enabled like
|
||||
// for Windows 7 in a VM.
|
||||
const auto hardwareResult = D3D11CreateDevice(NULL,
|
||||
const auto hardwareResult = D3D11CreateDevice(nullptr,
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
nullptr,
|
||||
DeviceFlags,
|
||||
FeatureLevels,
|
||||
ARRAYSIZE(FeatureLevels),
|
||||
FeatureLevels.data(),
|
||||
gsl::narrow_cast<UINT>(FeatureLevels.size()),
|
||||
D3D11_SDK_VERSION,
|
||||
&_d3dDevice,
|
||||
NULL,
|
||||
nullptr,
|
||||
&_d3dDeviceContext);
|
||||
|
||||
if (FAILED(hardwareResult))
|
||||
{
|
||||
RETURN_IF_FAILED(D3D11CreateDevice(NULL,
|
||||
RETURN_IF_FAILED(D3D11CreateDevice(nullptr,
|
||||
D3D_DRIVER_TYPE_WARP,
|
||||
NULL,
|
||||
nullptr,
|
||||
DeviceFlags,
|
||||
FeatureLevels,
|
||||
ARRAYSIZE(FeatureLevels),
|
||||
FeatureLevels.data(),
|
||||
gsl::narrow_cast<UINT>(FeatureLevels.size()),
|
||||
D3D11_SDK_VERSION,
|
||||
&_d3dDevice,
|
||||
NULL,
|
||||
nullptr,
|
||||
&_d3dDeviceContext));
|
||||
}
|
||||
|
||||
|
@ -196,58 +196,62 @@ DxEngine::~DxEngine()
|
|||
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
SwapChainDesc.Scaling = DXGI_SCALING_NONE;
|
||||
|
||||
switch (_chainMode)
|
||||
try
|
||||
{
|
||||
case SwapChainMode::ForHwnd:
|
||||
{
|
||||
// use the HWND's dimensions for the swap chain dimensions.
|
||||
RECT rect = { 0 };
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetClientRect(_hwndTarget, &rect));
|
||||
|
||||
SwapChainDesc.Width = rect.right - rect.left;
|
||||
SwapChainDesc.Height = rect.bottom - rect.top;
|
||||
|
||||
// We can't do alpha for HWNDs. Set to ignore. It will fail otherwise.
|
||||
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
const auto createSwapChainResult = _dxgiFactory2->CreateSwapChainForHwnd(_d3dDevice.Get(),
|
||||
_hwndTarget,
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&_dxgiSwapChain);
|
||||
if (FAILED(createSwapChainResult))
|
||||
switch (_chainMode)
|
||||
{
|
||||
SwapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForHwnd(_d3dDevice.Get(),
|
||||
_hwndTarget,
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
case SwapChainMode::ForHwnd:
|
||||
{
|
||||
// use the HWND's dimensions for the swap chain dimensions.
|
||||
RECT rect = { 0 };
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetClientRect(_hwndTarget, &rect));
|
||||
|
||||
SwapChainDesc.Width = rect.right - rect.left;
|
||||
SwapChainDesc.Height = rect.bottom - rect.top;
|
||||
|
||||
// We can't do alpha for HWNDs. Set to ignore. It will fail otherwise.
|
||||
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
const auto createSwapChainResult = _dxgiFactory2->CreateSwapChainForHwnd(_d3dDevice.Get(),
|
||||
_hwndTarget,
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&_dxgiSwapChain);
|
||||
if (FAILED(createSwapChainResult))
|
||||
{
|
||||
SwapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForHwnd(_d3dDevice.Get(),
|
||||
_hwndTarget,
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SwapChainMode::ForComposition:
|
||||
{
|
||||
// Use the given target size for compositions.
|
||||
SwapChainDesc.Width = _displaySizePixels.cx;
|
||||
SwapChainDesc.Height = _displaySizePixels.cy;
|
||||
|
||||
break;
|
||||
}
|
||||
case SwapChainMode::ForComposition:
|
||||
{
|
||||
// Use the given target size for compositions.
|
||||
SwapChainDesc.Width = _displaySizePixels.cx;
|
||||
SwapChainDesc.Height = _displaySizePixels.cy;
|
||||
// We're doing advanced composition pretty much for the purpose of pretty alpha, so turn it on.
|
||||
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
|
||||
// It's 100% required to use scaling mode stretch for composition. There is no other choice.
|
||||
SwapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
|
||||
// We're doing advanced composition pretty much for the purpose of pretty alpha, so turn it on.
|
||||
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
|
||||
// It's 100% required to use scaling mode stretch for composition. There is no other choice.
|
||||
SwapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
|
||||
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(),
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
THROW_HR(E_NOTIMPL);
|
||||
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(),
|
||||
&SwapChainDesc,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
THROW_HR(E_NOTIMPL);
|
||||
}
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
// With a new swap chain, mark the entire thing as invalid.
|
||||
RETURN_IF_FAILED(InvalidateAll());
|
||||
|
@ -265,9 +269,14 @@ DxEngine::~DxEngine()
|
|||
freeOnFail.release(); // don't need to release if we made it to the bottom and everything was good.
|
||||
|
||||
// Notify that swap chain changed.
|
||||
|
||||
if (_pfn)
|
||||
{
|
||||
_pfn();
|
||||
try
|
||||
{
|
||||
_pfn();
|
||||
}
|
||||
CATCH_LOG(); // A failure in the notification function isn't a failure to prepare, so just log it and go on.
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -275,54 +284,57 @@ DxEngine::~DxEngine()
|
|||
|
||||
[[nodiscard]] HRESULT DxEngine::_PrepareRenderTarget() noexcept
|
||||
{
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&_dxgiSurface)));
|
||||
|
||||
D2D1_RENDER_TARGET_PROPERTIES props =
|
||||
D2D1::RenderTargetProperties(
|
||||
D2D1_RENDER_TARGET_TYPE_DEFAULT,
|
||||
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
|
||||
0.0f,
|
||||
0.0f);
|
||||
|
||||
RETURN_IF_FAILED(_d2dFactory->CreateDxgiSurfaceRenderTarget(_dxgiSurface.Get(),
|
||||
&props,
|
||||
&_d2dRenderTarget));
|
||||
|
||||
_d2dRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
RETURN_IF_FAILED(_d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::DarkRed),
|
||||
&_d2dBrushBackground));
|
||||
|
||||
RETURN_IF_FAILED(_d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White),
|
||||
&_d2dBrushForeground));
|
||||
|
||||
const D2D1_STROKE_STYLE_PROPERTIES strokeStyleProperties{
|
||||
D2D1_CAP_STYLE_SQUARE, // startCap
|
||||
D2D1_CAP_STYLE_SQUARE, // endCap
|
||||
D2D1_CAP_STYLE_SQUARE, // dashCap
|
||||
D2D1_LINE_JOIN_MITER, // lineJoin
|
||||
0.f, // miterLimit
|
||||
D2D1_DASH_STYLE_SOLID, // dashStyle
|
||||
0.f, // dashOffset
|
||||
};
|
||||
RETURN_IF_FAILED(_d2dFactory->CreateStrokeStyle(&strokeStyleProperties, nullptr, 0, &_strokeStyle));
|
||||
|
||||
// If in composition mode, apply scaling factor matrix
|
||||
if (_chainMode == SwapChainMode::ForComposition)
|
||||
try
|
||||
{
|
||||
const auto fdpi = static_cast<float>(_dpi);
|
||||
_d2dRenderTarget->SetDpi(fdpi, fdpi);
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&_dxgiSurface)));
|
||||
|
||||
DXGI_MATRIX_3X2_F inverseScale = { 0 };
|
||||
inverseScale._11 = 1.0f / _scale;
|
||||
inverseScale._22 = inverseScale._11;
|
||||
const D2D1_RENDER_TARGET_PROPERTIES props =
|
||||
D2D1::RenderTargetProperties(
|
||||
D2D1_RENDER_TARGET_TYPE_DEFAULT,
|
||||
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
|
||||
0.0f,
|
||||
0.0f);
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDXGISwapChain2> sc2;
|
||||
RETURN_IF_FAILED(_dxgiSwapChain.As(&sc2));
|
||||
RETURN_IF_FAILED(_d2dFactory->CreateDxgiSurfaceRenderTarget(_dxgiSurface.Get(),
|
||||
&props,
|
||||
&_d2dRenderTarget));
|
||||
|
||||
RETURN_IF_FAILED(sc2->SetMatrixTransform(&inverseScale));
|
||||
_d2dRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
RETURN_IF_FAILED(_d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::DarkRed),
|
||||
&_d2dBrushBackground));
|
||||
|
||||
RETURN_IF_FAILED(_d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White),
|
||||
&_d2dBrushForeground));
|
||||
|
||||
const D2D1_STROKE_STYLE_PROPERTIES strokeStyleProperties{
|
||||
D2D1_CAP_STYLE_SQUARE, // startCap
|
||||
D2D1_CAP_STYLE_SQUARE, // endCap
|
||||
D2D1_CAP_STYLE_SQUARE, // dashCap
|
||||
D2D1_LINE_JOIN_MITER, // lineJoin
|
||||
0.f, // miterLimit
|
||||
D2D1_DASH_STYLE_SOLID, // dashStyle
|
||||
0.f, // dashOffset
|
||||
};
|
||||
RETURN_IF_FAILED(_d2dFactory->CreateStrokeStyle(&strokeStyleProperties, nullptr, 0, &_strokeStyle));
|
||||
|
||||
// If in composition mode, apply scaling factor matrix
|
||||
if (_chainMode == SwapChainMode::ForComposition)
|
||||
{
|
||||
const auto fdpi = static_cast<float>(_dpi);
|
||||
_d2dRenderTarget->SetDpi(fdpi, fdpi);
|
||||
|
||||
DXGI_MATRIX_3X2_F inverseScale = { 0 };
|
||||
inverseScale._11 = 1.0f / _scale;
|
||||
inverseScale._22 = inverseScale._11;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDXGISwapChain2> sc2;
|
||||
RETURN_IF_FAILED(_dxgiSwapChain.As(&sc2));
|
||||
|
||||
RETURN_IF_FAILED(sc2->SetMatrixTransform(&inverseScale));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -333,31 +345,35 @@ DxEngine::~DxEngine()
|
|||
// - <none>
|
||||
void DxEngine::_ReleaseDeviceResources() noexcept
|
||||
{
|
||||
_haveDeviceResources = false;
|
||||
_d2dBrushForeground.Reset();
|
||||
_d2dBrushBackground.Reset();
|
||||
|
||||
if (nullptr != _d2dRenderTarget.Get() && _isPainting)
|
||||
try
|
||||
{
|
||||
_d2dRenderTarget->EndDraw();
|
||||
_haveDeviceResources = false;
|
||||
_d2dBrushForeground.Reset();
|
||||
_d2dBrushBackground.Reset();
|
||||
|
||||
if (nullptr != _d2dRenderTarget.Get() && _isPainting)
|
||||
{
|
||||
_d2dRenderTarget->EndDraw();
|
||||
}
|
||||
|
||||
_d2dRenderTarget.Reset();
|
||||
|
||||
_dxgiSurface.Reset();
|
||||
_dxgiSwapChain.Reset();
|
||||
|
||||
if (nullptr != _d3dDeviceContext.Get())
|
||||
{
|
||||
// To ensure the swap chain goes away we must unbind any views from the
|
||||
// D3D pipeline
|
||||
_d3dDeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
}
|
||||
_d3dDeviceContext.Reset();
|
||||
|
||||
_d3dDevice.Reset();
|
||||
|
||||
_dxgiFactory2.Reset();
|
||||
}
|
||||
|
||||
_d2dRenderTarget.Reset();
|
||||
|
||||
_dxgiSurface.Reset();
|
||||
_dxgiSwapChain.Reset();
|
||||
|
||||
if (nullptr != _d3dDeviceContext.Get())
|
||||
{
|
||||
// To ensure the swap chain goes away we must unbind any views from the
|
||||
// D3D pipeline
|
||||
_d3dDeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
}
|
||||
_d3dDeviceContext.Reset();
|
||||
|
||||
_d3dDevice.Reset();
|
||||
|
||||
_dxgiFactory2.Reset();
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -375,10 +391,10 @@ void DxEngine::_ReleaseDeviceResources() noexcept
|
|||
_Out_ IDWriteTextLayout** ppTextLayout) noexcept
|
||||
{
|
||||
return _dwriteFactory->CreateTextLayout(string,
|
||||
static_cast<UINT32>(stringLength),
|
||||
gsl::narrow<UINT32>(stringLength),
|
||||
_dwriteTextFormat.Get(),
|
||||
(float)_displaySizePixels.cx,
|
||||
_glyphCell.cy != 0 ? _glyphCell.cy : (float)_displaySizePixels.cy,
|
||||
gsl::narrow<float>(_displaySizePixels.cx),
|
||||
_glyphCell.cy != 0 ? _glyphCell.cy : gsl::narrow<float>(_displaySizePixels.cy),
|
||||
ppTextLayout);
|
||||
}
|
||||
|
||||
|
@ -410,7 +426,7 @@ void DxEngine::SetCallback(std::function<void()> pfn)
|
|||
_pfn = pfn;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain()
|
||||
{
|
||||
if (_dxgiSwapChain.Get() == nullptr)
|
||||
{
|
||||
|
@ -428,6 +444,8 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
// - S_OK
|
||||
[[nodiscard]] HRESULT DxEngine::Invalidate(const SMALL_RECT* const psrRegion) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, psrRegion);
|
||||
|
||||
_InvalidOr(*psrRegion);
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -440,7 +458,9 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
// - S_OK
|
||||
[[nodiscard]] HRESULT DxEngine::InvalidateCursor(const COORD* const pcoordCursor) noexcept
|
||||
{
|
||||
SMALL_RECT sr = Microsoft::Console::Types::Viewport::FromCoord(*pcoordCursor).ToInclusive();
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pcoordCursor);
|
||||
|
||||
const SMALL_RECT sr = Microsoft::Console::Types::Viewport::FromCoord(*pcoordCursor).ToInclusive();
|
||||
return Invalidate(&sr);
|
||||
}
|
||||
|
||||
|
@ -452,6 +472,8 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
// - S_OK
|
||||
[[nodiscard]] HRESULT DxEngine::InvalidateSystem(const RECT* const prcDirtyClient) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, prcDirtyClient);
|
||||
|
||||
_InvalidOr(*prcDirtyClient);
|
||||
|
||||
return S_OK;
|
||||
|
@ -484,39 +506,43 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
{
|
||||
if (pcoordDelta->X != 0 || pcoordDelta->Y != 0)
|
||||
{
|
||||
POINT delta = { 0 };
|
||||
delta.x = pcoordDelta->X * _glyphCell.cx;
|
||||
delta.y = pcoordDelta->Y * _glyphCell.cy;
|
||||
|
||||
_InvalidOffset(delta);
|
||||
|
||||
_invalidScroll.cx += delta.x;
|
||||
_invalidScroll.cy += delta.y;
|
||||
|
||||
// Add the revealed portion of the screen from the scroll to the invalid area.
|
||||
const RECT display = _GetDisplayRect();
|
||||
RECT reveal = display;
|
||||
|
||||
// X delta first
|
||||
OffsetRect(&reveal, delta.x, 0);
|
||||
IntersectRect(&reveal, &reveal, &display);
|
||||
SubtractRect(&reveal, &display, &reveal);
|
||||
|
||||
if (!IsRectEmpty(&reveal))
|
||||
try
|
||||
{
|
||||
_InvalidOr(reveal);
|
||||
}
|
||||
POINT delta = { 0 };
|
||||
delta.x = pcoordDelta->X * _glyphCell.cx;
|
||||
delta.y = pcoordDelta->Y * _glyphCell.cy;
|
||||
|
||||
// Y delta second (subtract rect won't work if you move both)
|
||||
reveal = display;
|
||||
OffsetRect(&reveal, 0, delta.y);
|
||||
IntersectRect(&reveal, &reveal, &display);
|
||||
SubtractRect(&reveal, &display, &reveal);
|
||||
_InvalidOffset(delta);
|
||||
|
||||
if (!IsRectEmpty(&reveal))
|
||||
{
|
||||
_InvalidOr(reveal);
|
||||
_invalidScroll.cx += delta.x;
|
||||
_invalidScroll.cy += delta.y;
|
||||
|
||||
// Add the revealed portion of the screen from the scroll to the invalid area.
|
||||
const RECT display = _GetDisplayRect();
|
||||
RECT reveal = display;
|
||||
|
||||
// X delta first
|
||||
OffsetRect(&reveal, delta.x, 0);
|
||||
IntersectRect(&reveal, &reveal, &display);
|
||||
SubtractRect(&reveal, &display, &reveal);
|
||||
|
||||
if (!IsRectEmpty(&reveal))
|
||||
{
|
||||
_InvalidOr(reveal);
|
||||
}
|
||||
|
||||
// Y delta second (subtract rect won't work if you move both)
|
||||
reveal = display;
|
||||
OffsetRect(&reveal, 0, delta.y);
|
||||
IntersectRect(&reveal, &reveal, &display);
|
||||
SubtractRect(&reveal, &display, &reveal);
|
||||
|
||||
if (!IsRectEmpty(&reveal))
|
||||
{
|
||||
_InvalidOr(reveal);
|
||||
}
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -544,6 +570,8 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
// - S_FALSE because we don't use this.
|
||||
[[nodiscard]] HRESULT DxEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint);
|
||||
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
@ -577,7 +605,7 @@ Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain() noexcept
|
|||
return size;
|
||||
}
|
||||
default:
|
||||
THROW_HR(E_NOTIMPL);
|
||||
FAIL_FAST_HR(E_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,7 +645,7 @@ void _ScaleByFont(RECT& cellsToPixels, SIZE fontSize) noexcept
|
|||
// - -Y is up, Y is down, -X is left, X is right.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void DxEngine::_InvalidOffset(POINT delta) noexcept
|
||||
void DxEngine::_InvalidOffset(POINT delta)
|
||||
{
|
||||
if (_isInvalidUsed)
|
||||
{
|
||||
|
@ -671,7 +699,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
{
|
||||
UnionRect(&_invalidRect, &_invalidRect, &rc);
|
||||
|
||||
RECT rcScreen = _GetDisplayRect();
|
||||
const RECT rcScreen = _GetDisplayRect();
|
||||
IntersectRect(&_invalidRect, &_invalidRect, &rcScreen);
|
||||
}
|
||||
else
|
||||
|
@ -689,6 +717,8 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
// - S_FALSE because this is unused.
|
||||
[[nodiscard]] HRESULT DxEngine::PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint);
|
||||
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
@ -706,37 +736,41 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
|
||||
if (_isEnabled)
|
||||
{
|
||||
const auto clientSize = _GetClientSize();
|
||||
if (!_haveDeviceResources)
|
||||
try
|
||||
{
|
||||
RETURN_IF_FAILED(_CreateDeviceResources(true));
|
||||
const auto clientSize = _GetClientSize();
|
||||
if (!_haveDeviceResources)
|
||||
{
|
||||
RETURN_IF_FAILED(_CreateDeviceResources(true));
|
||||
}
|
||||
else if (_displaySizePixels.cy != clientSize.cy ||
|
||||
_displaySizePixels.cx != clientSize.cx)
|
||||
{
|
||||
// OK, we're going to play a dangerous game here for the sake of optimizing resize
|
||||
// First, set up a complete clear of all device resources if something goes terribly wrong.
|
||||
auto resetDeviceResourcesOnFailure = wil::scope_exit([&]() noexcept {
|
||||
_ReleaseDeviceResources();
|
||||
});
|
||||
|
||||
// Now let go of a few of the device resources that get in the way of resizing buffers in the swap chain
|
||||
_dxgiSurface.Reset();
|
||||
_d2dRenderTarget.Reset();
|
||||
|
||||
// Change the buffer size and recreate the render target (and surface)
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.cx, clientSize.cy, DXGI_FORMAT_B8G8R8A8_UNORM, 0));
|
||||
RETURN_IF_FAILED(_PrepareRenderTarget());
|
||||
|
||||
// OK we made it past the parts that can cause errors. We can release our failure handler.
|
||||
resetDeviceResourcesOnFailure.release();
|
||||
|
||||
// And persist the new size.
|
||||
_displaySizePixels = clientSize;
|
||||
}
|
||||
|
||||
_d2dRenderTarget->BeginDraw();
|
||||
_isPainting = true;
|
||||
}
|
||||
else if (_displaySizePixels.cy != clientSize.cy ||
|
||||
_displaySizePixels.cx != clientSize.cx)
|
||||
{
|
||||
// OK, we're going to play a dangerous game here for the sake of optimizing resize
|
||||
// First, set up a complete clear of all device resources if something goes terribly wrong.
|
||||
auto resetDeviceResourcesOnFailure = wil::scope_exit([&] {
|
||||
_ReleaseDeviceResources();
|
||||
});
|
||||
|
||||
// Now let go of a few of the device resources that get in the way of resizing buffers in the swap chain
|
||||
_dxgiSurface.Reset();
|
||||
_d2dRenderTarget.Reset();
|
||||
|
||||
// Change the buffer size and recreate the render target (and surface)
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->ResizeBuffers(2, clientSize.cx, clientSize.cy, DXGI_FORMAT_B8G8R8A8_UNORM, 0));
|
||||
RETURN_IF_FAILED(_PrepareRenderTarget());
|
||||
|
||||
// OK we made it past the parts that can cause errors. We can release our failure handler.
|
||||
resetDeviceResourcesOnFailure.release();
|
||||
|
||||
// And persist the new size.
|
||||
_displaySizePixels = clientSize;
|
||||
}
|
||||
|
||||
_d2dRenderTarget->BeginDraw();
|
||||
_isPainting = true;
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -766,7 +800,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
{
|
||||
_presentDirty = _invalidRect;
|
||||
|
||||
RECT display = _GetDisplayRect();
|
||||
const RECT display = _GetDisplayRect();
|
||||
SubtractRect(&_presentScroll, &display, &_presentDirty);
|
||||
_presentOffset.x = _invalidScroll.cx;
|
||||
_presentOffset.y = _invalidScroll.cy;
|
||||
|
@ -811,13 +845,17 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
// - Any DirectX error, a memory error, etc.
|
||||
[[nodiscard]] HRESULT DxEngine::_CopyFrontToBack() noexcept
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> backBuffer;
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> frontBuffer;
|
||||
try
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> backBuffer;
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> frontBuffer;
|
||||
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)));
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(1, IID_PPV_ARGS(&frontBuffer)));
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)));
|
||||
RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(1, IID_PPV_ARGS(&frontBuffer)));
|
||||
|
||||
_d3dDeviceContext->CopyResource(backBuffer.Get(), frontBuffer.Get());
|
||||
_d3dDeviceContext->CopyResource(backBuffer.Get(), frontBuffer.Get());
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -833,16 +871,20 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
{
|
||||
if (_presentReady)
|
||||
{
|
||||
FAIL_FAST_IF_FAILED(_dxgiSwapChain->Present(1, 0));
|
||||
/*FAIL_FAST_IF_FAILED(_dxgiSwapChain->Present1(1, 0, &_presentParams));*/
|
||||
try
|
||||
{
|
||||
FAIL_FAST_IF_FAILED(_dxgiSwapChain->Present(1, 0));
|
||||
/*FAIL_FAST_IF_FAILED(_dxgiSwapChain->Present1(1, 0, &_presentParams));*/
|
||||
|
||||
RETURN_IF_FAILED(_CopyFrontToBack());
|
||||
_presentReady = false;
|
||||
RETURN_IF_FAILED(_CopyFrontToBack());
|
||||
_presentReady = false;
|
||||
|
||||
_presentDirty = { 0 };
|
||||
_presentOffset = { 0 };
|
||||
_presentScroll = { 0 };
|
||||
_presentParams = { 0 };
|
||||
_presentDirty = { 0 };
|
||||
_presentOffset = { 0 };
|
||||
_presentScroll = { 0 };
|
||||
_presentParams = { 0 };
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -945,7 +987,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
COORD const coordTarget) noexcept
|
||||
{
|
||||
const auto existingColor = _d2dBrushForeground->GetColor();
|
||||
const auto restoreBrushOnExit = wil::scope_exit([&] { _d2dBrushForeground->SetColor(existingColor); });
|
||||
const auto restoreBrushOnExit = wil::scope_exit([&]() noexcept { _d2dBrushForeground->SetColor(existingColor); });
|
||||
|
||||
_d2dBrushForeground->SetColor(_ColorFFromColorRef(color));
|
||||
|
||||
|
@ -1028,7 +1070,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
|
|||
0.5f);
|
||||
|
||||
_d2dBrushForeground->SetColor(selectionColor);
|
||||
const auto resetColorOnExit = wil::scope_exit([&] { _d2dBrushForeground->SetColor(existingColor); });
|
||||
const auto resetColorOnExit = wil::scope_exit([&]() noexcept { _d2dBrushForeground->SetColor(existingColor); });
|
||||
|
||||
RECT pixels;
|
||||
pixels.left = rect.Left * _glyphCell.cx;
|
||||
|
@ -1089,7 +1131,8 @@ enum class CursorPaintType
|
|||
{
|
||||
// Enforce min/max cursor height
|
||||
ULONG ulHeight = std::clamp(options.ulCursorHeightPercent, s_ulMinCursorHeightPercent, s_ulMaxCursorHeightPercent);
|
||||
ulHeight = (ULONG)((_glyphCell.cy * ulHeight) / 100);
|
||||
|
||||
ulHeight = gsl::narrow<ULONG>((_glyphCell.cy * ulHeight) / 100);
|
||||
rect.top = rect.bottom - ulHeight;
|
||||
break;
|
||||
}
|
||||
|
@ -1202,25 +1245,29 @@ enum class CursorPaintType
|
|||
// - S_OK or relevant DirectX error
|
||||
[[nodiscard]] HRESULT DxEngine::UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo) noexcept
|
||||
{
|
||||
const auto hr = _GetProposedFont(pfiFontInfoDesired,
|
||||
fiFontInfo,
|
||||
_dpi,
|
||||
_dwriteTextFormat,
|
||||
_dwriteTextAnalyzer,
|
||||
_dwriteFontFace);
|
||||
RETURN_IF_FAILED(_GetProposedFont(pfiFontInfoDesired,
|
||||
fiFontInfo,
|
||||
_dpi,
|
||||
_dwriteTextFormat,
|
||||
_dwriteTextAnalyzer,
|
||||
_dwriteFontFace));
|
||||
|
||||
const auto size = fiFontInfo.GetSize();
|
||||
try
|
||||
{
|
||||
const auto size = fiFontInfo.GetSize();
|
||||
|
||||
_glyphCell.cx = size.X;
|
||||
_glyphCell.cy = size.Y;
|
||||
_glyphCell.cx = size.X;
|
||||
_glyphCell.cy = size.Y;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] Viewport DxEngine::GetViewportInCharacters(const Viewport& viewInPixels) noexcept
|
||||
{
|
||||
short widthInChars = static_cast<short>(viewInPixels.Width() / _glyphCell.cx);
|
||||
short heightInChars = static_cast<short>(viewInPixels.Height() / _glyphCell.cy);
|
||||
const short widthInChars = gsl::narrow_cast<short>(viewInPixels.Width() / _glyphCell.cx);
|
||||
const short heightInChars = gsl::narrow_cast<short>(viewInPixels.Height() / _glyphCell.cy);
|
||||
|
||||
return Viewport::FromDimensions(viewInPixels.Origin(), { widthInChars, heightInChars });
|
||||
}
|
||||
|
@ -1297,13 +1344,13 @@ float DxEngine::GetScaling() const noexcept
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - Rectangle describing dirty area in characters.
|
||||
[[nodiscard]] SMALL_RECT DxEngine::GetDirtyRectInChars() noexcept
|
||||
[[nodiscard]] SMALL_RECT DxEngine::GetDirtyRectInChars()
|
||||
{
|
||||
SMALL_RECT r;
|
||||
r.Top = (SHORT)(floor(_invalidRect.top / _glyphCell.cy));
|
||||
r.Left = (SHORT)(floor(_invalidRect.left / _glyphCell.cx));
|
||||
r.Bottom = (SHORT)(floor(_invalidRect.bottom / _glyphCell.cy));
|
||||
r.Right = (SHORT)(floor(_invalidRect.right / _glyphCell.cx));
|
||||
r.Top = gsl::narrow<SHORT>(floor(_invalidRect.top / _glyphCell.cy));
|
||||
r.Left = gsl::narrow<SHORT>(floor(_invalidRect.left / _glyphCell.cx));
|
||||
r.Bottom = gsl::narrow<SHORT>(floor(_invalidRect.bottom / _glyphCell.cy));
|
||||
r.Right = gsl::narrow<SHORT>(floor(_invalidRect.right / _glyphCell.cx));
|
||||
|
||||
// Exclusive to inclusive
|
||||
r.Bottom--;
|
||||
|
@ -1321,7 +1368,7 @@ float DxEngine::GetScaling() const noexcept
|
|||
// - Nearest integer short x and y values for each cell.
|
||||
[[nodiscard]] COORD DxEngine::_GetFontSize() const noexcept
|
||||
{
|
||||
return { (SHORT)(_glyphCell.cx), (SHORT)(_glyphCell.cy) };
|
||||
return { gsl::narrow<SHORT>(_glyphCell.cx), gsl::narrow<SHORT>(_glyphCell.cy) };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -1345,20 +1392,26 @@ float DxEngine::GetScaling() const noexcept
|
|||
// - S_OK or relevant DirectWrite error.
|
||||
[[nodiscard]] HRESULT DxEngine::IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept
|
||||
{
|
||||
Cluster cluster(glyph, 0); // columns don't matter, we're doing analysis not layout.
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pResult);
|
||||
|
||||
// Create the text layout
|
||||
CustomTextLayout layout(_dwriteFactory.Get(),
|
||||
_dwriteTextAnalyzer.Get(),
|
||||
_dwriteTextFormat.Get(),
|
||||
_dwriteFontFace.Get(),
|
||||
{ &cluster, 1 },
|
||||
_glyphCell.cx);
|
||||
try
|
||||
{
|
||||
const Cluster cluster(glyph, 0); // columns don't matter, we're doing analysis not layout.
|
||||
|
||||
UINT32 columns = 0;
|
||||
RETURN_IF_FAILED(layout.GetColumns(&columns));
|
||||
// Create the text layout
|
||||
CustomTextLayout layout(_dwriteFactory.Get(),
|
||||
_dwriteTextAnalyzer.Get(),
|
||||
_dwriteTextFormat.Get(),
|
||||
_dwriteFontFace.Get(),
|
||||
{ &cluster, 1 },
|
||||
_glyphCell.cx);
|
||||
|
||||
*pResult = columns != 1;
|
||||
UINT32 columns = 0;
|
||||
RETURN_IF_FAILED(layout.GetColumns(&columns));
|
||||
|
||||
*pResult = columns != 1;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1371,7 +1424,7 @@ float DxEngine::GetScaling() const noexcept
|
|||
// - S_OK
|
||||
[[nodiscard]] HRESULT DxEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept
|
||||
{
|
||||
return PostMessageW(_hwndTarget, CM_UPDATE_TITLE, 0, (LPARAM) nullptr) ? S_OK : E_FAIL;
|
||||
return PostMessageW(_hwndTarget, CM_UPDATE_TITLE, 0, 0) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -1451,6 +1504,11 @@ float DxEngine::GetScaling() const noexcept
|
|||
|
||||
THROW_IF_FAILED(fontFace0.As(&fontFace));
|
||||
|
||||
// Retrieve metrics in case the font we created was different than what was requested.
|
||||
weight = font->GetWeight();
|
||||
stretch = font->GetStretch();
|
||||
style = font->GetStyle();
|
||||
|
||||
// Dig the family name out at the end to return it.
|
||||
familyName = _GetFontFamilyName(fontFamily.Get(), localeName);
|
||||
}
|
||||
|
@ -1488,7 +1546,7 @@ float DxEngine::GetScaling() const noexcept
|
|||
// - If fallback occurred, this is updated to what we retrieved instead.
|
||||
// Return Value:
|
||||
// - Localized string name of the font family
|
||||
[[nodiscard]] std::wstring DxEngine::_GetFontFamilyName(IDWriteFontFamily* const fontFamily,
|
||||
[[nodiscard]] std::wstring DxEngine::_GetFontFamilyName(gsl::not_null<IDWriteFontFamily*> const fontFamily,
|
||||
std::wstring& localeName) const
|
||||
{
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontcollection
|
||||
|
@ -1691,9 +1749,9 @@ float DxEngine::GetScaling() const noexcept
|
|||
// Unscaled is for the purposes of re-communicating this font back to the renderer again later.
|
||||
// As such, we need to give the same original size parameter back here without padding
|
||||
// or rounding or scaling manipulation.
|
||||
COORD unscaled = desired.GetEngineSize();
|
||||
const COORD unscaled = desired.GetEngineSize();
|
||||
|
||||
COORD scaled = coordSize;
|
||||
const COORD scaled = coordSize;
|
||||
|
||||
actual.SetFromEngine(fontName.data(),
|
||||
desired.GetFamily(),
|
||||
|
@ -1733,22 +1791,6 @@ float DxEngine::GetScaling() const noexcept
|
|||
return D2D1::ColorF(rgb, aFloat);
|
||||
}
|
||||
default:
|
||||
THROW_HR(E_NOTIMPL);
|
||||
FAIL_FAST_HR(E_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helps convert a Direct2D ColorF into a DXGI RGBA
|
||||
// Arguments:
|
||||
// - color - Direct2D Color F
|
||||
// Return Value:
|
||||
// - DXGI RGBA
|
||||
[[nodiscard]] DXGI_RGBA DxEngine::s_RgbaFromColorF(const D2D1_COLOR_F color) noexcept
|
||||
{
|
||||
DXGI_RGBA rgba;
|
||||
rgba.a = color.a;
|
||||
rgba.b = color.b;
|
||||
rgba.g = color.g;
|
||||
rgba.r = color.r;
|
||||
return rgba;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,11 @@ namespace Microsoft::Console::Render
|
|||
{
|
||||
public:
|
||||
DxEngine();
|
||||
virtual ~DxEngine() override;
|
||||
~DxEngine();
|
||||
DxEngine(const DxEngine&) = default;
|
||||
DxEngine(DxEngine&&) = default;
|
||||
DxEngine& operator=(const DxEngine&) = default;
|
||||
DxEngine& operator=(DxEngine&&) = default;
|
||||
|
||||
// Used to release device resources so that another instance of
|
||||
// conhost can render to the screen (i.e. only one DirectX
|
||||
|
@ -45,7 +49,7 @@ namespace Microsoft::Console::Render
|
|||
|
||||
void SetCallback(std::function<void()> pfn);
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDXGISwapChain1> GetSwapChain() noexcept;
|
||||
::Microsoft::WRL::ComPtr<IDXGISwapChain1> GetSwapChain();
|
||||
|
||||
// IRenderEngine Members
|
||||
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
|
@ -84,7 +88,7 @@ namespace Microsoft::Console::Render
|
|||
|
||||
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
|
||||
|
||||
[[nodiscard]] SMALL_RECT GetDirtyRectInChars() noexcept override;
|
||||
[[nodiscard]] SMALL_RECT GetDirtyRectInChars() override;
|
||||
|
||||
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
|
||||
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
|
||||
|
@ -133,7 +137,7 @@ namespace Microsoft::Console::Render
|
|||
void _InvalidOr(SMALL_RECT sr) noexcept;
|
||||
void _InvalidOr(RECT rc) noexcept;
|
||||
|
||||
void _InvalidOffset(POINT pt) noexcept;
|
||||
void _InvalidOffset(POINT pt);
|
||||
|
||||
bool _presentReady;
|
||||
RECT _presentDirty;
|
||||
|
@ -193,7 +197,7 @@ namespace Microsoft::Console::Render
|
|||
|
||||
[[nodiscard]] std::wstring _GetLocaleName() const;
|
||||
|
||||
[[nodiscard]] std::wstring _GetFontFamilyName(IDWriteFontFamily* const fontFamily,
|
||||
[[nodiscard]] std::wstring _GetFontFamilyName(gsl::not_null<IDWriteFontFamily*> const fontFamily,
|
||||
std::wstring& localeName) const;
|
||||
|
||||
[[nodiscard]] HRESULT _GetProposedFont(const FontInfoDesired& desired,
|
||||
|
@ -209,6 +213,15 @@ namespace Microsoft::Console::Render
|
|||
|
||||
[[nodiscard]] D2D1_COLOR_F _ColorFFromColorRef(const COLORREF color) noexcept;
|
||||
|
||||
[[nodiscard]] static DXGI_RGBA s_RgbaFromColorF(const D2D1_COLOR_F color) noexcept;
|
||||
// Routine Description:
|
||||
// - Helps convert a Direct2D ColorF into a DXGI RGBA
|
||||
// Arguments:
|
||||
// - color - Direct2D Color F
|
||||
// Return Value:
|
||||
// - DXGI RGBA
|
||||
[[nodiscard]] constexpr DXGI_RGBA s_RgbaFromColorF(const D2D1_COLOR_F color) noexcept
|
||||
{
|
||||
return { color.r, color.g, color.b, color.a };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -64,6 +64,14 @@ namespace Microsoft::Console::Render
|
|||
|
||||
virtual ~IRenderEngine() = 0;
|
||||
|
||||
protected:
|
||||
IRenderEngine() = default;
|
||||
IRenderEngine(const IRenderEngine&) = default;
|
||||
IRenderEngine(IRenderEngine&&) = default;
|
||||
IRenderEngine& operator=(const IRenderEngine&) = default;
|
||||
IRenderEngine& operator=(IRenderEngine&&) = default;
|
||||
|
||||
public:
|
||||
[[nodiscard]] virtual HRESULT StartPaint() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT EndPaint() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT Present() noexcept = 0;
|
||||
|
|
|
@ -25,6 +25,14 @@ namespace Microsoft::Console::Render
|
|||
public:
|
||||
virtual ~IRenderTarget() = 0;
|
||||
|
||||
protected:
|
||||
IRenderTarget() = default;
|
||||
IRenderTarget(const IRenderTarget&) = default;
|
||||
IRenderTarget(IRenderTarget&&) = default;
|
||||
IRenderTarget& operator=(const IRenderTarget&) = default;
|
||||
IRenderTarget& operator=(IRenderTarget&&) = default;
|
||||
|
||||
public:
|
||||
virtual void TriggerRedraw(const Microsoft::Console::Types::Viewport& region) = 0;
|
||||
virtual void TriggerRedraw(const COORD* const pcoord) = 0;
|
||||
virtual void TriggerRedrawCursor(const COORD* const pcoord) = 0;
|
||||
|
|
|
@ -24,9 +24,16 @@ namespace Microsoft::Console::Render
|
|||
class RenderEngineBase : public IRenderEngine
|
||||
{
|
||||
public:
|
||||
RenderEngineBase();
|
||||
virtual ~RenderEngineBase() = 0;
|
||||
~RenderEngineBase() = 0;
|
||||
|
||||
protected:
|
||||
RenderEngineBase();
|
||||
RenderEngineBase(const RenderEngineBase&) = default;
|
||||
RenderEngineBase(RenderEngineBase&&) = default;
|
||||
RenderEngineBase& operator=(const RenderEngineBase&) = default;
|
||||
RenderEngineBase& operator=(RenderEngineBase&&) = default;
|
||||
|
||||
public:
|
||||
[[nodiscard]] HRESULT InvalidateTitle(const std::wstring& proposedTitle) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT UpdateTitle(const std::wstring& newTitle) noexcept override;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace
|
|||
CodepointWidth width;
|
||||
};
|
||||
|
||||
static bool operator<(const UnicodeRange& range, const unsigned int searchTerm)
|
||||
static bool operator<(const UnicodeRange& range, const unsigned int searchTerm) noexcept
|
||||
{
|
||||
return range.upperBound < searchTerm;
|
||||
}
|
||||
|
@ -310,13 +310,21 @@ namespace
|
|||
};
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Constructs an instance of the CodepointWidthDetector class
|
||||
CodepointWidthDetector::CodepointWidthDetector() noexcept :
|
||||
_fallbackCache{},
|
||||
_pfnFallbackMethod{}
|
||||
{
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - returns the width type of codepoint by searching the map generated from the unicode spec
|
||||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint to search for
|
||||
// Return Value:
|
||||
// - the width type of the codepoint
|
||||
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) const noexcept
|
||||
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) const
|
||||
{
|
||||
if (glyph.empty())
|
||||
{
|
||||
|
@ -443,7 +451,7 @@ bool CodepointWidthDetector::_checkFallbackViaCache(const std::wstring_view glyp
|
|||
const std::wstring findMe{ glyph };
|
||||
|
||||
// TODO: Cache needs to be emptied when font changes.
|
||||
auto it = _fallbackCache.find(findMe);
|
||||
const auto it = _fallbackCache.find(findMe);
|
||||
if (it == _fallbackCache.end())
|
||||
{
|
||||
auto result = _pfnFallbackMethod(glyph);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "inc/CodepointWidthDetector.hpp"
|
||||
#include "inc/GlyphWidth.hpp"
|
||||
|
||||
#pragma warning(suppress : 26426)
|
||||
// TODO GH 2676 - remove warning suppression and decide what to do re: singleton instance of CodepointWidthDetector
|
||||
static CodepointWidthDetector widthDetector;
|
||||
|
||||
// Function Description:
|
||||
|
@ -18,7 +20,7 @@ bool IsGlyphFullWidth(const std::wstring_view glyph)
|
|||
// Function Description:
|
||||
// - determines if the glyph represented by the single character should be
|
||||
// wide or not. See CodepointWidthDetector::IsWide
|
||||
bool IsGlyphFullWidth(const wchar_t wch)
|
||||
bool IsGlyphFullWidth(const wchar_t wch) noexcept
|
||||
{
|
||||
return widthDetector.IsWide(wch);
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ void SetGlyphWidthFallback(std::function<bool(const std::wstring_view)> pfnFallb
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void NotifyGlyphWidthFontChanged()
|
||||
void NotifyGlyphWidthFontChanged() noexcept
|
||||
{
|
||||
widthDetector.NotifyFontChanged();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,15 @@ namespace Microsoft::Console::Types
|
|||
{
|
||||
public:
|
||||
virtual ~IBaseData() = 0;
|
||||
|
||||
protected:
|
||||
IBaseData() = default;
|
||||
IBaseData(const IBaseData&) = default;
|
||||
IBaseData(IBaseData&&) = default;
|
||||
IBaseData& operator=(const IBaseData&) = default;
|
||||
IBaseData& operator=(IBaseData&&) = default;
|
||||
|
||||
public:
|
||||
virtual Microsoft::Console::Types::Viewport GetViewport() noexcept = 0;
|
||||
virtual const TextBuffer& GetTextBuffer() noexcept = 0;
|
||||
virtual const FontInfo& GetFontInfo() noexcept = 0;
|
||||
|
|
|
@ -48,7 +48,7 @@ std::deque<std::unique_ptr<IInputEvent>> IInputEvent::Create(const std::deque<IN
|
|||
std::deque<std::unique_ptr<IInputEvent>> outEvents;
|
||||
for (size_t i = 0; i < records.size(); ++i)
|
||||
{
|
||||
std::unique_ptr<IInputEvent> event = IInputEvent::Create(records[i]);
|
||||
std::unique_ptr<IInputEvent> event = IInputEvent::Create(records.at(i));
|
||||
outEvents.push_back(std::move(event));
|
||||
}
|
||||
return outEvents;
|
||||
|
|
|
@ -23,8 +23,16 @@ namespace Microsoft::Console::Types
|
|||
class IUiaData : public IBaseData
|
||||
{
|
||||
public:
|
||||
virtual ~IUiaData() = 0;
|
||||
~IUiaData() = 0;
|
||||
|
||||
protected:
|
||||
IUiaData() = default;
|
||||
IUiaData(const IUiaData&) = default;
|
||||
IUiaData(IUiaData&&) = default;
|
||||
IUiaData& operator=(const IUiaData&) = default;
|
||||
IUiaData& operator=(IUiaData&&) = default;
|
||||
|
||||
public:
|
||||
virtual const bool IsSelectionActive() const = 0;
|
||||
virtual void ClearSelection() = 0;
|
||||
virtual void SelectNewRegion(const COORD coordStart, const COORD coordEnd) = 0;
|
||||
|
|
|
@ -68,7 +68,7 @@ void KeyEvent::ActivateModifierKey(const ModifierKeyState modifierKey) noexcept
|
|||
WI_SetAllFlags(_activeModifierKeys, bitFlag);
|
||||
}
|
||||
|
||||
bool KeyEvent::DoActiveModifierKeysMatch(const std::unordered_set<ModifierKeyState>& consoleModifiers) const noexcept
|
||||
bool KeyEvent::DoActiveModifierKeysMatch(const std::unordered_set<ModifierKeyState>& consoleModifiers) const
|
||||
{
|
||||
DWORD consoleBits = 0;
|
||||
for (const ModifierKeyState& mod : consoleModifiers)
|
||||
|
|
|
@ -10,14 +10,16 @@ using namespace Microsoft::Console::Types;
|
|||
using namespace Microsoft::Console::Types::ScreenInfoUiaProviderTracing;
|
||||
|
||||
// A helper function to create a SafeArray Version of an int array of a specified length
|
||||
SAFEARRAY* BuildIntSafeArray(_In_reads_(length) const int* const data, const int length)
|
||||
SAFEARRAY* BuildIntSafeArray(std::basic_string_view<int> data)
|
||||
{
|
||||
SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, length);
|
||||
SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, gsl::narrow<ULONG>(data.size()));
|
||||
if (psa != nullptr)
|
||||
{
|
||||
for (long i = 0; i < length; i++)
|
||||
for (size_t i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (FAILED(SafeArrayPutElement(psa, &i, (void*)&(data[i]))))
|
||||
LONG lIndex = 0;
|
||||
if (FAILED(SizeTToLong(i, &lIndex) ||
|
||||
FAILED(SafeArrayPutElement(psa, &lIndex, (void*)&(data.at(i))))))
|
||||
{
|
||||
SafeArrayDestroy(psa);
|
||||
psa = nullptr;
|
||||
|
@ -38,10 +40,6 @@ ScreenInfoUiaProviderBase::ScreenInfoUiaProviderBase(_In_ IUiaData* pData) :
|
|||
//Tracing::s_TraceUia(nullptr, ApiCall::Constructor, nullptr);
|
||||
}
|
||||
|
||||
ScreenInfoUiaProviderBase::~ScreenInfoUiaProviderBase()
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT ScreenInfoUiaProviderBase::Signal(_In_ EVENTID id)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
@ -58,7 +56,7 @@ ScreenInfoUiaProviderBase::~ScreenInfoUiaProviderBase()
|
|||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
IRawElementProviderSimple* pProvider = static_cast<IRawElementProviderSimple*>(this);
|
||||
IRawElementProviderSimple* pProvider = this;
|
||||
hr = UiaRaiseAutomationEvent(pProvider, id);
|
||||
_signalFiringMapping[id] = false;
|
||||
|
||||
|
@ -85,7 +83,7 @@ ScreenInfoUiaProviderBase::Release()
|
|||
{
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::Release, nullptr);
|
||||
long val = InterlockedDecrement(&_cRefs);
|
||||
const long val = InterlockedDecrement(&_cRefs);
|
||||
if (val == 0)
|
||||
{
|
||||
delete this;
|
||||
|
@ -96,23 +94,16 @@ ScreenInfoUiaProviderBase::Release()
|
|||
IFACEMETHODIMP ScreenInfoUiaProviderBase::QueryInterface(_In_ REFIID riid,
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppInterface);
|
||||
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::QueryInterface, nullptr);
|
||||
if (riid == __uuidof(IUnknown))
|
||||
if (riid == __uuidof(IUnknown) ||
|
||||
riid == __uuidof(IRawElementProviderSimple) ||
|
||||
riid == __uuidof(IRawElementProviderFragment) ||
|
||||
riid == __uuidof(ITextProvider))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderSimple*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(IRawElementProviderSimple))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderSimple*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(IRawElementProviderFragment))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderFragment*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(ITextProvider))
|
||||
{
|
||||
*ppInterface = static_cast<ITextProvider*>(this);
|
||||
*ppInterface = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -120,7 +111,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::QueryInterface(_In_ REFIID riid,
|
|||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
(static_cast<IUnknown*>(*ppInterface))->AddRef();
|
||||
AddRef();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -131,8 +122,10 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::QueryInterface(_In_ REFIID riid,
|
|||
|
||||
// Implementation of IRawElementProviderSimple::get_ProviderOptions.
|
||||
// Gets UI Automation provider options.
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_ProviderOptions(_Out_ ProviderOptions* pOptions)
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_ProviderOptions(_Out_ ProviderOptions* pOptions) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pOptions);
|
||||
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetProviderOptions, nullptr);
|
||||
*pOptions = ProviderOptions_ServerSideProvider;
|
||||
|
@ -155,7 +148,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetPatternProvider(_In_ PATTERNID patt
|
|||
|
||||
if (patternId == UIA_TextPatternId)
|
||||
{
|
||||
hr = this->QueryInterface(__uuidof(ITextProvider), reinterpret_cast<void**>(ppInterface));
|
||||
hr = this->QueryInterface(IID_PPV_ARGS(ppInterface));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
*ppInterface = nullptr;
|
||||
|
@ -167,7 +160,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetPatternProvider(_In_ PATTERNID patt
|
|||
// Implementation of IRawElementProviderSimple::get_PropertyValue.
|
||||
// Gets custom properties.
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::GetPropertyValue(_In_ PROPERTYID propertyId,
|
||||
_Out_ VARIANT* pVariant)
|
||||
_Out_ VARIANT* pVariant) noexcept
|
||||
{
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetPropertyValue, nullptr);
|
||||
|
@ -237,7 +230,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetPropertyValue(_In_ PROPERTYID prope
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider)
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider) noexcept
|
||||
{
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetHostRawElementProvider, nullptr);
|
||||
|
@ -260,15 +253,17 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetRuntimeId(_Outptr_result_maybenull_
|
|||
*ppRuntimeId = nullptr;
|
||||
|
||||
// AppendRuntimeId is a magic Number that tells UIAutomation to Append its own Runtime ID(From the HWND)
|
||||
int rId[] = { UiaAppendRuntimeId, -1 };
|
||||
const std::array<int, 2> rId{ UiaAppendRuntimeId, -1 };
|
||||
|
||||
const std::basic_string_view<int> span{ rId.data(), rId.size() };
|
||||
// BuildIntSafeArray is a custom function to hide the SafeArray creation
|
||||
*ppRuntimeId = BuildIntSafeArray(rId, 2);
|
||||
*ppRuntimeId = BuildIntSafeArray(span);
|
||||
RETURN_IF_NULL_ALLOC(*ppRuntimeId);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots)
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots) noexcept
|
||||
{
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetEmbeddedFragmentRoots, nullptr);
|
||||
|
@ -296,11 +291,11 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
//ApiMsgGetSelection apiMsg;
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] {
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
|
@ -322,6 +317,11 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
|
||||
IRawElementProviderSimple* pProvider;
|
||||
hr = this->QueryInterface(IID_PPV_ARGS(&pProvider));
|
||||
if (pProvider == nullptr)
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
|
@ -340,7 +340,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
range = nullptr;
|
||||
hr = wil::ResultFromCaughtException();
|
||||
}
|
||||
(static_cast<IUnknown*>(pProvider))->Release();
|
||||
pProvider->Release();
|
||||
if (range == nullptr)
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
|
@ -349,7 +349,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
}
|
||||
|
||||
LONG currentIndex = 0;
|
||||
hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, reinterpret_cast<void*>(range));
|
||||
hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, range);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
|
@ -363,6 +363,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
std::deque<UiaTextRangeBase*> ranges;
|
||||
IRawElementProviderSimple* pProvider;
|
||||
RETURN_IF_FAILED(QueryInterface(IID_PPV_ARGS(&pProvider)));
|
||||
RETURN_HR_IF_NULL(E_POINTER, pProvider);
|
||||
try
|
||||
{
|
||||
ranges = GetSelectionRanges(pProvider);
|
||||
|
@ -379,25 +380,28 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
//apiMsg.SelectionRowCount = static_cast<unsigned int>(ranges.size());
|
||||
|
||||
// make a safe array
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast<ULONG>(ranges.size()));
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, gsl::narrow<ULONG>(ranges.size()));
|
||||
if (*ppRetVal == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// fill the safe array
|
||||
for (LONG i = 0; i < static_cast<LONG>(ranges.size()); ++i)
|
||||
for (LONG i = 0; i < gsl::narrow<LONG>(ranges.size()); ++i)
|
||||
{
|
||||
hr = SafeArrayPutElement(*ppRetVal, &i, reinterpret_cast<void*>(ranges[i]));
|
||||
hr = SafeArrayPutElement(*ppRetVal, &i, ranges.at(i));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
while (!ranges.empty())
|
||||
{
|
||||
UiaTextRangeBase* pRange = ranges[0];
|
||||
UiaTextRangeBase* pRange = ranges.at(0);
|
||||
ranges.pop_front();
|
||||
pRange->Release();
|
||||
if (pRange)
|
||||
{
|
||||
pRange->Release();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
@ -415,11 +419,11 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
|||
//Tracing::s_TraceUia(this, ApiCall::GetVisibleRanges, nullptr);
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] {
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
const auto viewport = _getViewport();
|
||||
|
@ -428,7 +432,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
|||
|
||||
// make a safe array
|
||||
const size_t rowCount = viewport.Height();
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast<ULONG>(rowCount));
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, gsl::narrow<ULONG>(rowCount));
|
||||
if (*ppRetVal == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -444,6 +448,11 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
|||
|
||||
IRawElementProviderSimple* pProvider;
|
||||
HRESULT hr = this->QueryInterface(IID_PPV_ARGS(&pProvider));
|
||||
if (pProvider == nullptr)
|
||||
{
|
||||
hr = E_POINTER;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
|
@ -464,7 +473,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
|||
range = nullptr;
|
||||
hr = wil::ResultFromCaughtException();
|
||||
}
|
||||
(static_cast<IUnknown*>(pProvider))->Release();
|
||||
pProvider->Release();
|
||||
|
||||
if (range == nullptr)
|
||||
{
|
||||
|
@ -473,8 +482,8 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
|||
return hr;
|
||||
}
|
||||
|
||||
LONG currentIndex = static_cast<LONG>(i);
|
||||
hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, reinterpret_cast<void*>(range));
|
||||
LONG currentIndex = gsl::narrow<LONG>(i);
|
||||
hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, range);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(*ppRetVal);
|
||||
|
@ -491,11 +500,12 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::RangeFromChild(_In_ IRawElementProvide
|
|||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::RangeFromChild, nullptr);
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
IRawElementProviderSimple* pProvider;
|
||||
RETURN_IF_FAILED(this->QueryInterface(IID_PPV_ARGS(&pProvider)));
|
||||
RETURN_HR_IF_NULL(E_POINTER, pProvider);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
try
|
||||
|
@ -507,7 +517,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::RangeFromChild(_In_ IRawElementProvide
|
|||
*ppRetVal = nullptr;
|
||||
hr = wil::ResultFromCaughtException();
|
||||
}
|
||||
(static_cast<IUnknown*>(pProvider))->Release();
|
||||
pProvider->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -518,11 +528,12 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::RangeFromPoint(_In_ UiaPoint point,
|
|||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::RangeFromPoint, nullptr);
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
IRawElementProviderSimple* pProvider;
|
||||
RETURN_IF_FAILED(this->QueryInterface(IID_PPV_ARGS(&pProvider)));
|
||||
RETURN_HR_IF_NULL(E_POINTER, pProvider);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
try
|
||||
|
@ -535,7 +546,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::RangeFromPoint(_In_ UiaPoint point,
|
|||
*ppRetVal = nullptr;
|
||||
hr = wil::ResultFromCaughtException();
|
||||
}
|
||||
(static_cast<IUnknown*>(pProvider))->Release();
|
||||
pProvider->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -545,11 +556,12 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::get_DocumentRange(_COM_Outptr_result_m
|
|||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetDocumentRange, nullptr);
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
IRawElementProviderSimple* pProvider;
|
||||
RETURN_IF_FAILED(this->QueryInterface(IID_PPV_ARGS(&pProvider)));
|
||||
RETURN_HR_IF_NULL(E_POINTER, pProvider);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
try
|
||||
|
@ -561,7 +573,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::get_DocumentRange(_COM_Outptr_result_m
|
|||
*ppRetVal = nullptr;
|
||||
hr = wil::ResultFromCaughtException();
|
||||
}
|
||||
(static_cast<IUnknown*>(pProvider))->Release();
|
||||
pProvider->Release();
|
||||
|
||||
if (*ppRetVal)
|
||||
{
|
||||
|
@ -571,8 +583,10 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::get_DocumentRange(_COM_Outptr_result_m
|
|||
return hr;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_SupportedTextSelection(_Out_ SupportedTextSelection* pRetVal)
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::get_SupportedTextSelection(_Out_ SupportedTextSelection* pRetVal) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pRetVal);
|
||||
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(this, ApiCall::GetSupportedTextSelection, nullptr);
|
||||
|
||||
|
@ -587,12 +601,12 @@ const COORD ScreenInfoUiaProviderBase::_getScreenBufferCoords() const
|
|||
return _getTextBuffer().GetSize().Dimensions();
|
||||
}
|
||||
|
||||
const TextBuffer& ScreenInfoUiaProviderBase::_getTextBuffer() const
|
||||
const TextBuffer& ScreenInfoUiaProviderBase::_getTextBuffer() const noexcept
|
||||
{
|
||||
return _pData->GetTextBuffer();
|
||||
}
|
||||
|
||||
const Viewport ScreenInfoUiaProviderBase::_getViewport() const
|
||||
const Viewport ScreenInfoUiaProviderBase::_getViewport() const noexcept
|
||||
{
|
||||
return _pData->GetViewport();
|
||||
}
|
||||
|
|
|
@ -38,44 +38,48 @@ namespace Microsoft::Console::Types
|
|||
{
|
||||
public:
|
||||
ScreenInfoUiaProviderBase(_In_ IUiaData* pData);
|
||||
virtual ~ScreenInfoUiaProviderBase();
|
||||
ScreenInfoUiaProviderBase(const ScreenInfoUiaProviderBase&) = default;
|
||||
ScreenInfoUiaProviderBase(ScreenInfoUiaProviderBase&&) = default;
|
||||
ScreenInfoUiaProviderBase& operator=(const ScreenInfoUiaProviderBase&) = default;
|
||||
ScreenInfoUiaProviderBase& operator=(ScreenInfoUiaProviderBase&&) = default;
|
||||
virtual ~ScreenInfoUiaProviderBase() = default;
|
||||
|
||||
[[nodiscard]] HRESULT Signal(_In_ EVENTID id);
|
||||
|
||||
// IUnknown methods
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
AddRef();
|
||||
AddRef() override;
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
Release();
|
||||
Release() override;
|
||||
IFACEMETHODIMP QueryInterface(_In_ REFIID riid,
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface);
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface) override;
|
||||
|
||||
// IRawElementProviderSimple methods
|
||||
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions);
|
||||
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions) noexcept override;
|
||||
IFACEMETHODIMP GetPatternProvider(_In_ PATTERNID iid,
|
||||
_COM_Outptr_result_maybenull_ IUnknown** ppInterface);
|
||||
_COM_Outptr_result_maybenull_ IUnknown** ppInterface) override;
|
||||
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
|
||||
_Out_ VARIANT* pVariant);
|
||||
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider);
|
||||
_Out_ VARIANT* pVariant) noexcept override;
|
||||
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider) noexcept override;
|
||||
|
||||
// IRawElementProviderFragment methods
|
||||
virtual IFACEMETHODIMP Navigate(_In_ NavigateDirection direction,
|
||||
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) = 0;
|
||||
IFACEMETHODIMP GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId);
|
||||
IFACEMETHODIMP GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId) override;
|
||||
virtual IFACEMETHODIMP get_BoundingRectangle(_Out_ UiaRect* pRect) = 0;
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots);
|
||||
IFACEMETHODIMP SetFocus();
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots) noexcept override;
|
||||
IFACEMETHODIMP SetFocus() override;
|
||||
virtual IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider) = 0;
|
||||
|
||||
// ITextProvider
|
||||
IFACEMETHODIMP GetSelection(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal);
|
||||
IFACEMETHODIMP GetVisibleRanges(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal);
|
||||
IFACEMETHODIMP GetSelection(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) override;
|
||||
IFACEMETHODIMP GetVisibleRanges(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) override;
|
||||
IFACEMETHODIMP RangeFromChild(_In_ IRawElementProviderSimple* childElement,
|
||||
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal);
|
||||
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
|
||||
IFACEMETHODIMP RangeFromPoint(_In_ UiaPoint point,
|
||||
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal);
|
||||
IFACEMETHODIMP get_DocumentRange(_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal);
|
||||
IFACEMETHODIMP get_SupportedTextSelection(_Out_ SupportedTextSelection* pRetVal);
|
||||
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
|
||||
IFACEMETHODIMP get_DocumentRange(_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
|
||||
IFACEMETHODIMP get_SupportedTextSelection(_Out_ SupportedTextSelection* pRetVal) noexcept override;
|
||||
|
||||
protected:
|
||||
virtual std::deque<UiaTextRangeBase*> GetSelectionRanges(_In_ IRawElementProviderSimple* pProvider) = 0;
|
||||
|
@ -118,8 +122,8 @@ namespace Microsoft::Console::Types
|
|||
std::map<EVENTID, bool> _signalFiringMapping;
|
||||
|
||||
const COORD _getScreenBufferCoords() const;
|
||||
const TextBuffer& _getTextBuffer() const;
|
||||
const Viewport _getViewport() const;
|
||||
const TextBuffer& _getTextBuffer() const noexcept;
|
||||
const Viewport _getViewport() const noexcept;
|
||||
void _LockConsole() noexcept;
|
||||
void _UnlockConsole() noexcept;
|
||||
};
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
||||
_outPipe{ outPipe }
|
||||
UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) noexcept :
|
||||
_outPipe{ outPipe },
|
||||
_buffer{ 0 },
|
||||
_utf8Partials{ 0 }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -30,24 +32,24 @@ UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
|||
bool fSuccess{};
|
||||
|
||||
// in case of early escaping
|
||||
*_buffer = 0;
|
||||
strView = std::string_view{ reinterpret_cast<char*>(_buffer), 0 };
|
||||
_buffer.at(0) = 0;
|
||||
strView = std::string_view{ _buffer.data(), 0 };
|
||||
|
||||
// copy UTF-8 code units that were remaining from the previously read chunk (if any)
|
||||
if (_dwPartialsLen != 0)
|
||||
{
|
||||
std::move(_utf8Partials, _utf8Partials + _dwPartialsLen, _buffer);
|
||||
std::move(_utf8Partials.cbegin(), _utf8Partials.cbegin() + _dwPartialsLen, _buffer.begin());
|
||||
}
|
||||
|
||||
// try to read data
|
||||
fSuccess = !!ReadFile(_outPipe, &_buffer[_dwPartialsLen], std::extent<decltype(_buffer)>::value - _dwPartialsLen, &dwRead, nullptr);
|
||||
fSuccess = !!ReadFile(_outPipe, &_buffer.at(_dwPartialsLen), gsl::narrow<DWORD>(_buffer.size()) - _dwPartialsLen, &dwRead, nullptr);
|
||||
|
||||
dwRead += _dwPartialsLen;
|
||||
_dwPartialsLen = 0;
|
||||
|
||||
if (!fSuccess) // reading failed (we must check this first, because dwRead will also be 0.)
|
||||
{
|
||||
auto lastError = GetLastError();
|
||||
const auto lastError = GetLastError();
|
||||
if (lastError == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
// This is a successful, but detectable, exit.
|
||||
|
@ -65,13 +67,13 @@ UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
const BYTE* const endPtr{ _buffer + dwRead };
|
||||
const BYTE* backIter{ endPtr - 1 };
|
||||
const auto endPtr = _buffer.cbegin() + dwRead;
|
||||
auto backIter = endPtr - 1;
|
||||
// If the last byte in the buffer was a byte belonging to a UTF-8 multi-byte character
|
||||
if ((*backIter & _Utf8BitMasks::MaskAsciiByte) > _Utf8BitMasks::IsAsciiByte)
|
||||
{
|
||||
// Check only up to 3 last bytes, if no Lead Byte was found then the byte before must be the Lead Byte and no partials are in the buffer
|
||||
for (DWORD dwSequenceLen{ 1UL }, stop{ dwRead < 4UL ? dwRead : 4UL }; dwSequenceLen < stop; ++dwSequenceLen, --backIter)
|
||||
for (DWORD dwSequenceLen{ 1UL }; dwSequenceLen < std::min(dwRead, 4UL); ++dwSequenceLen, --backIter)
|
||||
{
|
||||
// If Lead Byte found
|
||||
if ((*backIter & _Utf8BitMasks::MaskContinuationByte) > _Utf8BitMasks::IsContinuationByte)
|
||||
|
@ -80,9 +82,9 @@ UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
|||
// Use the bitmask at index `dwSequenceLen`. Compare the result with the operand having the same index. If they
|
||||
// are not equal then the sequence has to be cached because it is a partial code point. Otherwise the
|
||||
// sequence is a complete UTF-8 code point and the whole buffer is ready for the conversion to hstring.
|
||||
if ((*backIter & _cmpMasks[dwSequenceLen]) != _cmpOperands[dwSequenceLen])
|
||||
if ((*backIter & _cmpMasks.at(dwSequenceLen)) != _cmpOperands.at(dwSequenceLen))
|
||||
{
|
||||
std::move(backIter, endPtr, _utf8Partials);
|
||||
std::move(backIter, endPtr, _utf8Partials.begin());
|
||||
dwRead -= dwSequenceLen;
|
||||
_dwPartialsLen = dwSequenceLen;
|
||||
}
|
||||
|
@ -93,6 +95,6 @@ UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
|||
}
|
||||
|
||||
// give back a view of the part of the buffer that contains complete code points only
|
||||
strView = std::string_view{ reinterpret_cast<char*>(_buffer), dwRead };
|
||||
strView = std::string_view{ &_buffer.at(0), dwRead };
|
||||
return S_OK;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -129,7 +129,7 @@ namespace Microsoft::Console::Types
|
|||
const Column firstColumnInRow,
|
||||
const Column lastColumnInRow,
|
||||
const MovementIncrement increment,
|
||||
const MovementDirection direction);
|
||||
const MovementDirection direction) noexcept;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class ::UiaTextRangeTests;
|
||||
|
@ -137,62 +137,65 @@ namespace Microsoft::Console::Types
|
|||
};
|
||||
|
||||
public:
|
||||
UiaTextRangeBase(UiaTextRangeBase&&) = default;
|
||||
UiaTextRangeBase& operator=(const UiaTextRangeBase&) = default;
|
||||
UiaTextRangeBase& operator=(UiaTextRangeBase&&) = default;
|
||||
virtual ~UiaTextRangeBase() = default;
|
||||
|
||||
const IdType GetId() const;
|
||||
const Endpoint GetStart() const;
|
||||
const Endpoint GetEnd() const;
|
||||
const bool IsDegenerate() const;
|
||||
const IdType GetId() const noexcept;
|
||||
const Endpoint GetStart() const noexcept;
|
||||
const Endpoint GetEnd() const noexcept;
|
||||
const bool IsDegenerate() const noexcept;
|
||||
|
||||
// TODO GitHub #605:
|
||||
// only used for UiaData::FindText. Remove after Search added properly
|
||||
void SetRangeValues(const Endpoint start, const Endpoint end, const bool isDegenerate);
|
||||
void SetRangeValues(const Endpoint start, const Endpoint end, const bool isDegenerate) noexcept;
|
||||
|
||||
// IUnknown methods
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
AddRef();
|
||||
AddRef() override;
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
Release();
|
||||
Release() override;
|
||||
IFACEMETHODIMP QueryInterface(_In_ REFIID riid,
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface);
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface) override;
|
||||
|
||||
// ITextRangeProvider methods
|
||||
virtual IFACEMETHODIMP Clone(_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) = 0;
|
||||
IFACEMETHODIMP Compare(_In_opt_ ITextRangeProvider* pRange, _Out_ BOOL* pRetVal);
|
||||
IFACEMETHODIMP Compare(_In_opt_ ITextRangeProvider* pRange, _Out_ BOOL* pRetVal) noexcept override;
|
||||
IFACEMETHODIMP CompareEndpoints(_In_ TextPatternRangeEndpoint endpoint,
|
||||
_In_ ITextRangeProvider* pTargetRange,
|
||||
_In_ TextPatternRangeEndpoint targetEndpoint,
|
||||
_Out_ int* pRetVal);
|
||||
IFACEMETHODIMP ExpandToEnclosingUnit(_In_ TextUnit unit);
|
||||
_Out_ int* pRetVal) noexcept override;
|
||||
IFACEMETHODIMP ExpandToEnclosingUnit(_In_ TextUnit unit) override;
|
||||
IFACEMETHODIMP FindAttribute(_In_ TEXTATTRIBUTEID textAttributeId,
|
||||
_In_ VARIANT val,
|
||||
_In_ BOOL searchBackward,
|
||||
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal);
|
||||
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) noexcept override;
|
||||
virtual IFACEMETHODIMP FindText(_In_ BSTR text,
|
||||
_In_ BOOL searchBackward,
|
||||
_In_ BOOL ignoreCase,
|
||||
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) = 0;
|
||||
IFACEMETHODIMP GetAttributeValue(_In_ TEXTATTRIBUTEID textAttributeId,
|
||||
_Out_ VARIANT* pRetVal);
|
||||
IFACEMETHODIMP GetBoundingRectangles(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal);
|
||||
IFACEMETHODIMP GetEnclosingElement(_Outptr_result_maybenull_ IRawElementProviderSimple** ppRetVal);
|
||||
_Out_ VARIANT* pRetVal) noexcept override;
|
||||
IFACEMETHODIMP GetBoundingRectangles(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) override;
|
||||
IFACEMETHODIMP GetEnclosingElement(_Outptr_result_maybenull_ IRawElementProviderSimple** ppRetVal) override;
|
||||
IFACEMETHODIMP GetText(_In_ int maxLength,
|
||||
_Out_ BSTR* pRetVal);
|
||||
_Out_ BSTR* pRetVal) override;
|
||||
IFACEMETHODIMP Move(_In_ TextUnit unit,
|
||||
_In_ int count,
|
||||
_Out_ int* pRetVal);
|
||||
_Out_ int* pRetVal) override;
|
||||
IFACEMETHODIMP MoveEndpointByUnit(_In_ TextPatternRangeEndpoint endpoint,
|
||||
_In_ TextUnit unit,
|
||||
_In_ int count,
|
||||
_Out_ int* pRetVal);
|
||||
_Out_ int* pRetVal) override;
|
||||
IFACEMETHODIMP MoveEndpointByRange(_In_ TextPatternRangeEndpoint endpoint,
|
||||
_In_ ITextRangeProvider* pTargetRange,
|
||||
_In_ TextPatternRangeEndpoint targetEndpoint);
|
||||
IFACEMETHODIMP Select();
|
||||
IFACEMETHODIMP AddToSelection();
|
||||
IFACEMETHODIMP RemoveFromSelection();
|
||||
IFACEMETHODIMP ScrollIntoView(_In_ BOOL alignToTop);
|
||||
IFACEMETHODIMP GetChildren(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal);
|
||||
_In_ TextPatternRangeEndpoint targetEndpoint) override;
|
||||
IFACEMETHODIMP Select() override;
|
||||
IFACEMETHODIMP AddToSelection() noexcept override;
|
||||
IFACEMETHODIMP RemoveFromSelection() noexcept override;
|
||||
IFACEMETHODIMP ScrollIntoView(_In_ BOOL alignToTop) override;
|
||||
IFACEMETHODIMP GetChildren(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) noexcept override;
|
||||
|
||||
protected:
|
||||
#if _DEBUG
|
||||
|
@ -225,7 +228,7 @@ namespace Microsoft::Console::Types
|
|||
|
||||
void Initialize(_In_ const UiaPoint point);
|
||||
|
||||
UiaTextRangeBase(const UiaTextRangeBase& a);
|
||||
UiaTextRangeBase(const UiaTextRangeBase& a) noexcept;
|
||||
|
||||
// used to debug objects passed back and forth
|
||||
// between the provider and the client
|
||||
|
@ -259,126 +262,136 @@ namespace Microsoft::Console::Types
|
|||
|
||||
RECT _getTerminalRect() const;
|
||||
|
||||
static const COORD _getScreenBufferCoords(IUiaData* pData);
|
||||
static const COORD _getScreenBufferCoords(gsl::not_null<IUiaData*> pData);
|
||||
virtual const COORD _getScreenFontSize() const;
|
||||
|
||||
static const unsigned int _getTotalRows(IUiaData* pData);
|
||||
static const unsigned int _getRowWidth(IUiaData* pData);
|
||||
static const unsigned int _getTotalRows(gsl::not_null<IUiaData*> pData) noexcept;
|
||||
static const unsigned int _getRowWidth(gsl::not_null<IUiaData*> pData);
|
||||
|
||||
static const unsigned int _getFirstScreenInfoRowIndex();
|
||||
static const unsigned int _getLastScreenInfoRowIndex(IUiaData* pData);
|
||||
static const unsigned int _getFirstScreenInfoRowIndex() noexcept;
|
||||
static const unsigned int _getLastScreenInfoRowIndex(gsl::not_null<IUiaData*> pData) noexcept;
|
||||
|
||||
static const Column _getFirstColumnIndex();
|
||||
static const Column _getLastColumnIndex(IUiaData* pData);
|
||||
static const Column _getFirstColumnIndex() noexcept;
|
||||
static const Column _getLastColumnIndex(gsl::not_null<IUiaData*> pData);
|
||||
|
||||
const unsigned int _rowCountInRange(IUiaData* pData) const;
|
||||
const unsigned int _rowCountInRange(gsl::not_null<IUiaData*> pData) const;
|
||||
|
||||
static const TextBufferRow _endpointToTextBufferRow(IUiaData* pData,
|
||||
static const TextBufferRow _endpointToTextBufferRow(gsl::not_null<IUiaData*> pData,
|
||||
const Endpoint endpoint);
|
||||
static const ScreenInfoRow _textBufferRowToScreenInfoRow(IUiaData* pData,
|
||||
const TextBufferRow row);
|
||||
static const ScreenInfoRow _textBufferRowToScreenInfoRow(gsl::not_null<IUiaData*> pData,
|
||||
const TextBufferRow row) noexcept;
|
||||
|
||||
static const TextBufferRow _screenInfoRowToTextBufferRow(IUiaData* pData,
|
||||
const ScreenInfoRow row);
|
||||
static const Endpoint _textBufferRowToEndpoint(IUiaData* pData, const TextBufferRow row);
|
||||
static const TextBufferRow _screenInfoRowToTextBufferRow(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow row) noexcept;
|
||||
static const Endpoint _textBufferRowToEndpoint(gsl::not_null<IUiaData*> pData, const TextBufferRow row);
|
||||
|
||||
static const ScreenInfoRow _endpointToScreenInfoRow(IUiaData* pData,
|
||||
static const ScreenInfoRow _endpointToScreenInfoRow(gsl::not_null<IUiaData*> pData,
|
||||
const Endpoint endpoint);
|
||||
static const Endpoint _screenInfoRowToEndpoint(IUiaData* pData,
|
||||
static const Endpoint _screenInfoRowToEndpoint(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow row);
|
||||
|
||||
static COORD _endpointToCoord(IUiaData* pData,
|
||||
static COORD _endpointToCoord(gsl::not_null<IUiaData*> pData,
|
||||
const Endpoint endpoint);
|
||||
static Endpoint _coordToEndpoint(IUiaData* pData,
|
||||
static Endpoint _coordToEndpoint(gsl::not_null<IUiaData*> pData,
|
||||
const COORD coord);
|
||||
|
||||
static const Column _endpointToColumn(IUiaData* pData,
|
||||
static const Column _endpointToColumn(gsl::not_null<IUiaData*> pData,
|
||||
const Endpoint endpoint);
|
||||
|
||||
static const Row _normalizeRow(IUiaData* pData, const Row row);
|
||||
static const Row _normalizeRow(gsl::not_null<IUiaData*> pData, const Row row) noexcept;
|
||||
|
||||
static const ViewportRow _screenInfoRowToViewportRow(IUiaData* pData,
|
||||
const ScreenInfoRow row);
|
||||
static const ViewportRow _screenInfoRowToViewportRow(const ScreenInfoRow row,
|
||||
const SMALL_RECT viewport);
|
||||
static const ViewportRow _screenInfoRowToViewportRow(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow row) noexcept;
|
||||
// Routine Description:
|
||||
// - Converts a ScreenInfoRow to a ViewportRow.
|
||||
// Arguments:
|
||||
// - row - the ScreenInfoRow to convert
|
||||
// - viewport - the viewport to use for the conversion
|
||||
// Return Value:
|
||||
// - the equivalent ViewportRow.
|
||||
static constexpr const ViewportRow _screenInfoRowToViewportRow(const ScreenInfoRow row,
|
||||
const SMALL_RECT viewport) noexcept
|
||||
{
|
||||
return row - viewport.Top;
|
||||
}
|
||||
|
||||
static const bool _isScreenInfoRowInViewport(IUiaData* pData,
|
||||
const ScreenInfoRow row);
|
||||
static const bool _isScreenInfoRowInViewport(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow row) noexcept;
|
||||
static const bool _isScreenInfoRowInViewport(const ScreenInfoRow row,
|
||||
const SMALL_RECT viewport);
|
||||
const SMALL_RECT viewport) noexcept;
|
||||
|
||||
static const unsigned int _getViewportHeight(const SMALL_RECT viewport);
|
||||
static const unsigned int _getViewportWidth(const SMALL_RECT viewport);
|
||||
static const unsigned int _getViewportHeight(const SMALL_RECT viewport) noexcept;
|
||||
static const unsigned int _getViewportWidth(const SMALL_RECT viewport) noexcept;
|
||||
|
||||
void _addScreenInfoRowBoundaries(IUiaData* pData,
|
||||
void _addScreenInfoRowBoundaries(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow screenInfoRow,
|
||||
_Inout_ std::vector<double>& coords) const;
|
||||
|
||||
static const int _compareScreenCoords(IUiaData* pData,
|
||||
static const int _compareScreenCoords(gsl::not_null<IUiaData*> pData,
|
||||
const ScreenInfoRow rowA,
|
||||
const Column colA,
|
||||
const ScreenInfoRow rowB,
|
||||
const Column colB);
|
||||
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacter(IUiaData* pData,
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacter(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacterForward(IUiaData* pData,
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacterForward(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacterBackward(IUiaData* pData,
|
||||
static std::pair<Endpoint, Endpoint> _moveByCharacterBackward(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::pair<Endpoint, Endpoint> _moveByLine(IUiaData* pData,
|
||||
static std::pair<Endpoint, Endpoint> _moveByLine(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::pair<Endpoint, Endpoint> _moveByDocument(IUiaData* pData,
|
||||
static std::pair<Endpoint, Endpoint> _moveByDocument(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::tuple<Endpoint, Endpoint, bool>
|
||||
_moveEndpointByUnitCharacter(IUiaData* pData,
|
||||
_moveEndpointByUnitCharacter(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const TextPatternRangeEndpoint endpoint,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::tuple<Endpoint, Endpoint, bool>
|
||||
_moveEndpointByUnitCharacterForward(IUiaData* pData,
|
||||
_moveEndpointByUnitCharacterForward(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const TextPatternRangeEndpoint endpoint,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::tuple<Endpoint, Endpoint, bool>
|
||||
_moveEndpointByUnitCharacterBackward(IUiaData* pData,
|
||||
_moveEndpointByUnitCharacterBackward(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const TextPatternRangeEndpoint endpoint,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::tuple<Endpoint, Endpoint, bool>
|
||||
_moveEndpointByUnitLine(IUiaData* pData,
|
||||
_moveEndpointByUnitLine(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const TextPatternRangeEndpoint endpoint,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
static std::tuple<Endpoint, Endpoint, bool>
|
||||
_moveEndpointByUnitDocument(IUiaData* pData,
|
||||
_moveEndpointByUnitDocument(gsl::not_null<IUiaData*> pData,
|
||||
const int moveCount,
|
||||
const TextPatternRangeEndpoint endpoint,
|
||||
const MoveState moveState,
|
||||
_Out_ int* const pAmountMoved);
|
||||
_Out_ gsl::not_null<int*> const pAmountMoved);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class ::UiaTextRangeTests;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// - wstr - The UTF-16 string to parse.
|
||||
// Return Value:
|
||||
// - A view into the string given of just the next codepoint unit.
|
||||
std::wstring_view Utf16Parser::ParseNext(std::wstring_view wstr)
|
||||
std::wstring_view Utf16Parser::ParseNext(std::wstring_view wstr) noexcept
|
||||
{
|
||||
for (size_t pos = 0; pos < wstr.size(); ++pos)
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ WindowUiaProviderBase::AddRef()
|
|||
IFACEMETHODIMP_(ULONG)
|
||||
WindowUiaProviderBase::Release()
|
||||
{
|
||||
long val = InterlockedDecrement(&_cRefs);
|
||||
const long val = InterlockedDecrement(&_cRefs);
|
||||
if (val == 0)
|
||||
{
|
||||
delete this;
|
||||
|
@ -36,21 +36,13 @@ WindowUiaProviderBase::Release()
|
|||
|
||||
IFACEMETHODIMP WindowUiaProviderBase::QueryInterface(_In_ REFIID riid, _COM_Outptr_result_maybenull_ void** ppInterface)
|
||||
{
|
||||
if (riid == __uuidof(IUnknown))
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppInterface);
|
||||
if (riid == __uuidof(IUnknown) ||
|
||||
riid == __uuidof(IRawElementProviderSimple) ||
|
||||
riid == __uuidof(IRawElementProviderFragment) ||
|
||||
riid == __uuidof(IRawElementProviderFragmentRoot))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderSimple*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(IRawElementProviderSimple))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderSimple*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(IRawElementProviderFragment))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderFragment*>(this);
|
||||
}
|
||||
else if (riid == __uuidof(IRawElementProviderFragmentRoot))
|
||||
{
|
||||
*ppInterface = static_cast<IRawElementProviderFragmentRoot*>(this);
|
||||
*ppInterface = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -58,7 +50,7 @@ IFACEMETHODIMP WindowUiaProviderBase::QueryInterface(_In_ REFIID riid, _COM_Outp
|
|||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
(static_cast<IUnknown*>(*ppInterface))->AddRef();
|
||||
AddRef();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -71,6 +63,7 @@ IFACEMETHODIMP WindowUiaProviderBase::QueryInterface(_In_ REFIID riid, _COM_Outp
|
|||
// Gets UI Automation provider options.
|
||||
IFACEMETHODIMP WindowUiaProviderBase::get_ProviderOptions(_Out_ ProviderOptions* pOptions)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pOptions);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
*pOptions = ProviderOptions_ServerSideProvider;
|
||||
|
@ -82,6 +75,7 @@ IFACEMETHODIMP WindowUiaProviderBase::get_ProviderOptions(_Out_ ProviderOptions*
|
|||
IFACEMETHODIMP WindowUiaProviderBase::GetPatternProvider(_In_ PATTERNID /*patternId*/,
|
||||
_COM_Outptr_result_maybenull_ IUnknown** ppInterface)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppInterface);
|
||||
*ppInterface = nullptr;
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
|
@ -92,6 +86,7 @@ IFACEMETHODIMP WindowUiaProviderBase::GetPatternProvider(_In_ PATTERNID /*patter
|
|||
// Gets custom properties.
|
||||
IFACEMETHODIMP WindowUiaProviderBase::GetPropertyValue(_In_ PROPERTYID propertyId, _Out_ VARIANT* pVariant)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pVariant);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
pVariant->vt = VT_EMPTY;
|
||||
|
@ -148,6 +143,7 @@ IFACEMETHODIMP WindowUiaProviderBase::GetPropertyValue(_In_ PROPERTYID propertyI
|
|||
// supplies many properties.
|
||||
IFACEMETHODIMP WindowUiaProviderBase::get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppProvider);
|
||||
try
|
||||
{
|
||||
const HWND hwnd = GetWindowHandle();
|
||||
|
@ -155,7 +151,7 @@ IFACEMETHODIMP WindowUiaProviderBase::get_HostRawElementProvider(_COM_Outptr_res
|
|||
}
|
||||
catch (...)
|
||||
{
|
||||
return static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
|
||||
return gsl::narrow_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
@ -164,6 +160,7 @@ IFACEMETHODIMP WindowUiaProviderBase::get_HostRawElementProvider(_COM_Outptr_res
|
|||
|
||||
IFACEMETHODIMP WindowUiaProviderBase::GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRuntimeId);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
// Root defers this to host, others must implement it...
|
||||
*ppRuntimeId = nullptr;
|
||||
|
@ -173,6 +170,7 @@ IFACEMETHODIMP WindowUiaProviderBase::GetRuntimeId(_Outptr_result_maybenull_ SAF
|
|||
|
||||
IFACEMETHODIMP WindowUiaProviderBase::get_BoundingRectangle(_Out_ UiaRect* pRect)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pRect);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
const IUiaWindow* const pConsoleWindow = _baseWindow;
|
||||
|
@ -182,14 +180,20 @@ IFACEMETHODIMP WindowUiaProviderBase::get_BoundingRectangle(_Out_ UiaRect* pRect
|
|||
|
||||
pRect->left = rc.left;
|
||||
pRect->top = rc.top;
|
||||
pRect->width = rc.right - rc.left;
|
||||
pRect->height = rc.bottom - rc.top;
|
||||
|
||||
LONG longWidth = 0;
|
||||
RETURN_IF_FAILED(LongSub(rc.right, rc.left, &longWidth));
|
||||
pRect->width = longWidth;
|
||||
LONG longHeight = 0;
|
||||
RETURN_IF_FAILED(LongSub(rc.bottom, rc.top, &longHeight));
|
||||
pRect->height = longHeight;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP WindowUiaProviderBase::GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRoots);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
*ppRoots = nullptr;
|
||||
|
@ -198,6 +202,7 @@ IFACEMETHODIMP WindowUiaProviderBase::GetEmbeddedFragmentRoots(_Outptr_result_ma
|
|||
|
||||
IFACEMETHODIMP WindowUiaProviderBase::get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppProvider);
|
||||
RETURN_IF_FAILED(_EnsureValidHwnd());
|
||||
|
||||
*ppProvider = this;
|
||||
|
@ -209,10 +214,15 @@ IFACEMETHODIMP WindowUiaProviderBase::get_FragmentRoot(_COM_Outptr_result_mayben
|
|||
|
||||
HWND WindowUiaProviderBase::GetWindowHandle() const
|
||||
{
|
||||
IUiaWindow* const pConsoleWindow = _baseWindow;
|
||||
THROW_HR_IF_NULL(E_POINTER, pConsoleWindow);
|
||||
|
||||
return pConsoleWindow->GetWindowHandle();
|
||||
const IUiaWindow* const pConsoleWindow = _baseWindow;
|
||||
if (pConsoleWindow)
|
||||
{
|
||||
return pConsoleWindow->GetWindowHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT WindowUiaProviderBase::_EnsureValidHwnd() const
|
||||
|
|
|
@ -31,34 +31,44 @@ namespace Microsoft::Console::Types
|
|||
public IRawElementProviderFragment,
|
||||
public IRawElementProviderFragmentRoot
|
||||
{
|
||||
public:
|
||||
virtual ~WindowUiaProviderBase() = default;
|
||||
|
||||
protected:
|
||||
WindowUiaProviderBase() = default;
|
||||
WindowUiaProviderBase(const WindowUiaProviderBase&) = default;
|
||||
WindowUiaProviderBase(WindowUiaProviderBase&&) = default;
|
||||
WindowUiaProviderBase& operator=(const WindowUiaProviderBase&) = default;
|
||||
WindowUiaProviderBase& operator=(WindowUiaProviderBase&&) = default;
|
||||
|
||||
public:
|
||||
[[nodiscard]] virtual HRESULT Signal(_In_ EVENTID id) = 0;
|
||||
[[nodiscard]] virtual HRESULT SetTextAreaFocus() = 0;
|
||||
|
||||
// IUnknown methods
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
AddRef();
|
||||
AddRef() override;
|
||||
IFACEMETHODIMP_(ULONG)
|
||||
Release();
|
||||
Release() override;
|
||||
IFACEMETHODIMP QueryInterface(_In_ REFIID riid,
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface);
|
||||
_COM_Outptr_result_maybenull_ void** ppInterface) override;
|
||||
|
||||
// IRawElementProviderSimple methods
|
||||
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions);
|
||||
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions) override;
|
||||
IFACEMETHODIMP GetPatternProvider(_In_ PATTERNID iid,
|
||||
_COM_Outptr_result_maybenull_ IUnknown** ppInterface);
|
||||
_COM_Outptr_result_maybenull_ IUnknown** ppInterface) override;
|
||||
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
|
||||
_Out_ VARIANT* pVariant);
|
||||
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider);
|
||||
_Out_ VARIANT* pVariant) override;
|
||||
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider) override;
|
||||
|
||||
// IRawElementProviderFragment methods
|
||||
virtual IFACEMETHODIMP Navigate(_In_ NavigateDirection direction,
|
||||
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) = 0;
|
||||
IFACEMETHODIMP GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId);
|
||||
IFACEMETHODIMP get_BoundingRectangle(_Out_ UiaRect* pRect);
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots);
|
||||
IFACEMETHODIMP GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId) override;
|
||||
IFACEMETHODIMP get_BoundingRectangle(_Out_ UiaRect* pRect) override;
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots) override;
|
||||
virtual IFACEMETHODIMP SetFocus() = 0;
|
||||
IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider);
|
||||
IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider) override;
|
||||
|
||||
// IRawElementProviderFragmentRoot methods
|
||||
virtual IFACEMETHODIMP ElementProviderFromPoint(_In_ double x,
|
||||
|
|
|
@ -44,15 +44,15 @@ static const WORD leftShiftScanCode = 0x2A;
|
|||
size_t cchNeeded;
|
||||
THROW_IF_FAILED(IntToSizeT(iTarget, &cchNeeded));
|
||||
|
||||
// Allocate ourselves space in a smart pointer.
|
||||
std::unique_ptr<wchar_t[]> pwsOut = std::make_unique<wchar_t[]>(cchNeeded);
|
||||
THROW_IF_NULL_ALLOC(pwsOut);
|
||||
// Allocate ourselves some space
|
||||
std::wstring out;
|
||||
out.resize(cchNeeded);
|
||||
|
||||
// Attempt conversion for real.
|
||||
THROW_LAST_ERROR_IF(0 == MultiByteToWideChar(codePage, 0, source.data(), iSource, pwsOut.get(), iTarget));
|
||||
THROW_LAST_ERROR_IF(0 == MultiByteToWideChar(codePage, 0, source.data(), iSource, out.data(), iTarget));
|
||||
|
||||
// Return as a string
|
||||
return std::wstring(pwsOut.get(), cchNeeded);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -85,18 +85,18 @@ static const WORD leftShiftScanCode = 0x2A;
|
|||
size_t cchNeeded;
|
||||
THROW_IF_FAILED(IntToSizeT(iTarget, &cchNeeded));
|
||||
|
||||
// Allocate ourselves space in a smart pointer
|
||||
std::unique_ptr<char[]> psOut = std::make_unique<char[]>(cchNeeded);
|
||||
THROW_IF_NULL_ALLOC(psOut.get());
|
||||
// Allocate ourselves some space
|
||||
std::string out;
|
||||
out.resize(cchNeeded);
|
||||
|
||||
// Attempt conversion for real.
|
||||
// clang-format off
|
||||
#pragma prefast(suppress: __WARNING_W2A_BEST_FIT, "WC_NO_BEST_FIT_CHARS doesn't work in many codepages. Retain old behavior.")
|
||||
// clang-format on
|
||||
THROW_LAST_ERROR_IF(0 == WideCharToMultiByte(codepage, 0, source.data(), iSource, psOut.get(), iTarget, nullptr, nullptr));
|
||||
THROW_LAST_ERROR_IF(0 == WideCharToMultiByte(codepage, 0, source.data(), iSource, out.data(), iTarget, nullptr, nullptr));
|
||||
|
||||
// Return as a string
|
||||
return std::string(psOut.get(), cchNeeded);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -284,7 +284,7 @@ std::deque<std::unique_ptr<KeyEvent>> SynthesizeNumpadEvents(const wchar_t wch,
|
|||
// But it is absolutely valid as 0xFF or 255 unsigned as the correct CP437 character.
|
||||
// We need to treat it as unsigned because we're going to pretend it was a keypad entry
|
||||
// and you don't enter negative numbers on the keypad.
|
||||
unsigned char const uch = static_cast<unsigned char>(convertedChars[0]);
|
||||
unsigned char const uch = static_cast<unsigned char>(convertedChars.at(0));
|
||||
|
||||
// unsigned char values are in the range [0, 255] so we need to be
|
||||
// able to store up to 4 chars from the conversion (including the end of string char)
|
||||
|
|
|
@ -23,13 +23,14 @@ static_assert(sizeof(unsigned int) == sizeof(wchar_t) * 2,
|
|||
class CodepointWidthDetector final
|
||||
{
|
||||
public:
|
||||
CodepointWidthDetector() = default;
|
||||
CodepointWidthDetector() noexcept;
|
||||
CodepointWidthDetector(const CodepointWidthDetector&) = delete;
|
||||
CodepointWidthDetector(CodepointWidthDetector&&) = delete;
|
||||
~CodepointWidthDetector() = default;
|
||||
CodepointWidthDetector& operator=(const CodepointWidthDetector&) = delete;
|
||||
CodepointWidthDetector& operator=(CodepointWidthDetector&&) = delete;
|
||||
|
||||
CodepointWidth GetWidth(const std::wstring_view glyph) const noexcept;
|
||||
CodepointWidth GetWidth(const std::wstring_view glyph) const;
|
||||
bool IsWide(const std::wstring_view glyph) const;
|
||||
bool IsWide(const wchar_t wch) const noexcept;
|
||||
void SetFallbackMethod(std::function<bool(const std::wstring_view)> pfnFallback);
|
||||
|
|
|
@ -13,6 +13,6 @@ Abstract:
|
|||
#include <string_view>
|
||||
|
||||
bool IsGlyphFullWidth(const std::wstring_view glyph);
|
||||
bool IsGlyphFullWidth(const wchar_t wch);
|
||||
bool IsGlyphFullWidth(const wchar_t wch) noexcept;
|
||||
void SetGlyphWidthFallback(std::function<bool(std::wstring_view)> pfnFallback);
|
||||
void NotifyGlyphWidthFontChanged();
|
||||
void NotifyGlyphWidthFontChanged() noexcept;
|
||||
|
|
|
@ -245,7 +245,7 @@ public:
|
|||
void SetActiveModifierKeys(const DWORD activeModifierKeys) noexcept;
|
||||
void DeactivateModifierKey(const ModifierKeyState modifierKey) noexcept;
|
||||
void ActivateModifierKey(const ModifierKeyState modifierKey) noexcept;
|
||||
bool DoActiveModifierKeysMatch(const std::unordered_set<ModifierKeyState>& consoleModifiers) const noexcept;
|
||||
bool DoActiveModifierKeysMatch(const std::unordered_set<ModifierKeyState>& consoleModifiers) const;
|
||||
bool IsCommandLineEditingKey() const noexcept;
|
||||
bool IsPopupKey() const noexcept;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ Author(s):
|
|||
class UTF8OutPipeReader final
|
||||
{
|
||||
public:
|
||||
UTF8OutPipeReader(HANDLE outPipe);
|
||||
UTF8OutPipeReader(HANDLE outPipe) noexcept;
|
||||
[[nodiscard]] HRESULT Read(_Out_ std::string_view& strView);
|
||||
|
||||
private:
|
||||
|
@ -46,7 +46,7 @@ private:
|
|||
};
|
||||
|
||||
// array of bitmasks
|
||||
constexpr const static BYTE _cmpMasks[]{
|
||||
constexpr static std::array<BYTE, 4> _cmpMasks{
|
||||
0, // unused
|
||||
_Utf8BitMasks::MaskContinuationByte,
|
||||
_Utf8BitMasks::MaskLeadByteTwoByteSequence,
|
||||
|
@ -54,7 +54,7 @@ private:
|
|||
};
|
||||
|
||||
// array of values for the comparisons
|
||||
constexpr const static BYTE _cmpOperands[]{
|
||||
constexpr static std::array<BYTE, 4> _cmpOperands{
|
||||
0, // unused
|
||||
_Utf8BitMasks::IsAsciiByte, // intentionally conflicts with MaskContinuationByte
|
||||
_Utf8BitMasks::IsLeadByteTwoByteSequence,
|
||||
|
@ -62,7 +62,7 @@ private:
|
|||
};
|
||||
|
||||
HANDLE _outPipe; // non-owning reference to a pipe.
|
||||
BYTE _buffer[4096]{ 0 }; // buffer for the chunk read
|
||||
BYTE _utf8Partials[4]{ 0 }; // buffer for code units of a partial UTF-8 code point that have to be cached
|
||||
std::array<char, 4096> _buffer; // buffer for the chunk read.
|
||||
std::array<char, 4> _utf8Partials; // buffer for code units of a partial UTF-8 code point that have to be cached
|
||||
DWORD _dwPartialsLen{}; // number of cached UTF-8 code units
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@ private:
|
|||
|
||||
public:
|
||||
static std::vector<std::vector<wchar_t>> Parse(std::wstring_view wstr);
|
||||
static std::wstring_view ParseNext(std::wstring_view wstr);
|
||||
static std::wstring_view ParseNext(std::wstring_view wstr) noexcept;
|
||||
|
||||
// Routine Description:
|
||||
// - checks if wchar is a utf16 leading surrogate
|
||||
|
|
|
@ -15,7 +15,19 @@ namespace Microsoft::Console::Utils
|
|||
{
|
||||
bool IsValidHandle(const HANDLE handle) noexcept;
|
||||
|
||||
short ClampToShortMax(const long value, const short min);
|
||||
// Function Description:
|
||||
// - Clamps a long in between `min` and `SHRT_MAX`
|
||||
// Arguments:
|
||||
// - value: the value to clamp
|
||||
// - min: the minimum value to clamp to
|
||||
// Return Value:
|
||||
// - The clamped value as a short.
|
||||
constexpr short ClampToShortMax(const long value, const short min) noexcept
|
||||
{
|
||||
return static_cast<short>(std::clamp(value,
|
||||
static_cast<long>(min),
|
||||
static_cast<long>(SHRT_MAX)));
|
||||
}
|
||||
|
||||
std::wstring GuidToString(const GUID guid);
|
||||
GUID GuidFromString(const std::wstring wstr);
|
||||
|
@ -24,11 +36,26 @@ namespace Microsoft::Console::Utils
|
|||
std::string ColorToHexString(const COLORREF color);
|
||||
COLORREF ColorFromHexString(const std::string wstr);
|
||||
|
||||
void InitializeCampbellColorTable(gsl::span<COLORREF>& table);
|
||||
void InitializeCampbellColorTableForConhost(gsl::span<COLORREF>& table);
|
||||
void SwapANSIColorOrderForConhost(gsl::span<COLORREF>& table);
|
||||
void Initialize256ColorTable(gsl::span<COLORREF>& table);
|
||||
void SetColorTableAlpha(gsl::span<COLORREF>& table, const BYTE newAlpha);
|
||||
void InitializeCampbellColorTable(const gsl::span<COLORREF> table);
|
||||
void InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table);
|
||||
void SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table);
|
||||
void Initialize256ColorTable(const gsl::span<COLORREF> table);
|
||||
|
||||
// Function Description:
|
||||
// - Fill the alpha byte of the colors in a given color table with the given value.
|
||||
// Arguments:
|
||||
// - table: a color table
|
||||
// - newAlpha: the new value to use as the alpha for all the entries in that table.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
constexpr void SetColorTableAlpha(const gsl::span<COLORREF> table, const BYTE newAlpha) noexcept
|
||||
{
|
||||
const auto shiftedAlpha = newAlpha << 24;
|
||||
for (auto& color : table)
|
||||
{
|
||||
WI_UpdateFlagsInMask(color, 0xff000000, shiftedAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint16_t EndianSwap(uint16_t value)
|
||||
{
|
||||
|
@ -46,7 +73,7 @@ namespace Microsoft::Console::Utils
|
|||
|
||||
constexpr unsigned long EndianSwap(unsigned long value)
|
||||
{
|
||||
return static_cast<unsigned long>(EndianSwap(static_cast<uint32_t>(value)));
|
||||
return gsl::narrow_cast<unsigned long>(EndianSwap(gsl::narrow_cast<uint32_t>(value)));
|
||||
}
|
||||
|
||||
constexpr GUID EndianSwap(GUID value)
|
||||
|
@ -57,5 +84,5 @@ namespace Microsoft::Console::Utils
|
|||
return value;
|
||||
}
|
||||
|
||||
GUID CreateV5Uuid(const GUID& namespaceGuid, const gsl::span<const gsl::byte>& name);
|
||||
GUID CreateV5Uuid(const GUID& namespaceGuid, const gsl::span<const gsl::byte> name);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace Microsoft::Console::Types
|
|||
bool IsInBounds(const COORD& pos) const noexcept;
|
||||
|
||||
void Clamp(COORD& pos) const;
|
||||
Viewport Clamp(const Viewport& other) const;
|
||||
Viewport Clamp(const Viewport& other) const noexcept;
|
||||
|
||||
bool MoveInBounds(const ptrdiff_t move, COORD& pos) const noexcept;
|
||||
bool IncrementInBounds(COORD& pos) const noexcept;
|
||||
|
|
|
@ -52,11 +52,11 @@ void UtilsTests::TestSwapColorPalette()
|
|||
std::array<COLORREF, COLOR_TABLE_SIZE> consoleTable;
|
||||
|
||||
gsl::span<COLORREF> terminalTableView = { &terminalTable[0], gsl::narrow<ptrdiff_t>(terminalTable.size()) };
|
||||
gsl::span<COLORREF> consoleTableleView = { &consoleTable[0], gsl::narrow<ptrdiff_t>(consoleTable.size()) };
|
||||
gsl::span<COLORREF> consoleTableView = { &consoleTable[0], gsl::narrow<ptrdiff_t>(consoleTable.size()) };
|
||||
|
||||
// First set up the colors
|
||||
InitializeCampbellColorTable(terminalTableView);
|
||||
InitializeCampbellColorTableForConhost(consoleTableleView);
|
||||
InitializeCampbellColorTableForConhost(consoleTableView);
|
||||
|
||||
VERIFY_ARE_EQUAL(terminalTable[0], consoleTable[0]);
|
||||
VERIFY_ARE_EQUAL(terminalTable[1], consoleTable[4]);
|
||||
|
|
|
@ -6,20 +6,6 @@
|
|||
|
||||
using namespace Microsoft::Console;
|
||||
|
||||
// Function Description:
|
||||
// - Clamps a long in between `min` and `SHRT_MAX`
|
||||
// Arguments:
|
||||
// - value: the value to clamp
|
||||
// - min: the minimum value to clamp to
|
||||
// Return Value:
|
||||
// - The clamped value as a short.
|
||||
short Utils::ClampToShortMax(const long value, const short min)
|
||||
{
|
||||
return static_cast<short>(std::clamp(value,
|
||||
static_cast<long>(min),
|
||||
static_cast<long>(SHRT_MAX)));
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a String representation of a guid, in the format
|
||||
// "{12345678-ABCD-EF12-3456-7890ABCDEF12}"
|
||||
|
@ -29,12 +15,12 @@ short Utils::ClampToShortMax(const long value, const short min)
|
|||
// - a string representation of the GUID. On failure, throws E_INVALIDARG.
|
||||
std::wstring Utils::GuidToString(const GUID guid)
|
||||
{
|
||||
wchar_t guid_cstr[39];
|
||||
const int written = swprintf(guid_cstr, sizeof(guid_cstr), L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
std::array<wchar_t, 39> guid_cstr;
|
||||
const int written = swprintf(guid_cstr.data(), guid_cstr.size(), L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
|
||||
THROW_HR_IF(E_INVALIDARG, written == -1);
|
||||
|
||||
return std::wstring(guid_cstr);
|
||||
return std::wstring(guid_cstr.data(), guid_cstr.size());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -92,7 +78,7 @@ std::string Utils::ColorToHexString(const COLORREF color)
|
|||
COLORREF Utils::ColorFromHexString(const std::string str)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, str.size() != 7 && str.size() != 4);
|
||||
THROW_HR_IF(E_INVALIDARG, str[0] != '#');
|
||||
THROW_HR_IF(E_INVALIDARG, str.at(0) != '#');
|
||||
|
||||
std::string rStr;
|
||||
std::string gStr;
|
||||
|
@ -100,20 +86,20 @@ COLORREF Utils::ColorFromHexString(const std::string str)
|
|||
|
||||
if (str.size() == 4)
|
||||
{
|
||||
rStr = std::string(2, str[1]);
|
||||
gStr = std::string(2, str[2]);
|
||||
bStr = std::string(2, str[3]);
|
||||
rStr = std::string(2, str.at(1));
|
||||
gStr = std::string(2, str.at(2));
|
||||
bStr = std::string(2, str.at(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
rStr = std::string(&str[1], 2);
|
||||
gStr = std::string(&str[3], 2);
|
||||
bStr = std::string(&str[5], 2);
|
||||
rStr = std::string(&str.at(1), 2);
|
||||
gStr = std::string(&str.at(3), 2);
|
||||
bStr = std::string(&str.at(5), 2);
|
||||
}
|
||||
|
||||
BYTE r = static_cast<BYTE>(std::stoul(rStr, nullptr, 16));
|
||||
BYTE g = static_cast<BYTE>(std::stoul(gStr, nullptr, 16));
|
||||
BYTE b = static_cast<BYTE>(std::stoul(bStr, nullptr, 16));
|
||||
const BYTE r = gsl::narrow_cast<BYTE>(std::stoul(rStr, nullptr, 16));
|
||||
const BYTE g = gsl::narrow_cast<BYTE>(std::stoul(gStr, nullptr, 16));
|
||||
const BYTE b = gsl::narrow_cast<BYTE>(std::stoul(bStr, nullptr, 16));
|
||||
|
||||
return RGB(r, g, b);
|
||||
}
|
||||
|
@ -126,7 +112,7 @@ COLORREF Utils::ColorFromHexString(const std::string str)
|
|||
// - True if non zero and not set to invalid magic value. False otherwise.
|
||||
bool Utils::IsValidHandle(const HANDLE handle) noexcept
|
||||
{
|
||||
return handle != 0 && handle != INVALID_HANDLE_VALUE;
|
||||
return handle != nullptr && handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -136,7 +122,7 @@ bool Utils::IsValidHandle(const HANDLE handle) noexcept
|
|||
// - table: a color table with at least 16 entries
|
||||
// Return Value:
|
||||
// - <none>, throws if the table has less that 16 entries
|
||||
void Utils::InitializeCampbellColorTable(gsl::span<COLORREF>& table)
|
||||
void Utils::InitializeCampbellColorTable(const gsl::span<COLORREF> table)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
||||
|
||||
|
@ -167,7 +153,7 @@ void Utils::InitializeCampbellColorTable(gsl::span<COLORREF>& table)
|
|||
// - table: a color table with at least 16 entries
|
||||
// Return Value:
|
||||
// - <none>, throws if the table has less that 16 entries
|
||||
void Utils::InitializeCampbellColorTableForConhost(gsl::span<COLORREF>& table)
|
||||
void Utils::InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
||||
InitializeCampbellColorTable(table);
|
||||
|
@ -180,7 +166,7 @@ void Utils::InitializeCampbellColorTableForConhost(gsl::span<COLORREF>& table)
|
|||
// - table: a color table with at least 16 entries
|
||||
// Return Value:
|
||||
// - <none>, throws if the table has less that 16 entries
|
||||
void Utils::SwapANSIColorOrderForConhost(gsl::span<COLORREF>& table)
|
||||
void Utils::SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
||||
std::swap(table[1], table[4]);
|
||||
|
@ -196,7 +182,7 @@ void Utils::SwapANSIColorOrderForConhost(gsl::span<COLORREF>& table)
|
|||
// - table: a color table with at least 256 entries
|
||||
// Return Value:
|
||||
// - <none>, throws if the table has less that 256 entries
|
||||
void Utils::Initialize256ColorTable(gsl::span<COLORREF>& table)
|
||||
void Utils::Initialize256ColorTable(const gsl::span<COLORREF> table)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, table.size() < 256);
|
||||
|
||||
|
@ -460,22 +446,6 @@ void Utils::Initialize256ColorTable(gsl::span<COLORREF>& table)
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Fill the alpha byte of the colors in a given color table with the given value.
|
||||
// Arguments:
|
||||
// - table: a color table
|
||||
// - newAlpha: the new value to use as the alpha for all the entries in that table.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Utils::SetColorTableAlpha(gsl::span<COLORREF>& table, const BYTE newAlpha)
|
||||
{
|
||||
const auto shiftedAlpha = newAlpha << 24;
|
||||
for (auto& color : table)
|
||||
{
|
||||
WI_UpdateFlagsInMask(color, 0xff000000, shiftedAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Generate a Version 5 UUID (specified in RFC4122 4.3)
|
||||
// v5 UUIDs are stable given the same namespace and "name".
|
||||
|
@ -486,7 +456,7 @@ void Utils::SetColorTableAlpha(gsl::span<COLORREF>& table, const BYTE newAlpha)
|
|||
// - name: Bytes comprising the name (in a namespace-specific format)
|
||||
// Return Value:
|
||||
// - a new stable v5 UUID
|
||||
GUID Utils::CreateV5Uuid(const GUID& namespaceGuid, const gsl::span<const gsl::byte>& name)
|
||||
GUID Utils::CreateV5Uuid(const GUID& namespaceGuid, const gsl::span<const gsl::byte> name)
|
||||
{
|
||||
// v5 uuid generation happens over values in network byte order, so let's enforce that
|
||||
auto correctEndianNamespaceGuid{ EndianSwap(namespaceGuid) };
|
||||
|
@ -503,8 +473,8 @@ GUID Utils::CreateV5Uuid(const GUID& namespaceGuid, const gsl::span<const gsl::b
|
|||
std::array<uint8_t, 20> buffer;
|
||||
THROW_IF_NTSTATUS_FAILED(BCryptFinishHash(hash.get(), buffer.data(), gsl::narrow<ULONG>(buffer.size()), 0));
|
||||
|
||||
buffer[6] = (buffer[6] & 0x0F) | 0x50; // set the uuid version to 5
|
||||
buffer[8] = (buffer[8] & 0x3F) | 0x80; // set the variant to 2 (RFC4122)
|
||||
buffer.at(6) = (buffer.at(6) & 0x0F) | 0x50; // set the uuid version to 5
|
||||
buffer.at(8) = (buffer.at(8) & 0x3F) | 0x80; // set the variant to 2 (RFC4122)
|
||||
|
||||
// We're using memcpy here pursuant to N4713 6.7.2/3 [basic.types],
|
||||
// "...the underlying bytes making up the object can be copied into an array
|
||||
|
|
|
@ -194,7 +194,7 @@ void Viewport::Clamp(COORD& pos) const
|
|||
// - other - Viewport to clamp to the inside of this viewport
|
||||
// Return Value:
|
||||
// - Clamped viewport
|
||||
Viewport Viewport::Clamp(const Viewport& other) const
|
||||
Viewport Viewport::Clamp(const Viewport& other) const noexcept
|
||||
{
|
||||
auto clampMe = other.ToInclusive();
|
||||
|
||||
|
@ -450,7 +450,7 @@ bool Viewport::WalkInBoundsCircular(COORD& pos, const WalkDir dir) const noexcep
|
|||
// if using this same viewport with the `WalkInBounds` methods.
|
||||
COORD Viewport::GetWalkOrigin(const WalkDir dir) const noexcept
|
||||
{
|
||||
COORD origin;
|
||||
COORD origin{ 0 };
|
||||
origin.X = dir.x == XWalk::LeftToRight ? Left() : RightInclusive();
|
||||
origin.Y = dir.y == YWalk::TopToBottom ? Top() : BottomInclusive();
|
||||
return origin;
|
||||
|
|
Loading…
Reference in a new issue