diff --git a/src/StaticAnalysis.ruleset b/src/StaticAnalysis.ruleset index e9d2a69ed8d..114c0cc5c2f 100644 --- a/src/StaticAnalysis.ruleset +++ b/src/StaticAnalysis.ruleset @@ -1,11 +1,15 @@  - + - - - + + + + + + + diff --git a/src/buffer/out/AttrRow.cpp b/src/buffer/out/AttrRow.cpp index e9efd8f6037..c97bcbba884 100644 --- a/src/buffer/out/AttrRow.cpp +++ b/src/buffer/out/AttrRow.cpp @@ -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(); diff --git a/src/buffer/out/AttrRowIterator.cpp b/src/buffer/out/AttrRowIterator.cpp index 0462afa144c..c4e735d3e11 100644 --- a/src/buffer/out/AttrRowIterator.cpp +++ b/src/buffer/out/AttrRowIterator.cpp @@ -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; diff --git a/src/buffer/out/AttrRowIterator.hpp b/src/buffer/out/AttrRowIterator.hpp index 5ca7f72c125..c9e053ea247 100644 --- a/src/buffer/out/AttrRowIterator.hpp +++ b/src/buffer/out/AttrRowIterator.hpp @@ -29,11 +29,11 @@ class AttrRowIterator final 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 @@ class AttrRowIterator final void _increment(size_t count); void _decrement(size_t count); - void _setToEnd(); + void _setToEnd() noexcept; }; diff --git a/src/buffer/out/CharRow.cpp b/src/buffer/out/CharRow.cpp index 60a7d0d144c..8ac4ea217da 100644 --- a/src/buffer/out/CharRow.cpp +++ b/src/buffer/out/CharRow.cpp @@ -84,7 +84,7 @@ size_t CharRow::size() const noexcept // - sRowWidth - The width of the row. // Return Value: // - -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(static_cast(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(column), _pParent->GetId() }; } diff --git a/src/buffer/out/CharRow.hpp b/src/buffer/out/CharRow.hpp index c9ff3a0ae17..e1b802d065f 100644 --- a/src/buffer/out/CharRow.hpp +++ b/src/buffer/out/CharRow.hpp @@ -53,7 +53,7 @@ class CharRow final 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 @@ class CharRow final 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 @@ class CharRow final 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; diff --git a/src/buffer/out/CharRowCell.cpp b/src/buffer/out/CharRowCell.cpp index a6c2d2fb66e..d8cdeff429c 100644 --- a/src/buffer/out/CharRowCell.cpp +++ b/src/buffer/out/CharRowCell.cpp @@ -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()) { diff --git a/src/buffer/out/CharRowCell.hpp b/src/buffer/out/CharRowCell.hpp index fd8785bafd7..9ce8ee16b45 100644 --- a/src/buffer/out/CharRowCell.hpp +++ b/src/buffer/out/CharRowCell.hpp @@ -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; diff --git a/src/buffer/out/CharRowCellReference.cpp b/src/buffer/out/CharRowCellReference.cpp index 1f320756bd0..0f8a2e1a574 100644 --- a/src/buffer/out/CharRowCellReference.cpp +++ b/src/buffer/out/CharRowCellReference.cpp @@ -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& glyph) { diff --git a/src/buffer/out/CharRowCellReference.hpp b/src/buffer/out/CharRowCellReference.hpp index 64a42a17710..24e2ae45fe9 100644 --- a/src/buffer/out/CharRowCellReference.hpp +++ b/src/buffer/out/CharRowCellReference.hpp @@ -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 } { diff --git a/src/buffer/out/DbcsAttribute.hpp b/src/buffer/out/DbcsAttribute.hpp index f92a707b167..442505052c3 100644 --- a/src/buffer/out/DbcsAttribute.hpp +++ b/src/buffer/out/DbcsAttribute.hpp @@ -63,7 +63,7 @@ class DbcsAttribute final return _glyphStored; } - void SetGlyphStored(const bool stored) + void SetGlyphStored(const bool stored) noexcept { _glyphStored = stored; } diff --git a/src/buffer/out/OutputCell.cpp b/src/buffer/out/OutputCell.cpp index 59dc1c1f8b2..ad30b996bdb 100644 --- a/src/buffer/out/OutputCell.cpp +++ b/src/buffer/out/OutputCell.cpp @@ -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(); } diff --git a/src/buffer/out/OutputCell.hpp b/src/buffer/out/OutputCell.hpp index 8599ddf7cb3..df64e0b461e 100644 --- a/src/buffer/out/OutputCell.hpp +++ b/src/buffer/out/OutputCell.hpp @@ -25,7 +25,7 @@ Module Name: 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, diff --git a/src/buffer/out/OutputCellIterator.cpp b/src/buffer/out/OutputCellIterator.cpp index 2068e73af58..dbd9fb8bb7a 100644 --- a/src/buffer/out/OutputCellIterator.cpp +++ b/src/buffer/out/OutputCellIterator.cpp @@ -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 // 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 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 legacyAttrs, const bool /*unused*/) noexcept : _mode(Mode::LegacyAttr), _currentView(s_GenerateViewLegacyAttr(legacyAttrs.at(0))), _run(std::wstring_view(reinterpret_cast(legacyAttrs.data()), legacyAttrs.size())), @@ -126,12 +131,13 @@ OutputCellIterator::OutputCellIterator(const std::basic_string_view 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 charInfos) : +OutputCellIterator::OutputCellIterator(const std::basic_string_view 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); diff --git a/src/buffer/out/OutputCellIterator.hpp b/src/buffer/out/OutputCellIterator.hpp index b5b29050760..02f6aefa54e 100644 --- a/src/buffer/out/OutputCellIterator.hpp +++ b/src/buffer/out/OutputCellIterator.hpp @@ -33,14 +33,14 @@ class OutputCellIterator final 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 legacyAttributes, const bool unused); - OutputCellIterator(const std::basic_string_view charInfos); + OutputCellIterator(const std::basic_string_view legacyAttributes, const bool unused) noexcept; + OutputCellIterator(const std::basic_string_view charInfos) noexcept; OutputCellIterator(const std::basic_string_view cells); ~OutputCellIterator() = default; @@ -55,8 +55,8 @@ class OutputCellIterator final 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 @@ class OutputCellIterator final TextAttribute _attr; - bool _TryMoveTrailing(); + bool _TryMoveTrailing() noexcept; static OutputCellView s_GenerateView(const std::wstring_view view); @@ -108,11 +108,11 @@ class OutputCellIterator final 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); diff --git a/src/buffer/out/OutputCellRect.cpp b/src/buffer/out/OutputCellRect.cpp index 37711c5343b..90385094465 100644 --- a/src/buffer/out/OutputCellRect.cpp +++ b/src/buffer/out/OutputCellRect.cpp @@ -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: diff --git a/src/buffer/out/OutputCellRect.hpp b/src/buffer/out/OutputCellRect.hpp index ae73232505d..ebdb4883e35 100644 --- a/src/buffer/out/OutputCellRect.hpp +++ b/src/buffer/out/OutputCellRect.hpp @@ -29,7 +29,7 @@ Revision History: class OutputCellRect final { public: - OutputCellRect(); + OutputCellRect() noexcept; OutputCellRect(const size_t rows, const size_t cols); gsl::span GetRow(const size_t row); diff --git a/src/buffer/out/OutputCellView.cpp b/src/buffer/out/OutputCellView.cpp index 434333c030f..cd1f16a7646 100644 --- a/src/buffer/out/OutputCellView.cpp +++ b/src/buffer/out/OutputCellView.cpp @@ -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; } diff --git a/src/buffer/out/OutputCellView.hpp b/src/buffer/out/OutputCellView.hpp index 2c425d8088a..06c9b86af21 100644 --- a/src/buffer/out/OutputCellView.hpp +++ b/src/buffer/out/OutputCellView.hpp @@ -28,7 +28,7 @@ class OutputCellView 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; diff --git a/src/buffer/out/Row.cpp b/src/buffer/out/Row.cpp index 44ffd941f04..4172374af6d 100644 --- a/src/buffer/out/Row.cpp +++ b/src/buffer/out/Row.cpp @@ -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(static_cast(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(static_cast(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(); } diff --git a/src/buffer/out/Row.hpp b/src/buffer/out/Row.hpp index 5bf05c858f6..27d2a390928 100644 --- a/src/buffer/out/Row.hpp +++ b/src/buffer/out/Row.hpp @@ -36,8 +36,8 @@ class ROW final 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 @@ class ROW final 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 limitRight = std::nullopt); diff --git a/src/buffer/out/RowCellIterator.cpp b/src/buffer/out/RowCellIterator.cpp index 0381e4d933e..0dedc264a25 100644 --- a/src/buffer/out/RowCellIterator.cpp +++ b/src/buffer/out/RowCellIterator.cpp @@ -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; } diff --git a/src/buffer/out/RowCellIterator.hpp b/src/buffer/out/RowCellIterator.hpp index c386bb6afa1..62d6ffc1c14 100644 --- a/src/buffer/out/RowCellIterator.hpp +++ b/src/buffer/out/RowCellIterator.hpp @@ -38,13 +38,13 @@ class RowCellIterator final 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; diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp index 84e100afa30..0c964b848e9 100644 --- a/src/buffer/out/TextAttribute.cpp +++ b/src/buffer/out/TextAttribute.cpp @@ -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 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 // - color that should be displayed as the background color COLORREF TextAttribute::CalculateRgbBackground(std::basic_string_view 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 // Return Value: // - color that is stored as the foreground color COLORREF TextAttribute::_GetRgbForeground(std::basic_string_view 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 color // Return Value: // - color that is stored as the background color COLORREF TextAttribute::_GetRgbBackground(std::basic_string_view 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(wLegacy & META_ATTRS); + _wAttrLegacy = gsl::narrow_cast(wLegacy & META_ATTRS); WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS); - BYTE fgIndex = static_cast(wLegacy & FG_ATTRS); - BYTE bgIndex = static_cast(wLegacy & BG_ATTRS) >> 4; + const BYTE fgIndex = gsl::narrow_cast(wLegacy & FG_ATTRS); + const BYTE bgIndex = gsl::narrow_cast(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(attrs & FG_ATTRS); _foreground = TextColor(fgIndex); } if (setBackground) { - BYTE bgIndex = (BYTE)(attrs & BG_ATTRS) >> 4; + const BYTE bgIndex = gsl::narrow_cast(attrs & BG_ATTRS) >> 4; _background = TextColor(bgIndex); } if (setMeta) @@ -133,17 +133,17 @@ void TextAttribute::SetIndexedAttributes(const std::optional 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) { diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index 1a53bbb611e..eb8cc6111df 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -39,9 +39,9 @@ class TextAttribute final } constexpr TextAttribute(const WORD wLegacyAttr) noexcept : - _wAttrLegacy{ static_cast(wLegacyAttr & META_ATTRS) }, - _foreground{ static_cast(wLegacyAttr & FG_ATTRS) }, - _background{ static_cast((wLegacyAttr & BG_ATTRS) >> 4) }, + _wAttrLegacy{ gsl::narrow_cast(wLegacyAttr & META_ATTRS) }, + _foreground{ gsl::narrow_cast(wLegacyAttr & FG_ATTRS) }, + _background{ gsl::narrow_cast((wLegacyAttr & BG_ATTRS) >> 4) }, _isBold{ false } { // If we're given lead/trailing byte information with the legacy color, strip it. @@ -59,9 +59,9 @@ class TextAttribute final 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 @@ class TextAttribute final 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 colorTable, COLORREF defaultFgColor, - COLORREF defaultBgColor) const; + COLORREF defaultBgColor) const noexcept; COLORREF CalculateRgbBackground(std::basic_string_view colorTable, COLORREF defaultFgColor, - COLORREF defaultBgColor) const; + COLORREF defaultBgColor) const noexcept; bool IsLeadingByte() const noexcept; bool IsTrailingByte() const noexcept; @@ -110,7 +110,7 @@ class TextAttribute final void SetLegacyAttributes(const WORD attrs, const bool setForeground, const bool setBackground, - const bool setMeta); + const bool setMeta) noexcept; void SetIndexedAttributes(const std::optional foreground, const std::optional background) noexcept; @@ -133,9 +133,9 @@ class TextAttribute final 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 @@ class TextAttribute final private: COLORREF _GetRgbForeground(std::basic_string_view colorTable, - COLORREF defaultColor) const; + COLORREF defaultColor) const noexcept; COLORREF _GetRgbBackground(std::basic_string_view colorTable, - COLORREF defaultColor) const; + COLORREF defaultColor) const noexcept; bool _IsReverseVideo() const noexcept; void _SetBoldness(const bool isBold) noexcept; diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index 76778a8230b..606afdac148 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -11,7 +11,7 @@ // - rgbColor: the COLORREF containing the color information for this TextColor // Return Value: // - -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: // - -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) // - // Return Value: // - -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 colorTable, const COLORREF defaultColor, - bool brighten) const + bool brighten) const noexcept { if (IsDefault()) { @@ -81,9 +81,9 @@ COLORREF TextColor::GetColor(std::basic_string_view 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 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(_index) + 8 > colorTable.size()); + return colorTable.at(gsl::narrow_cast(_index) + 8); } else { - return colorTable[_index]; + return colorTable.at(_index); } } } @@ -119,7 +119,7 @@ COLORREF TextColor::GetColor(std::basic_string_view colorTable, // - // Return Value: // - a COLORREF containing our stored value -COLORREF TextColor::_GetRGB() const +COLORREF TextColor::_GetRGB() const noexcept { return RGB(_red, _green, _blue); } diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h index 6ba9284148c..f551f4e863a 100644 --- a/src/buffer/out/TextColor.h +++ b/src/buffer/out/TextColor.h @@ -91,13 +91,13 @@ struct TextColor 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 colorTable, const COLORREF defaultColor, - const bool brighten) const; + const bool brighten) const noexcept; constexpr BYTE GetIndex() const noexcept { @@ -113,7 +113,7 @@ struct TextColor BYTE _green; BYTE _blue; - COLORREF _GetRGB() const; + COLORREF _GetRGB() const noexcept; #ifdef UNIT_TESTING friend class TextBufferTests; diff --git a/src/buffer/out/UnicodeStorage.cpp b/src/buffer/out/UnicodeStorage.cpp index db5dd318255..41f85adcff6 100644 --- a/src/buffer/out/UnicodeStorage.cpp +++ b/src/buffer/out/UnicodeStorage.cpp @@ -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); } diff --git a/src/buffer/out/UnicodeStorage.hpp b/src/buffer/out/UnicodeStorage.hpp index 1b386da4792..0f2a629bd40 100644 --- a/src/buffer/out/UnicodeStorage.hpp +++ b/src/buffer/out/UnicodeStorage.hpp @@ -47,13 +47,13 @@ class UnicodeStorage final using key_type = typename COORD; using mapped_type = typename std::vector; - 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& rowMap, const std::optional width); diff --git a/src/buffer/out/cursor.cpp b/src/buffer/out/cursor.cpp index 6cb69597897..0b2f461be4d 100644 --- a/src/buffer/out/cursor.cpp +++ b/src/buffer/out/cursor.cpp @@ -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(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(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(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(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(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(DeltaY); _RedrawCursor(); ResetDelayEOLWrap(); } @@ -262,7 +262,7 @@ void Cursor::DecrementYPosition(const int DeltaY) // - OtherCursor - The cursor to copy properties from // Return Value: // - -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(color); } -void Cursor::SetType(const CursorType type) +void Cursor::SetType(const CursorType type) noexcept { _cursorType = type; } diff --git a/src/buffer/out/cursor.h b/src/buffer/out/cursor.h index 496e96f1ff2..140dcc9492a 100644 --- a/src/buffer/out/cursor.h +++ b/src/buffer/out/cursor.h @@ -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 @@ class Cursor final ULONG GetSize() const noexcept; COORD GetPosition() const noexcept; - const CursorType GetType() const; - const bool IsUsingColor() const; - const COLORREF GetColor() const; - - void StartDeferDrawing(); - void EndDeferDrawing(); - - 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); + const CursorType GetType() const noexcept; + const bool IsUsingColor() const noexcept; + const COLORREF GetColor() const noexcept; + + void StartDeferDrawing() noexcept; + void EndDeferDrawing() noexcept; + + 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; diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 831c672a586..a64406f074b 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -49,7 +49,7 @@ TextBuffer::TextBuffer(const COORD screenBufferSize, // - OtherBuffer - The text buffer to copy properties from // Return Value: // - -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) // - // Return Value: // - Total number of rows in the buffer -UINT TextBuffer::TotalRowCount() const +UINT TextBuffer::TotalRowCount() const noexcept { - return static_cast(_storage.size()); + return gsl::narrow(_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(static_cast(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(pCurrRow->GetCharRow().MeasureRight()) - 1; + coordEndOfText.X = gsl::narrow(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(pCurrRow->GetCharRow().MeasureRight()) - 1; + coordEndOfText.X = gsl::narrow(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(_storage.at(0).size()), gsl::narrow(_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) // - // 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 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(highlight.Width()) + 2); // + 2 for \r\n if we munged it + selectionFgAttr.reserve(gsl::narrow(highlight.Width()) + 2); + selectionBkAttr.reserve(gsl::narrow(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 fgColor = std::nullopt; std::optional 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 << "
"; } - 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 '
' 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; } }; diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index 97b3375606d..beb477fbbd6 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -72,7 +72,7 @@ class TextBuffer final ~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 @@ class TextBuffer final 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 @@ class TextBuffer final 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 @@ class TextBuffer final Microsoft::Console::Render::IRenderTarget& _renderTarget; - void _SetFirstRowIndex(const SHORT FirstRowIndex); + void _SetFirstRowIndex(const SHORT FirstRowIndex) noexcept; COORD _GetPreviousFromCursor() const; diff --git a/src/buffer/out/textBufferCellIterator.cpp b/src/buffer/out/textBufferCellIterator.cpp index 50948ab6bbd..285a4ec2047 100644 --- a/src/buffer/out/textBufferCellIterator.cpp +++ b/src/buffer/out/textBufferCellIterator.cpp @@ -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(newPos.X) - gsl::narrow_cast(_pos.X); _attrIter += diff; } diff --git a/src/buffer/out/textBufferCellIterator.hpp b/src/buffer/out/textBufferCellIterator.hpp index 730154f28ab..d647bd70152 100644 --- a/src/buffer/out/textBufferCellIterator.hpp +++ b/src/buffer/out/textBufferCellIterator.hpp @@ -28,12 +28,10 @@ class TextBufferCellIterator 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); diff --git a/src/buffer/out/textBufferTextIterator.cpp b/src/buffer/out/textBufferTextIterator.cpp index 05c6a4c997d..9687e317584 100644 --- a/src/buffer/out/textBufferTextIterator.cpp +++ b/src/buffer/out/textBufferTextIterator.cpp @@ -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(); } diff --git a/src/buffer/out/textBufferTextIterator.hpp b/src/buffer/out/textBufferTextIterator.hpp index 845e86e19c8..634745eec63 100644 --- a/src/buffer/out/textBufferTextIterator.hpp +++ b/src/buffer/out/textBufferTextIterator.hpp @@ -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 diff --git a/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest b/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest index ef9516047af..a447bc8fdc2 100644 --- a/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest +++ b/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest @@ -9,6 +9,7 @@ + diff --git a/src/inc/DefaultSettings.h b/src/inc/DefaultSettings.h index 678f4115b31..ed6d8f2a2f7 100644 --- a/src/inc/DefaultSettings.h +++ b/src/inc/DefaultSettings.h @@ -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) diff --git a/src/renderer/base/lib/base.vcxproj b/src/renderer/base/lib/base.vcxproj index 7ba34072f2a..03f238e9ad6 100644 --- a/src/renderer/base/lib/base.vcxproj +++ b/src/renderer/base/lib/base.vcxproj @@ -22,6 +22,7 @@ + diff --git a/src/renderer/base/lib/base.vcxproj.filters b/src/renderer/base/lib/base.vcxproj.filters index 00f0bb1e6dd..300c6dfc5d4 100644 --- a/src/renderer/base/lib/base.vcxproj.filters +++ b/src/renderer/base/lib/base.vcxproj.filters @@ -80,6 +80,9 @@ Header Files\inc + + Header Files\inc + diff --git a/src/renderer/dx/CustomTextLayout.cpp b/src/renderer/dx/CustomTextLayout.cpp index 94cf4c8e47a..de883e84215 100644 --- a/src/renderer/dx/CustomTextLayout.cpp +++ b/src/renderer/dx/CustomTextLayout.cpp @@ -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 const factory, + gsl::not_null const analyzer, + gsl::not_null const format, + gsl::not_null const font, std::basic_string_view 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(format->GetLocaleNameLength()) + 1); // +1 for null THROW_IF_FAILED(format->GetLocaleName(_localeName.data(), gsl::narrow(_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 runs; runs.resize(totalRuns); @@ -178,7 +179,7 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory, const auto textLength = gsl::narrow(_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(_glyphIndices.size() - glyphStart); + const UINT32 textStart = run.textStart; + const UINT32 textLength = run.textLength; + UINT32 maxGlyphCount = gsl::narrow(_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(glyphStart + actualGlyphCount), _glyphAdvances.size())); - _glyphOffsets.resize(std::max(static_cast(glyphStart + actualGlyphCount), _glyphOffsets.size())); + _glyphAdvances.resize(std::max(gsl::narrow_cast(glyphStart) + gsl::narrow_cast(actualGlyphCount), _glyphAdvances.size())); + _glyphOffsets.resize(std::max(gsl::narrow_cast(glyphStart) + gsl::narrow_cast(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(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(_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, // - // 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(_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(_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(format1->GetFontFamilyNameLength()) + 1); RETURN_IF_FAILED(format1->GetFontFamilyName(familyName.data(), gsl::narrow(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, // - - 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( + _runIndex = gsl::narrow( std::find(_runs.begin(), _runs.end(), textPosition) - _runs.begin()); } @@ -957,13 +972,13 @@ void CustomTextLayout::_SetCurrentRun(const UINT32 textPosition) // - - 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(totalRuns); - _runIndex = static_cast(totalRuns); + frontHalf.nextRunIndex = gsl::narrow(totalRuns); + _runIndex = gsl::narrow(totalRuns); } #pragma endregion diff --git a/src/renderer/dx/CustomTextLayout.h b/src/renderer/dx/CustomTextLayout.h index 6e57dc5c986..598431b8b74 100644 --- a/src/renderer/dx/CustomTextLayout.h +++ b/src/renderer/dx/CustomTextLayout.h @@ -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 const factory, + gsl::not_null const analyzer, + gsl::not_null const format, + gsl::not_null 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 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 _factory; diff --git a/src/renderer/dx/CustomTextRenderer.cpp b/src/renderer/dx/CustomTextRenderer.cpp index b99c263a635..c0e545faf20 100644 --- a/src/renderer/dx/CustomTextRenderer.cpp +++ b/src/renderer/dx/CustomTextRenderer.cpp @@ -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(clientDrawingContext); + RETURN_HR_IF_NULL(E_INVALIDARG, pixelsPerDip); + + const DrawingContext* drawingContext = static_cast(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(clientDrawingContext); + RETURN_HR_IF_NULL(E_INVALIDARG, transform); + + const DrawingContext* drawingContext = static_cast(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(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(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 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 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 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 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 d2dFactory; clientDrawingContext->renderTarget->GetFactory(d2dFactory.GetAddressOf()); diff --git a/src/renderer/dx/CustomTextRenderer.h b/src/renderer/dx/CustomTextRenderer.h index f64623c11e8..c3e2fc5219b 100644 --- a/src/renderer/dx/CustomTextRenderer.h +++ b/src/renderer/dx/CustomTextRenderer.h @@ -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]] virtual HRESULT STDMETHODCALLTYPE DrawUnderline(void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _In_ const DWRITE_UNDERLINE* underline, - IUnknown* clientDrawingEffect) override; - - [[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _In_ const DWRITE_STRIKETHROUGH* strikethrough, - IUnknown* clientDrawingEffect) override; - - [[nodiscard]] virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(void* clientDrawingContext, - FLOAT originX, - FLOAT originY, - IDWriteInlineObject* inlineObject, - BOOL isSideways, - BOOL isRightToLeft, - 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]] HRESULT STDMETHODCALLTYPE DrawUnderline(void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ const DWRITE_UNDERLINE* underline, + IUnknown* clientDrawingEffect) noexcept override; + + [[nodiscard]] HRESULT STDMETHODCALLTYPE DrawStrikethrough(void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ const DWRITE_STRIKETHROUGH* strikethrough, + IUnknown* clientDrawingEffect) noexcept 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; }; } diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 33f8790470b..e8cb5589de6 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -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 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(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(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; - - RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(), - &SwapChainDesc, - nullptr, - &_dxgiSwapChain)); - break; - } - default: - THROW_HR(E_NOTIMPL); + // 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); + } } + 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(_dpi); - _d2dRenderTarget->SetDpi(fdpi, fdpi); + RETURN_IF_FAILED(_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&_dxgiSurface))); + + 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); + + 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) + { + const auto fdpi = static_cast(_dpi); + _d2dRenderTarget->SetDpi(fdpi, fdpi); - DXGI_MATRIX_3X2_F inverseScale = { 0 }; - inverseScale._11 = 1.0f / _scale; - inverseScale._22 = inverseScale._11; + DXGI_MATRIX_3X2_F inverseScale = { 0 }; + inverseScale._11 = 1.0f / _scale; + inverseScale._22 = inverseScale._11; - ::Microsoft::WRL::ComPtr sc2; - RETURN_IF_FAILED(_dxgiSwapChain.As(&sc2)); + ::Microsoft::WRL::ComPtr sc2; + RETURN_IF_FAILED(_dxgiSwapChain.As(&sc2)); - RETURN_IF_FAILED(sc2->SetMatrixTransform(&inverseScale)); + RETURN_IF_FAILED(sc2->SetMatrixTransform(&inverseScale)); + } + return S_OK; } - - return S_OK; + CATCH_RETURN(); } // Routine Description: @@ -333,31 +345,35 @@ DxEngine::~DxEngine() // - void DxEngine::_ReleaseDeviceResources() noexcept { - _haveDeviceResources = false; - _d2dBrushForeground.Reset(); - _d2dBrushBackground.Reset(); - - if (nullptr != _d2dRenderTarget.Get() && _isPainting) + try { - _d2dRenderTarget->EndDraw(); - } + _haveDeviceResources = false; + _d2dBrushForeground.Reset(); + _d2dBrushBackground.Reset(); - _d2dRenderTarget.Reset(); + if (nullptr != _d2dRenderTarget.Get() && _isPainting) + { + _d2dRenderTarget->EndDraw(); + } - _dxgiSurface.Reset(); - _dxgiSwapChain.Reset(); + _d2dRenderTarget.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(); + _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(); + _d3dDevice.Reset(); - _dxgiFactory2.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(stringLength), + gsl::narrow(stringLength), _dwriteTextFormat.Get(), - (float)_displaySizePixels.cx, - _glyphCell.cy != 0 ? _glyphCell.cy : (float)_displaySizePixels.cy, + gsl::narrow(_displaySizePixels.cx), + _glyphCell.cy != 0 ? _glyphCell.cy : gsl::narrow(_displaySizePixels.cy), ppTextLayout); } @@ -410,7 +426,7 @@ void DxEngine::SetCallback(std::function pfn) _pfn = pfn; } -Microsoft::WRL::ComPtr DxEngine::GetSwapChain() noexcept +Microsoft::WRL::ComPtr DxEngine::GetSwapChain() { if (_dxgiSwapChain.Get() == nullptr) { @@ -428,6 +444,8 @@ Microsoft::WRL::ComPtr 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 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 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 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; + try + { + POINT delta = { 0 }; + delta.x = pcoordDelta->X * _glyphCell.cx; + delta.y = pcoordDelta->Y * _glyphCell.cy; - _InvalidOffset(delta); + _InvalidOffset(delta); - _invalidScroll.cx += delta.x; - _invalidScroll.cy += delta.y; + _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; + // 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); + // X delta first + OffsetRect(&reveal, delta.x, 0); + IntersectRect(&reveal, &reveal, &display); + SubtractRect(&reveal, &display, &reveal); - if (!IsRectEmpty(&reveal)) - { - _InvalidOr(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); + // 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); + if (!IsRectEmpty(&reveal)) + { + _InvalidOr(reveal); + } } + CATCH_RETURN(); } return S_OK; @@ -544,6 +570,8 @@ Microsoft::WRL::ComPtr 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 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: // - -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)); - } - 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(); - }); + 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(); + // 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()); + // 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(); + // 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; - } + // And persist the new size. + _displaySizePixels = clientSize; + } - _d2dRenderTarget->BeginDraw(); - _isPainting = true; + _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 backBuffer; - Microsoft::WRL::ComPtr frontBuffer; + try + { + Microsoft::WRL::ComPtr backBuffer; + Microsoft::WRL::ComPtr 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((_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(viewInPixels.Width() / _glyphCell.cx); - short heightInChars = static_cast(viewInPixels.Height() / _glyphCell.cy); + const short widthInChars = gsl::narrow_cast(viewInPixels.Width() / _glyphCell.cx); + const short heightInChars = gsl::narrow_cast(viewInPixels.Height() / _glyphCell.cy); return Viewport::FromDimensions(viewInPixels.Origin(), { widthInChars, heightInChars }); } @@ -1297,13 +1344,13 @@ float DxEngine::GetScaling() const noexcept // - // 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(floor(_invalidRect.top / _glyphCell.cy)); + r.Left = gsl::narrow(floor(_invalidRect.left / _glyphCell.cx)); + r.Bottom = gsl::narrow(floor(_invalidRect.bottom / _glyphCell.cy)); + r.Right = gsl::narrow(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(_glyphCell.cx), gsl::narrow(_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. + + // Create the text layout + CustomTextLayout layout(_dwriteFactory.Get(), + _dwriteTextAnalyzer.Get(), + _dwriteTextFormat.Get(), + _dwriteFontFace.Get(), + { &cluster, 1 }, + _glyphCell.cx); - UINT32 columns = 0; - RETURN_IF_FAILED(layout.GetColumns(&columns)); + UINT32 columns = 0; + RETURN_IF_FAILED(layout.GetColumns(&columns)); - *pResult = columns != 1; + *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 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; -} diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index bc25588d3f1..f0960120316 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -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 pfn); - ::Microsoft::WRL::ComPtr GetSwapChain() noexcept; + ::Microsoft::WRL::ComPtr 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 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 }; + } }; } diff --git a/src/renderer/inc/IRenderEngine.hpp b/src/renderer/inc/IRenderEngine.hpp index 2399ab6a3f2..2d321381318 100644 --- a/src/renderer/inc/IRenderEngine.hpp +++ b/src/renderer/inc/IRenderEngine.hpp @@ -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; diff --git a/src/renderer/inc/IRenderTarget.hpp b/src/renderer/inc/IRenderTarget.hpp index 1d1223b12b1..4fbba7fad41 100644 --- a/src/renderer/inc/IRenderTarget.hpp +++ b/src/renderer/inc/IRenderTarget.hpp @@ -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; diff --git a/src/renderer/inc/RenderEngineBase.hpp b/src/renderer/inc/RenderEngineBase.hpp index dad43c5c51a..eae934bc775 100644 --- a/src/renderer/inc/RenderEngineBase.hpp +++ b/src/renderer/inc/RenderEngineBase.hpp @@ -24,9 +24,16 @@ namespace Microsoft::Console::Render class RenderEngineBase : public IRenderEngine { public: + ~RenderEngineBase() = 0; + + protected: RenderEngineBase(); - virtual ~RenderEngineBase() = 0; + 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; diff --git a/src/types/CodepointWidthDetector.cpp b/src/types/CodepointWidthDetector.cpp index c627a2b1fd8..eb29a8af488 100644 --- a/src/types/CodepointWidthDetector.cpp +++ b/src/types/CodepointWidthDetector.cpp @@ -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); diff --git a/src/types/GlyphWidth.cpp b/src/types/GlyphWidth.cpp index b92935c31b6..f90c79f9481 100644 --- a/src/types/GlyphWidth.cpp +++ b/src/types/GlyphWidth.cpp @@ -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 pfnFallb // - // Return Value: // - -void NotifyGlyphWidthFontChanged() +void NotifyGlyphWidthFontChanged() noexcept { widthDetector.NotifyFontChanged(); } diff --git a/src/types/IBaseData.h b/src/types/IBaseData.h index e82bfa8c170..453dbae7711 100644 --- a/src/types/IBaseData.h +++ b/src/types/IBaseData.h @@ -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; diff --git a/src/types/IInputEvent.cpp b/src/types/IInputEvent.cpp index f7a3a925a2a..5df614a6ca5 100644 --- a/src/types/IInputEvent.cpp +++ b/src/types/IInputEvent.cpp @@ -48,7 +48,7 @@ std::deque> IInputEvent::Create(const std::deque> outEvents; for (size_t i = 0; i < records.size(); ++i) { - std::unique_ptr event = IInputEvent::Create(records[i]); + std::unique_ptr event = IInputEvent::Create(records.at(i)); outEvents.push_back(std::move(event)); } return outEvents; diff --git a/src/types/IUiaData.h b/src/types/IUiaData.h index a087789172d..6fbb2f513ef 100644 --- a/src/types/IUiaData.h +++ b/src/types/IUiaData.h @@ -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; diff --git a/src/types/KeyEvent.cpp b/src/types/KeyEvent.cpp index c62a35c908b..869d302d5a4 100644 --- a/src/types/KeyEvent.cpp +++ b/src/types/KeyEvent.cpp @@ -68,7 +68,7 @@ void KeyEvent::ActivateModifierKey(const ModifierKeyState modifierKey) noexcept WI_SetAllFlags(_activeModifierKeys, bitFlag); } -bool KeyEvent::DoActiveModifierKeysMatch(const std::unordered_set& consoleModifiers) const noexcept +bool KeyEvent::DoActiveModifierKeysMatch(const std::unordered_set& consoleModifiers) const { DWORD consoleBits = 0; for (const ModifierKeyState& mod : consoleModifiers) diff --git a/src/types/ScreenInfoUiaProviderBase.cpp b/src/types/ScreenInfoUiaProviderBase.cpp index aff23dde5cc..27cf40c14e0 100644 --- a/src/types/ScreenInfoUiaProviderBase.cpp +++ b/src/types/ScreenInfoUiaProviderBase.cpp @@ -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 data) { - SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, length); + SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, gsl::narrow(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(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)) - { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(IRawElementProviderSimple)) + if (riid == __uuidof(IUnknown) || + riid == __uuidof(IRawElementProviderSimple) || + riid == __uuidof(IRawElementProviderFragment) || + riid == __uuidof(ITextProvider)) { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(IRawElementProviderFragment)) - { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(ITextProvider)) - { - *ppInterface = static_cast(this); + *ppInterface = this; } else { @@ -120,7 +111,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::QueryInterface(_In_ REFIID riid, return E_NOINTERFACE; } - (static_cast(*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(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 rId{ UiaAppendRuntimeId, -1 }; + + const std::basic_string_view 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(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(range)); + hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, range); if (FAILED(hr)) { SafeArrayDestroy(*ppRetVal); @@ -363,6 +363,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_ std::deque 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(ranges.size()); // make a safe array - *ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast(ranges.size())); + *ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, gsl::narrow(ranges.size())); if (*ppRetVal == nullptr) { return E_OUTOFMEMORY; } // fill the safe array - for (LONG i = 0; i < static_cast(ranges.size()); ++i) + for (LONG i = 0; i < gsl::narrow(ranges.size()); ++i) { - hr = SafeArrayPutElement(*ppRetVal, &i, reinterpret_cast(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(rowCount)); + *ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, gsl::narrow(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(pProvider))->Release(); + pProvider->Release(); if (range == nullptr) { @@ -473,8 +482,8 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben return hr; } - LONG currentIndex = static_cast(i); - hr = SafeArrayPutElement(*ppRetVal, ¤tIndex, reinterpret_cast(range)); + LONG currentIndex = gsl::narrow(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(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(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(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(); } diff --git a/src/types/ScreenInfoUiaProviderBase.h b/src/types/ScreenInfoUiaProviderBase.h index 0b47454eefa..5ffe24b5b01 100644 --- a/src/types/ScreenInfoUiaProviderBase.h +++ b/src/types/ScreenInfoUiaProviderBase.h @@ -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 GetSelectionRanges(_In_ IRawElementProviderSimple* pProvider) = 0; @@ -118,8 +122,8 @@ namespace Microsoft::Console::Types std::map _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; }; diff --git a/src/types/UTF8OutPipeReader.cpp b/src/types/UTF8OutPipeReader.cpp index 5c646bc2166..1e69046c675 100644 --- a/src/types/UTF8OutPipeReader.cpp +++ b/src/types/UTF8OutPipeReader.cpp @@ -6,8 +6,10 @@ #include #include -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(_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::value - _dwPartialsLen, &dwRead, nullptr); + fSuccess = !!ReadFile(_outPipe, &_buffer.at(_dwPartialsLen), gsl::narrow(_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(_buffer), dwRead }; + strView = std::string_view{ &_buffer.at(0), dwRead }; return S_OK; } diff --git a/src/types/UiaTextRangeBase.cpp b/src/types/UiaTextRangeBase.cpp index 47e7d502f32..929a8c8e612 100644 --- a/src/types/UiaTextRangeBase.cpp +++ b/src/types/UiaTextRangeBase.cpp @@ -47,7 +47,7 @@ UiaTextRangeBase::MoveState::MoveState(const ScreenInfoRow startScreenInfoRow, const Column firstColumnInRow, const Column lastColumnInRow, const MovementIncrement increment, - const MovementDirection direction) : + const MovementDirection direction) noexcept : StartScreenInfoRow{ startScreenInfoRow }, StartColumn{ startColumn }, EndScreenInfoRow{ endScreenInfoRow }, @@ -162,7 +162,7 @@ void UiaTextRangeBase::Initialize(_In_ const UiaPoint point) // get row that point resides in const RECT windowRect = _getTerminalRect(); const SMALL_RECT viewport = _pData->GetViewport().ToInclusive(); - ScreenInfoRow row; + ScreenInfoRow row = 0; if (clientPoint.y <= windowRect.top) { row = viewport.Top; @@ -184,7 +184,7 @@ void UiaTextRangeBase::Initialize(_In_ const UiaPoint point) _degenerate = true; } -UiaTextRangeBase::UiaTextRangeBase(const UiaTextRangeBase& a) : +UiaTextRangeBase::UiaTextRangeBase(const UiaTextRangeBase& a) noexcept : _cRefs{ 1 }, _pProvider{ a._pProvider }, _start{ a._start }, @@ -201,17 +201,17 @@ UiaTextRangeBase::UiaTextRangeBase(const UiaTextRangeBase& a) : #endif } -const IdType UiaTextRangeBase::GetId() const +const IdType UiaTextRangeBase::GetId() const noexcept { return _id; } -const Endpoint UiaTextRangeBase::GetStart() const +const Endpoint UiaTextRangeBase::GetStart() const noexcept { return _start; } -const Endpoint UiaTextRangeBase::GetEnd() const +const Endpoint UiaTextRangeBase::GetEnd() const noexcept { return _end; } @@ -222,12 +222,12 @@ const Endpoint UiaTextRangeBase::GetEnd() const // - // Return Value: // - true if range is degenerate, false otherwise. -const bool UiaTextRangeBase::IsDegenerate() const +const bool UiaTextRangeBase::IsDegenerate() const noexcept { return _degenerate; } -void UiaTextRangeBase::SetRangeValues(const Endpoint start, const Endpoint end, const bool isDegenerate) +void UiaTextRangeBase::SetRangeValues(const Endpoint start, const Endpoint end, const bool isDegenerate) noexcept { _start = start; _end = end; @@ -266,13 +266,10 @@ IFACEMETHODIMP UiaTextRangeBase::QueryInterface(_In_ REFIID riid, _COM_Outptr_re // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::QueryInterface, nullptr); - if (riid == __uuidof(IUnknown)) - { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(ITextRangeProvider)) + if (riid == __uuidof(IUnknown) || + riid == __uuidof(ITextRangeProvider)) { - *ppInterface = static_cast(this); + *ppInterface = this; } else { @@ -280,7 +277,7 @@ IFACEMETHODIMP UiaTextRangeBase::QueryInterface(_In_ REFIID riid, _COM_Outptr_re return E_NOINTERFACE; } - (static_cast(*ppInterface))->AddRef(); + AddRef(); return S_OK; } @@ -288,16 +285,16 @@ IFACEMETHODIMP UiaTextRangeBase::QueryInterface(_In_ REFIID riid, _COM_Outptr_re #pragma region ITextRangeProvider -IFACEMETHODIMP UiaTextRangeBase::Compare(_In_opt_ ITextRangeProvider* pRange, _Out_ BOOL* pRetVal) +IFACEMETHODIMP UiaTextRangeBase::Compare(_In_opt_ ITextRangeProvider* pRange, _Out_ BOOL* pRetVal) noexcept { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr); *pRetVal = FALSE; - UiaTextRangeBase* other = static_cast(pRange); + const UiaTextRangeBase* other = static_cast(pRange); if (other) { *pRetVal = !!(_start == other->GetStart() && @@ -317,39 +314,23 @@ IFACEMETHODIMP UiaTextRangeBase::Compare(_In_opt_ ITextRangeProvider* pRange, _O IFACEMETHODIMP UiaTextRangeBase::CompareEndpoints(_In_ TextPatternRangeEndpoint endpoint, _In_ ITextRangeProvider* pTargetRange, _In_ TextPatternRangeEndpoint targetEndpoint, - _Out_ int* pRetVal) + _Out_ int* pRetVal) noexcept { RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr); *pRetVal = 0; // get the text range that we're comparing to - UiaTextRangeBase* range = static_cast(pTargetRange); + const UiaTextRangeBase* range = static_cast(pTargetRange); if (range == nullptr) { return E_INVALIDARG; } // get endpoint value that we're comparing to - Endpoint theirValue; - if (targetEndpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) - { - theirValue = range->GetStart(); - } - else - { - theirValue = range->GetEnd() + 1; - } + const Endpoint theirValue = targetEndpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start ? range->GetStart() : range->GetEnd() + 1; // get the values of our endpoint - Endpoint ourValue; - if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) - { - ourValue = _start; - } - else - { - ourValue = _end + 1; - } + const Endpoint ourValue = endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start ? _start : _end + 1; // compare them *pRetVal = std::clamp(static_cast(ourValue) - static_cast(theirValue), -1, 1); @@ -369,7 +350,7 @@ IFACEMETHODIMP UiaTextRangeBase::CompareEndpoints(_In_ TextPatternRangeEndpoint IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -415,7 +396,7 @@ IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) IFACEMETHODIMP UiaTextRangeBase::FindAttribute(_In_ TEXTATTRIBUTEID /*textAttributeId*/, _In_ VARIANT /*val*/, _In_ BOOL /*searchBackward*/, - _Outptr_result_maybenull_ ITextRangeProvider** /*ppRetVal*/) + _Outptr_result_maybenull_ ITextRangeProvider** /*ppRetVal*/) noexcept { // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::FindAttribute, nullptr); @@ -423,7 +404,7 @@ IFACEMETHODIMP UiaTextRangeBase::FindAttribute(_In_ TEXTATTRIBUTEID /*textAttrib } IFACEMETHODIMP UiaTextRangeBase::GetAttributeValue(_In_ TEXTATTRIBUTEID textAttributeId, - _Out_ VARIANT* pRetVal) + _Out_ VARIANT* pRetVal) noexcept { RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr); @@ -445,7 +426,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetAttributeValue(_In_ TEXTATTRIBUTEID textAttr IFACEMETHODIMP UiaTextRangeBase::GetBoundingRectangles(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -469,7 +450,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetBoundingRectangles(_Outptr_result_maybenull_ const unsigned int totalRowsInRange = _rowCountInRange(_pData); for (unsigned int i = 0; i < totalRowsInRange; ++i) { - ScreenInfoRow screenInfoRow = _textBufferRowToScreenInfoRow(_pData, startRow + i); + const ScreenInfoRow screenInfoRow = _textBufferRowToScreenInfoRow(_pData, startRow + i); if (!_isScreenInfoRowInViewport(_pData, screenInfoRow)) { continue; @@ -479,15 +460,15 @@ IFACEMETHODIMP UiaTextRangeBase::GetBoundingRectangles(_Outptr_result_maybenull_ } // convert to a safearray - *ppRetVal = SafeArrayCreateVector(VT_R8, 0, static_cast(coords.size())); + *ppRetVal = SafeArrayCreateVector(VT_R8, 0, gsl::narrow(coords.size())); if (*ppRetVal == nullptr) { return E_OUTOFMEMORY; } - HRESULT hr; - for (LONG i = 0; i < static_cast(coords.size()); ++i) + HRESULT hr = E_UNEXPECTED; + for (LONG i = 0; i < gsl::narrow(coords.size()); ++i) { - hr = SafeArrayPutElement(*ppRetVal, &i, &coords[i]); + hr = SafeArrayPutElement(*ppRetVal, &i, &coords.at(i)); if (FAILED(hr)) { SafeArrayDestroy(*ppRetVal); @@ -516,7 +497,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetEnclosingElement(_Outptr_result_maybenull_ I IFACEMETHODIMP UiaTextRangeBase::GetText(_In_ int maxLength, _Out_ BSTR* pRetVal) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -552,7 +533,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetText(_In_ int maxLength, _Out_ BSTR* pRetVal OutputDebugString(ss.str().c_str()); #endif - ScreenInfoRow currentScreenInfoRow; + ScreenInfoRow currentScreenInfoRow = 0; for (unsigned int i = 0; i < totalRowsInRange; ++i) { currentScreenInfoRow = startScreenInfoRow + i; @@ -569,7 +550,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetText(_In_ int maxLength, _Out_ BSTR* pRetVal if (currentScreenInfoRow == endScreenInfoRow) { // prevent the end from going past the last non-whitespace char in the row - endIndex = std::min(static_cast(endColumn + 1), rowRight); + endIndex = std::min(gsl::narrow_cast(endColumn) + 1, rowRight); } // if startIndex >= endIndex then _start is @@ -619,7 +600,7 @@ IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit, _Out_ int* pRetVal) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -657,12 +638,12 @@ IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit, moveFunc = &_moveByLine; } - MovementDirection moveDirection = (count > 0) ? MovementDirection::Forward : MovementDirection::Backward; + const MovementDirection moveDirection = (count > 0) ? MovementDirection::Forward : MovementDirection::Backward; std::pair newEndpoints; try { - MoveState moveState{ _pData, *this, moveDirection }; + const MoveState moveState{ _pData, *this, moveDirection }; newEndpoints = moveFunc(_pData, count, moveState, @@ -691,7 +672,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin _Out_ int* pRetVal) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -721,7 +702,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin _outputRowConversions(); #endif - MovementDirection moveDirection = (count > 0) ? MovementDirection::Forward : MovementDirection::Backward; + const MovementDirection moveDirection = (count > 0) ? MovementDirection::Forward : MovementDirection::Backward; auto moveFunc = &_moveEndpointByUnitDocument; if (unit == TextUnit::TextUnit_Character) @@ -736,7 +717,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin std::tuple moveResults; try { - MoveState moveState{ _pData, *this, moveDirection }; + const MoveState moveState{ _pData, *this, moveDirection }; moveResults = moveFunc(_pData, count, endpoint, moveState, pRetVal); } CATCH_RETURN(); @@ -758,11 +739,11 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByRange(_In_ TextPatternRangeEndpoi _In_ TextPatternRangeEndpoint targetEndpoint) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); - UiaTextRangeBase* range = static_cast(pTargetRange); + const UiaTextRangeBase* range = static_cast(pTargetRange); if (range == nullptr) { return E_INVALIDARG; @@ -789,7 +770,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByRange(_In_ TextPatternRangeEndpoi #endif // get the value that we're updating to - Endpoint targetEndpointValue; + Endpoint targetEndpointValue = 0; if (targetEndpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) { targetEndpointValue = range->GetStart(); @@ -816,47 +797,41 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByRange(_In_ TextPatternRangeEndpoi } } - // convert then endpoints to screen info rows/columns - ScreenInfoRow startScreenInfoRow; - Column startColumn; - ScreenInfoRow endScreenInfoRow; - Column endColumn; - ScreenInfoRow targetScreenInfoRow; - Column targetColumn; try { - startScreenInfoRow = _endpointToScreenInfoRow(_pData, _start); - startColumn = _endpointToColumn(_pData, _start); - endScreenInfoRow = _endpointToScreenInfoRow(_pData, _end); - endColumn = _endpointToColumn(_pData, _end); - targetScreenInfoRow = _endpointToScreenInfoRow(_pData, targetEndpointValue); - targetColumn = _endpointToColumn(_pData, targetEndpointValue); - } - CATCH_RETURN(); + // convert then endpoints to screen info rows/columns + const auto startScreenInfoRow = _endpointToScreenInfoRow(_pData, _start); + const auto startColumn = _endpointToColumn(_pData, _start); + const auto endScreenInfoRow = _endpointToScreenInfoRow(_pData, _end); + const auto endColumn = _endpointToColumn(_pData, _end); + const auto targetScreenInfoRow = _endpointToScreenInfoRow(_pData, targetEndpointValue); + const auto targetColumn = _endpointToColumn(_pData, targetEndpointValue); - // set endpoint value and check for crossed endpoints - bool crossedEndpoints = false; - if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) - { - _start = targetEndpointValue; - if (_compareScreenCoords(_pData, endScreenInfoRow, endColumn, targetScreenInfoRow, targetColumn) == -1) + // set endpoint value and check for crossed endpoints + bool crossedEndpoints = false; + if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) { - // endpoints were crossed - _end = _start; - crossedEndpoints = true; + _start = targetEndpointValue; + if (_compareScreenCoords(_pData, endScreenInfoRow, endColumn, targetScreenInfoRow, targetColumn) == -1) + { + // endpoints were crossed + _end = _start; + crossedEndpoints = true; + } } - } - else - { - _end = targetEndpointValue; - if (_compareScreenCoords(_pData, startScreenInfoRow, startColumn, targetScreenInfoRow, targetColumn) == 1) + else { - // endpoints were crossed - _start = _end; - crossedEndpoints = true; + _end = targetEndpointValue; + if (_compareScreenCoords(_pData, startScreenInfoRow, startColumn, targetScreenInfoRow, targetColumn) == 1) + { + // endpoints were crossed + _start = _end; + crossedEndpoints = true; + } } + _degenerate = crossedEndpoints; } - _degenerate = crossedEndpoints; + CATCH_RETURN(); // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::MoveEndpointByRange, &apiMsg); @@ -866,7 +841,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByRange(_In_ TextPatternRangeEndpoi IFACEMETHODIMP UiaTextRangeBase::Select() { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); @@ -877,14 +852,10 @@ IFACEMETHODIMP UiaTextRangeBase::Select() } else { - COORD coordStart; - COORD coordEnd; - - coordStart.X = static_cast(_endpointToColumn(_pData, _start)); - coordStart.Y = static_cast(_endpointToScreenInfoRow(_pData, _start)); - - coordEnd.X = static_cast(_endpointToColumn(_pData, _end)); - coordEnd.Y = static_cast(_endpointToScreenInfoRow(_pData, _end)); + const COORD coordStart{ gsl::narrow(_endpointToColumn(_pData, _start)), + gsl::narrow(_endpointToScreenInfoRow(_pData, _start)) }; + const COORD coordEnd{ gsl::narrow(_endpointToColumn(_pData, _end)), + gsl::narrow(_endpointToScreenInfoRow(_pData, _end)) }; _pData->SelectNewRegion(coordStart, coordEnd); } @@ -895,7 +866,7 @@ IFACEMETHODIMP UiaTextRangeBase::Select() } // we don't support this -IFACEMETHODIMP UiaTextRangeBase::AddToSelection() +IFACEMETHODIMP UiaTextRangeBase::AddToSelection() noexcept { // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::AddToSelection, nullptr); @@ -903,7 +874,7 @@ IFACEMETHODIMP UiaTextRangeBase::AddToSelection() } // we don't support this -IFACEMETHODIMP UiaTextRangeBase::RemoveFromSelection() +IFACEMETHODIMP UiaTextRangeBase::RemoveFromSelection() noexcept { // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::RemoveFromSelection, nullptr); @@ -913,91 +884,78 @@ IFACEMETHODIMP UiaTextRangeBase::RemoveFromSelection() IFACEMETHODIMP UiaTextRangeBase::ScrollIntoView(_In_ BOOL alignToTop) { _pData->LockConsole(); - auto Unlock = wil::scope_exit([&] { + auto Unlock = wil::scope_exit([&]() noexcept { _pData->UnlockConsole(); }); - SMALL_RECT oldViewport; - unsigned int viewportHeight; - // range rows - ScreenInfoRow startScreenInfoRow; - ScreenInfoRow endScreenInfoRow; - // screen buffer rows - ScreenInfoRow topRow; - ScreenInfoRow bottomRow; try { - oldViewport = _pData->GetViewport().ToInclusive(); - viewportHeight = _getViewportHeight(oldViewport); + const auto oldViewport = _pData->GetViewport().ToInclusive(); + const auto viewportHeight = _getViewportHeight(oldViewport); // range rows - startScreenInfoRow = _endpointToScreenInfoRow(_pData, _start); - endScreenInfoRow = _endpointToScreenInfoRow(_pData, _end); + const auto startScreenInfoRow = _endpointToScreenInfoRow(_pData, _start); + const auto endScreenInfoRow = _endpointToScreenInfoRow(_pData, _end); // screen buffer rows - topRow = _getFirstScreenInfoRowIndex(); - bottomRow = _getLastScreenInfoRowIndex(_pData); - } - CATCH_RETURN(); + const auto topRow = _getFirstScreenInfoRowIndex(); + const auto bottomRow = _getLastScreenInfoRowIndex(_pData); - SMALL_RECT newViewport = oldViewport; + SMALL_RECT newViewport = oldViewport; - // there's a bunch of +1/-1s here for setting the viewport. These - // are to account for the inclusivity of the viewport boundaries. - if (alignToTop) - { - // determine if we can align the start row to the top - if (startScreenInfoRow + viewportHeight <= bottomRow) - { - // we can align to the top - newViewport.Top = static_cast(startScreenInfoRow); - newViewport.Bottom = static_cast(startScreenInfoRow + viewportHeight - 1); - } - else - { - // we can align to the top so we'll just move the viewport - // to the bottom of the screen buffer - newViewport.Bottom = static_cast(bottomRow); - newViewport.Top = static_cast(bottomRow - viewportHeight + 1); - } - } - else - { - // we need to align to the bottom - // check if we can align to the bottom - if (endScreenInfoRow >= viewportHeight) + // there's a bunch of +1/-1s here for setting the viewport. These + // are to account for the inclusivity of the viewport boundaries. + if (alignToTop) { - // we can align to bottom - newViewport.Bottom = static_cast(endScreenInfoRow); - newViewport.Top = static_cast(endScreenInfoRow - viewportHeight + 1); + // determine if we can align the start row to the top + if (startScreenInfoRow + viewportHeight <= bottomRow) + { + // we can align to the top + newViewport.Top = gsl::narrow(startScreenInfoRow); + newViewport.Bottom = gsl::narrow(startScreenInfoRow + viewportHeight - 1); + } + else + { + // we can align to the top so we'll just move the viewport + // to the bottom of the screen buffer + newViewport.Bottom = gsl::narrow(bottomRow); + newViewport.Top = gsl::narrow(bottomRow - viewportHeight + 1); + } } else { - // we can't align to bottom so we'll move the viewport to - // the top of the screen buffer - newViewport.Top = static_cast(topRow); - newViewport.Bottom = static_cast(topRow + viewportHeight - 1); + // we need to align to the bottom + // check if we can align to the bottom + if (endScreenInfoRow >= viewportHeight) + { + // we can align to bottom + newViewport.Bottom = gsl::narrow(endScreenInfoRow); + newViewport.Top = gsl::narrow(endScreenInfoRow - viewportHeight + 1); + } + else + { + // we can't align to bottom so we'll move the viewport to + // the top of the screen buffer + newViewport.Top = gsl::narrow(topRow); + newViewport.Bottom = gsl::narrow(topRow + viewportHeight - 1); + } } - } - FAIL_FAST_IF(!(newViewport.Top >= static_cast(topRow))); - FAIL_FAST_IF(!(newViewport.Bottom <= static_cast(bottomRow))); - FAIL_FAST_IF(!(_getViewportHeight(oldViewport) == _getViewportHeight(newViewport))); + FAIL_FAST_IF(!(newViewport.Top >= gsl::narrow(topRow))); + FAIL_FAST_IF(!(newViewport.Bottom <= gsl::narrow(bottomRow))); + FAIL_FAST_IF(!(_getViewportHeight(oldViewport) == _getViewportHeight(newViewport))); - try - { _ChangeViewport(newViewport); + + // TODO GitHub #1914: Re-attach Tracing to UIA Tree + // tracing + /*ApiMsgScrollIntoView apiMsg; + apiMsg.AlignToTop = !!alignToTop; + Tracing::s_TraceUia(this, ApiCall::ScrollIntoView, &apiMsg);*/ } CATCH_RETURN(); - - // TODO GitHub #1914: Re-attach Tracing to UIA Tree - // tracing - /*ApiMsgScrollIntoView apiMsg; - apiMsg.AlignToTop = !!alignToTop; - Tracing::s_TraceUia(this, ApiCall::ScrollIntoView, &apiMsg);*/ - return S_OK; } -IFACEMETHODIMP UiaTextRangeBase::GetChildren(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) +IFACEMETHODIMP UiaTextRangeBase::GetChildren(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) noexcept { // TODO GitHub #1914: Re-attach Tracing to UIA Tree //Tracing::s_TraceUia(this, ApiCall::GetChildren, nullptr); @@ -1015,7 +973,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetChildren(_Outptr_result_maybenull_ SAFEARRAY #pragma endregion -const COORD UiaTextRangeBase::_getScreenBufferCoords(IUiaData* pData) +const COORD UiaTextRangeBase::_getScreenBufferCoords(gsl::not_null pData) { return pData->GetTextBuffer().GetSize().Dimensions(); } @@ -1037,7 +995,7 @@ const COORD UiaTextRangeBase::_getScreenFontSize() const // - // Return Value: // - The number of rows -const unsigned int UiaTextRangeBase::_getTotalRows(IUiaData* pData) +const unsigned int UiaTextRangeBase::_getTotalRows(gsl::not_null pData) noexcept { return pData->GetTextBuffer().TotalRowCount(); } @@ -1048,7 +1006,7 @@ const unsigned int UiaTextRangeBase::_getTotalRows(IUiaData* pData) // - // Return Value: // - The row width -const unsigned int UiaTextRangeBase::_getRowWidth(IUiaData* pData) +const unsigned int UiaTextRangeBase::_getRowWidth(gsl::not_null pData) { // make sure that we can't leak a 0 return std::max(static_cast(_getScreenBufferCoords(pData).X), 1u); @@ -1060,7 +1018,7 @@ const unsigned int UiaTextRangeBase::_getRowWidth(IUiaData* pData) // - endpoint - the endpoint to translate // Return Value: // - the column value -const Column UiaTextRangeBase::_endpointToColumn(IUiaData* pData, const Endpoint endpoint) +const Column UiaTextRangeBase::_endpointToColumn(gsl::not_null pData, const Endpoint endpoint) { return endpoint % _getRowWidth(pData); } @@ -1071,7 +1029,7 @@ const Column UiaTextRangeBase::_endpointToColumn(IUiaData* pData, const Endpoint // - endpoint - the endpoint to convert // Return Value: // - the text buffer row value -const TextBufferRow UiaTextRangeBase::_endpointToTextBufferRow(IUiaData* pData, +const TextBufferRow UiaTextRangeBase::_endpointToTextBufferRow(gsl::not_null pData, const Endpoint endpoint) { return endpoint / _getRowWidth(pData); @@ -1084,7 +1042,7 @@ const TextBufferRow UiaTextRangeBase::_endpointToTextBufferRow(IUiaData* pData, // - // Return Value: // - The number of rows in the range. -const unsigned int UiaTextRangeBase::_rowCountInRange(IUiaData* pData) const +const unsigned int UiaTextRangeBase::_rowCountInRange(gsl::not_null pData) const { if (_degenerate) { @@ -1108,8 +1066,8 @@ const unsigned int UiaTextRangeBase::_rowCountInRange(IUiaData* pData) const // - row - the TextBufferRow to convert // Return Value: // - the equivalent ScreenInfoRow. -const ScreenInfoRow UiaTextRangeBase::_textBufferRowToScreenInfoRow(IUiaData* pData, - const TextBufferRow row) +const ScreenInfoRow UiaTextRangeBase::_textBufferRowToScreenInfoRow(gsl::not_null pData, + const TextBufferRow row) noexcept { const int firstRowIndex = pData->GetTextBuffer().GetFirstRowIndex(); return _normalizeRow(pData, row - firstRowIndex); @@ -1122,25 +1080,12 @@ const ScreenInfoRow UiaTextRangeBase::_textBufferRowToScreenInfoRow(IUiaData* pD // - row - the ScreenInfoRow to convert // Return Value: // - the equivalent ViewportRow. -const ViewportRow UiaTextRangeBase::_screenInfoRowToViewportRow(IUiaData* pData, const ScreenInfoRow row) +const ViewportRow UiaTextRangeBase::_screenInfoRowToViewportRow(gsl::not_null pData, const ScreenInfoRow row) noexcept { const SMALL_RECT viewport = pData->GetViewport().ToInclusive(); return _screenInfoRowToViewportRow(row, viewport); } -// 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. -const ViewportRow UiaTextRangeBase::_screenInfoRowToViewportRow(const ScreenInfoRow row, - const SMALL_RECT viewport) -{ - return row - viewport.Top; -} - // Routine Description: // - normalizes the row index to within the bounds of the output // buffer. The output buffer stores the text in a circular buffer so @@ -1149,7 +1094,7 @@ const ViewportRow UiaTextRangeBase::_screenInfoRowToViewportRow(const ScreenInfo // - the non-normalized row index // Return Value: // - the normalized row index -const Row UiaTextRangeBase::_normalizeRow(IUiaData* pData, const Row row) +const Row UiaTextRangeBase::_normalizeRow(gsl::not_null pData, const Row row) noexcept { const unsigned int totalRows = _getTotalRows(pData); return ((row + totalRows) % totalRows); @@ -1161,7 +1106,7 @@ const Row UiaTextRangeBase::_normalizeRow(IUiaData* pData, const Row row) // - viewport - The viewport to measure // Return Value: // - The viewport height -const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewport) +const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewport) noexcept { FAIL_FAST_IF(!(viewport.Bottom >= viewport.Top)); // + 1 because COORD is inclusive on both sides so subtracting top @@ -1175,7 +1120,7 @@ const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewpor // - viewport - The viewport to measure // Return Value: // - The viewport width -const unsigned int UiaTextRangeBase::_getViewportWidth(const SMALL_RECT viewport) +const unsigned int UiaTextRangeBase::_getViewportWidth(const SMALL_RECT viewport) noexcept { FAIL_FAST_IF(!(viewport.Right >= viewport.Left)); @@ -1191,8 +1136,8 @@ const unsigned int UiaTextRangeBase::_getViewportWidth(const SMALL_RECT viewport // - row - the screen info row to check // Return Value: // - true if the row is within the bounds of the viewport -const bool UiaTextRangeBase::_isScreenInfoRowInViewport(IUiaData* pData, - const ScreenInfoRow row) +const bool UiaTextRangeBase::_isScreenInfoRowInViewport(gsl::not_null pData, + const ScreenInfoRow row) noexcept { return _isScreenInfoRowInViewport(row, pData->GetViewport().ToInclusive()); } @@ -1205,11 +1150,11 @@ const bool UiaTextRangeBase::_isScreenInfoRowInViewport(IUiaData* pData, // Return Value: // - true if the row is within the bounds of the viewport const bool UiaTextRangeBase::_isScreenInfoRowInViewport(const ScreenInfoRow row, - const SMALL_RECT viewport) + const SMALL_RECT viewport) noexcept { - ViewportRow viewportRow = _screenInfoRowToViewportRow(row, viewport); + const ViewportRow viewportRow = _screenInfoRowToViewportRow(row, viewport); return viewportRow >= 0 && - viewportRow < static_cast(_getViewportHeight(viewport)); + viewportRow < gsl::narrow(_getViewportHeight(viewport)); } // Routine Description: @@ -1218,8 +1163,8 @@ const bool UiaTextRangeBase::_isScreenInfoRowInViewport(const ScreenInfoRow row, // - row - the ScreenInfoRow to convert // Return Value: // - the equivalent TextBufferRow. -const TextBufferRow UiaTextRangeBase::_screenInfoRowToTextBufferRow(IUiaData* pData, - const ScreenInfoRow row) +const TextBufferRow UiaTextRangeBase::_screenInfoRowToTextBufferRow(gsl::not_null pData, + const ScreenInfoRow row) noexcept { const TextBufferRow firstRowIndex = pData->GetTextBuffer().GetFirstRowIndex(); return _normalizeRow(pData, row + firstRowIndex); @@ -1231,7 +1176,7 @@ const TextBufferRow UiaTextRangeBase::_screenInfoRowToTextBufferRow(IUiaData* pD // - row - the TextBufferRow to convert // Return Value: // - the equivalent Endpoint, starting at the beginning of the TextBufferRow. -const Endpoint UiaTextRangeBase::_textBufferRowToEndpoint(IUiaData* pData, const TextBufferRow row) +const Endpoint UiaTextRangeBase::_textBufferRowToEndpoint(gsl::not_null pData, const TextBufferRow row) { return _getRowWidth(pData) * row; } @@ -1242,7 +1187,7 @@ const Endpoint UiaTextRangeBase::_textBufferRowToEndpoint(IUiaData* pData, const // - row - the ScreenInfoRow to convert // Return Value: // - the equivalent Endpoint. -const Endpoint UiaTextRangeBase::_screenInfoRowToEndpoint(IUiaData* pData, +const Endpoint UiaTextRangeBase::_screenInfoRowToEndpoint(gsl::not_null pData, const ScreenInfoRow row) { return _textBufferRowToEndpoint(pData, _screenInfoRowToTextBufferRow(pData, row)); @@ -1254,7 +1199,7 @@ const Endpoint UiaTextRangeBase::_screenInfoRowToEndpoint(IUiaData* pData, // - endpoint - the endpoint to convert // Return Value: // - the equivalent ScreenInfoRow. -const ScreenInfoRow UiaTextRangeBase::_endpointToScreenInfoRow(IUiaData* pData, +const ScreenInfoRow UiaTextRangeBase::_endpointToScreenInfoRow(gsl::not_null pData, const Endpoint endpoint) { return _textBufferRowToScreenInfoRow(pData, _endpointToTextBufferRow(pData, endpoint)); @@ -1269,14 +1214,14 @@ const ScreenInfoRow UiaTextRangeBase::_endpointToScreenInfoRow(IUiaData* pData, // - // Notes: // - alters coords. may throw an exception. -void UiaTextRangeBase::_addScreenInfoRowBoundaries(IUiaData* pData, +void UiaTextRangeBase::_addScreenInfoRowBoundaries(gsl::not_null pData, const ScreenInfoRow screenInfoRow, _Inout_ std::vector& coords) const { const COORD currentFontSize = _getScreenFontSize(); - POINT topLeft; - POINT bottomRight; + POINT topLeft{ 0 }; + POINT bottomRight{ 0 }; if (_endpointToScreenInfoRow(pData, _start) == screenInfoRow) { @@ -1326,7 +1271,7 @@ void UiaTextRangeBase::_addScreenInfoRowBoundaries(IUiaData* pData, // - // Return Value: // - the index of the first row (0-indexed) of the screen info -const unsigned int UiaTextRangeBase::_getFirstScreenInfoRowIndex() +const unsigned int UiaTextRangeBase::_getFirstScreenInfoRowIndex() noexcept { return 0; } @@ -1337,7 +1282,7 @@ const unsigned int UiaTextRangeBase::_getFirstScreenInfoRowIndex() // - // Return Value: // - the index of the last row (0-indexed) of the screen info -const unsigned int UiaTextRangeBase::_getLastScreenInfoRowIndex(IUiaData* pData) +const unsigned int UiaTextRangeBase::_getLastScreenInfoRowIndex(gsl::not_null pData) noexcept { return _getTotalRows(pData) - 1; } @@ -1348,7 +1293,7 @@ const unsigned int UiaTextRangeBase::_getLastScreenInfoRowIndex(IUiaData* pData) // - // Return Value: // - the index of the first column (0-indexed) of the screen info rows -const Column UiaTextRangeBase::_getFirstColumnIndex() +const Column UiaTextRangeBase::_getFirstColumnIndex() noexcept { return 0; } @@ -1359,7 +1304,7 @@ const Column UiaTextRangeBase::_getFirstColumnIndex() // - // Return Value: // - the index of the last column (0-indexed) of the screen info rows -const Column UiaTextRangeBase::_getLastColumnIndex(IUiaData* pData) +const Column UiaTextRangeBase::_getLastColumnIndex(gsl::not_null pData) { return _getRowWidth(pData) - 1; } @@ -1375,7 +1320,7 @@ const Column UiaTextRangeBase::_getLastColumnIndex(IUiaData* pData) // -1 if A < B // 1 if A > B // 0 if A == B -const int UiaTextRangeBase::_compareScreenCoords(IUiaData* pData, +const int UiaTextRangeBase::_compareScreenCoords(gsl::not_null pData, const ScreenInfoRow rowA, const Column colA, const ScreenInfoRow rowB, @@ -1424,10 +1369,10 @@ const int UiaTextRangeBase::_compareScreenCoords(IUiaData* pData, // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - a pair of endpoints of the form -std::pair UiaTextRangeBase::_moveByCharacter(IUiaData* pData, +std::pair UiaTextRangeBase::_moveByCharacter(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { if (moveState.Direction == MovementDirection::Forward) { @@ -1439,13 +1384,13 @@ std::pair UiaTextRangeBase::_moveByCharacter(IUiaData* pData } } -std::pair UiaTextRangeBase::_moveByCharacterForward(IUiaData* pData, +std::pair UiaTextRangeBase::_moveByCharacterForward(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { *pAmountMoved = 0; - int count = moveCount; + const int count = moveCount; ScreenInfoRow currentScreenInfoRow = moveState.StartScreenInfoRow; Column currentColumn = moveState.StartColumn; @@ -1457,11 +1402,11 @@ std::pair UiaTextRangeBase::_moveByCharacterForward(IUiaData // check if we're at the edge of the screen info buffer if (currentScreenInfoRow == moveState.LimitingRow && - currentColumn + 1 >= right) + gsl::narrow_cast(currentColumn) + 1 >= right) { break; } - else if (currentColumn + 1 >= right) + else if (gsl::narrow_cast(currentColumn) + 1 >= right) { // we're at the edge of a row and need to go to the next one currentColumn = moveState.FirstColumnInRow; @@ -1485,14 +1430,13 @@ std::pair UiaTextRangeBase::_moveByCharacterForward(IUiaData return std::make_pair(std::move(start), std::move(end)); } -std::pair UiaTextRangeBase::_moveByCharacterBackward(IUiaData* pData, +std::pair UiaTextRangeBase::_moveByCharacterBackward(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; - int count = moveCount; + const int count = moveCount; ScreenInfoRow currentScreenInfoRow = moveState.StartScreenInfoRow; Column currentColumn = moveState.StartColumn; @@ -1513,7 +1457,7 @@ std::pair UiaTextRangeBase::_moveByCharacterBackward(IUiaDat // get the right cell for the next row const ROW& row = pData->GetTextBuffer().GetRowByOffset(currentScreenInfoRow); const size_t right = row.GetCharRow().MeasureRight(); - currentColumn = static_cast((right == 0) ? 0 : right - 1); + currentColumn = gsl::narrow((right == 0) ? 0 : right - 1); } else { @@ -1543,12 +1487,11 @@ std::pair UiaTextRangeBase::_moveByCharacterBackward(IUiaDat // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - a pair of endpoints of the form -std::pair UiaTextRangeBase::_moveByLine(IUiaData* pData, +std::pair UiaTextRangeBase::_moveByLine(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; Endpoint start = _screenInfoRowToEndpoint(pData, moveState.StartScreenInfoRow) + moveState.StartColumn; Endpoint end = _screenInfoRowToEndpoint(pData, moveState.EndScreenInfoRow) + moveState.EndColumn; @@ -1591,14 +1534,13 @@ std::pair UiaTextRangeBase::_moveByLine(IUiaData* pData, // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - a pair of endpoints of the form -std::pair UiaTextRangeBase::_moveByDocument(IUiaData* pData, +std::pair UiaTextRangeBase::_moveByDocument(gsl::not_null pData, const int /*moveCount*/, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { // We can't move by anything larger than a line, so move by document will apply and will // just report that it can't do that. - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; // We then have to return the same endpoints as what we initially had so nothing happens. @@ -1619,13 +1561,12 @@ std::pair UiaTextRangeBase::_moveByDocument(IUiaData* pData, // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - A tuple of elements of the form -std::tuple UiaTextRangeBase::_moveEndpointByUnitCharacter(IUiaData* pData, +std::tuple UiaTextRangeBase::_moveEndpointByUnitCharacter(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); if (moveState.Direction == MovementDirection::Forward) { return _moveEndpointByUnitCharacterForward(pData, moveCount, endpoint, moveState, pAmountMoved); @@ -1637,17 +1578,16 @@ std::tuple UiaTextRangeBase::_moveEndpointByUnitCharac } std::tuple -UiaTextRangeBase::_moveEndpointByUnitCharacterForward(IUiaData* pData, +UiaTextRangeBase::_moveEndpointByUnitCharacterForward(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; - int count = moveCount; - ScreenInfoRow currentScreenInfoRow; - Column currentColumn; + const int count = moveCount; + ScreenInfoRow currentScreenInfoRow = 0; + Column currentColumn = 0; // set current location vars if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) @@ -1669,11 +1609,11 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterForward(IUiaData* pData, // check if we're at the edge of the screen info buffer if (currentScreenInfoRow == moveState.LimitingRow && - currentColumn + 1 >= right) + gsl::narrow_cast(currentColumn) + 1 >= right) { break; } - else if (currentColumn + 1 >= right) + else if (gsl::narrow_cast(currentColumn) + 1 >= right) { // we're at the edge of a row and need to go to the next one currentColumn = moveState.FirstColumnInRow; @@ -1693,7 +1633,7 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterForward(IUiaData* pData, } // translate the row back to an endpoint and handle any crossed endpoints - Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; + const Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; Endpoint start = _screenInfoRowToEndpoint(pData, moveState.StartScreenInfoRow) + moveState.StartColumn; Endpoint end = _screenInfoRowToEndpoint(pData, moveState.EndScreenInfoRow) + moveState.EndColumn; bool degenerate = false; @@ -1727,17 +1667,16 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterForward(IUiaData* pData, } std::tuple -UiaTextRangeBase::_moveEndpointByUnitCharacterBackward(IUiaData* pData, +UiaTextRangeBase::_moveEndpointByUnitCharacterBackward(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; - int count = moveCount; - ScreenInfoRow currentScreenInfoRow; - Column currentColumn; + const int count = moveCount; + ScreenInfoRow currentScreenInfoRow = 0; + Column currentColumn = 0; // set current location vars if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) @@ -1768,7 +1707,7 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterBackward(IUiaData* pData, // get the right cell for the next row const ROW& row = pData->GetTextBuffer().GetRowByOffset(currentScreenInfoRow); const size_t right = row.GetCharRow().MeasureRight(); - currentColumn = static_cast((right == 0) ? 0 : right - 1); + currentColumn = gsl::narrow((right == 0) ? 0 : right - 1); } else { @@ -1784,7 +1723,7 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterBackward(IUiaData* pData, } // translate the row back to an endpoint and handle any crossed endpoints - Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; + const Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; Endpoint start = _screenInfoRowToEndpoint(pData, moveState.StartScreenInfoRow) + moveState.StartColumn; Endpoint end = _screenInfoRowToEndpoint(pData, moveState.EndScreenInfoRow) + moveState.EndColumn; bool degenerate = false; @@ -1828,17 +1767,16 @@ UiaTextRangeBase::_moveEndpointByUnitCharacterBackward(IUiaData* pData, // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - A tuple of elements of the form -std::tuple UiaTextRangeBase::_moveEndpointByUnitLine(IUiaData* pData, +std::tuple UiaTextRangeBase::_moveEndpointByUnitLine(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; int count = moveCount; - ScreenInfoRow currentScreenInfoRow; - Column currentColumn; + ScreenInfoRow currentScreenInfoRow = 0; + Column currentColumn = 0; bool forceDegenerate = false; Endpoint start = _screenInfoRowToEndpoint(pData, moveState.StartScreenInfoRow) + moveState.StartColumn; Endpoint end = _screenInfoRowToEndpoint(pData, moveState.EndScreenInfoRow) + moveState.EndColumn; @@ -1849,7 +1787,7 @@ std::tuple UiaTextRangeBase::_moveEndpointByUnitLine(I return std::make_tuple(start, end, degenerate); } - MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward; + const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward; if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) { @@ -1954,7 +1892,7 @@ std::tuple UiaTextRangeBase::_moveEndpointByUnitLine(I } // translate the row back to an endpoint and handle any crossed endpoints - Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; + const Endpoint convertedEndpoint = _screenInfoRowToEndpoint(pData, currentScreenInfoRow) + currentColumn; if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) { start = convertedEndpoint; @@ -1988,17 +1926,16 @@ std::tuple UiaTextRangeBase::_moveEndpointByUnitLine(I // - pAmountMoved - the number of times that the return values are "moved" // Return Value: // - A tuple of elements of the form -std::tuple UiaTextRangeBase::_moveEndpointByUnitDocument(IUiaData* pData, +std::tuple UiaTextRangeBase::_moveEndpointByUnitDocument(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved) + _Out_ gsl::not_null const pAmountMoved) { - THROW_HR_IF(E_INVALIDARG, pAmountMoved == nullptr); *pAmountMoved = 0; - Endpoint start; - Endpoint end; + Endpoint start = 0; + Endpoint end = 0; bool degenerate = false; if (endpoint == TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start) { @@ -2056,12 +1993,12 @@ std::tuple UiaTextRangeBase::_moveEndpointByUnitDocume return std::make_tuple(start, end, degenerate); } -COORD UiaTextRangeBase::_endpointToCoord(IUiaData* pData, const Endpoint endpoint) +COORD UiaTextRangeBase::_endpointToCoord(gsl::not_null pData, const Endpoint endpoint) { return { gsl::narrow(_endpointToColumn(pData, endpoint)), gsl::narrow(_endpointToScreenInfoRow(pData, endpoint)) }; } -Endpoint UiaTextRangeBase::_coordToEndpoint(IUiaData* pData, +Endpoint UiaTextRangeBase::_coordToEndpoint(gsl::not_null pData, const COORD coord) { return _screenInfoRowToEndpoint(pData, coord.Y) + coord.X; @@ -2069,11 +2006,14 @@ Endpoint UiaTextRangeBase::_coordToEndpoint(IUiaData* pData, RECT UiaTextRangeBase::_getTerminalRect() const { - UiaRect result; + UiaRect result{ 0 }; IRawElementProviderFragment* pRawElementProviderFragment; THROW_IF_FAILED(_pProvider->QueryInterface(&pRawElementProviderFragment)); - pRawElementProviderFragment->get_BoundingRectangle(&result); + if (pRawElementProviderFragment) + { + pRawElementProviderFragment->get_BoundingRectangle(&result); + } return { gsl::narrow(result.left), diff --git a/src/types/UiaTextRangeBase.hpp b/src/types/UiaTextRangeBase.hpp index 1d1f957af3f..3b9e4c01b4b 100644 --- a/src/types/UiaTextRangeBase.hpp +++ b/src/types/UiaTextRangeBase.hpp @@ -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 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 pData) noexcept; + static const unsigned int _getRowWidth(gsl::not_null 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 pData) noexcept; - static const Column _getFirstColumnIndex(); - static const Column _getLastColumnIndex(IUiaData* pData); + static const Column _getFirstColumnIndex() noexcept; + static const Column _getLastColumnIndex(gsl::not_null pData); - const unsigned int _rowCountInRange(IUiaData* pData) const; + const unsigned int _rowCountInRange(gsl::not_null pData) const; - static const TextBufferRow _endpointToTextBufferRow(IUiaData* pData, + static const TextBufferRow _endpointToTextBufferRow(gsl::not_null pData, const Endpoint endpoint); - static const ScreenInfoRow _textBufferRowToScreenInfoRow(IUiaData* pData, - const TextBufferRow row); + static const ScreenInfoRow _textBufferRowToScreenInfoRow(gsl::not_null 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 pData, + const ScreenInfoRow row) noexcept; + static const Endpoint _textBufferRowToEndpoint(gsl::not_null pData, const TextBufferRow row); - static const ScreenInfoRow _endpointToScreenInfoRow(IUiaData* pData, + static const ScreenInfoRow _endpointToScreenInfoRow(gsl::not_null pData, const Endpoint endpoint); - static const Endpoint _screenInfoRowToEndpoint(IUiaData* pData, + static const Endpoint _screenInfoRowToEndpoint(gsl::not_null pData, const ScreenInfoRow row); - static COORD _endpointToCoord(IUiaData* pData, + static COORD _endpointToCoord(gsl::not_null pData, const Endpoint endpoint); - static Endpoint _coordToEndpoint(IUiaData* pData, + static Endpoint _coordToEndpoint(gsl::not_null pData, const COORD coord); - static const Column _endpointToColumn(IUiaData* pData, + static const Column _endpointToColumn(gsl::not_null pData, const Endpoint endpoint); - static const Row _normalizeRow(IUiaData* pData, const Row row); - - static const ViewportRow _screenInfoRowToViewportRow(IUiaData* pData, - const ScreenInfoRow row); - static const ViewportRow _screenInfoRowToViewportRow(const ScreenInfoRow row, - const SMALL_RECT viewport); + static const Row _normalizeRow(gsl::not_null pData, const Row row) noexcept; + + static const ViewportRow _screenInfoRowToViewportRow(gsl::not_null 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 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 pData, const ScreenInfoRow screenInfoRow, _Inout_ std::vector& coords) const; - static const int _compareScreenCoords(IUiaData* pData, + static const int _compareScreenCoords(gsl::not_null pData, const ScreenInfoRow rowA, const Column colA, const ScreenInfoRow rowB, const Column colB); - static std::pair _moveByCharacter(IUiaData* pData, + static std::pair _moveByCharacter(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); - static std::pair _moveByCharacterForward(IUiaData* pData, + static std::pair _moveByCharacterForward(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); - static std::pair _moveByCharacterBackward(IUiaData* pData, + static std::pair _moveByCharacterBackward(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); - static std::pair _moveByLine(IUiaData* pData, + static std::pair _moveByLine(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); - static std::pair _moveByDocument(IUiaData* pData, + static std::pair _moveByDocument(gsl::not_null pData, const int moveCount, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); static std::tuple - _moveEndpointByUnitCharacter(IUiaData* pData, + _moveEndpointByUnitCharacter(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); static std::tuple - _moveEndpointByUnitCharacterForward(IUiaData* pData, + _moveEndpointByUnitCharacterForward(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); static std::tuple - _moveEndpointByUnitCharacterBackward(IUiaData* pData, + _moveEndpointByUnitCharacterBackward(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); static std::tuple - _moveEndpointByUnitLine(IUiaData* pData, + _moveEndpointByUnitLine(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); static std::tuple - _moveEndpointByUnitDocument(IUiaData* pData, + _moveEndpointByUnitDocument(gsl::not_null pData, const int moveCount, const TextPatternRangeEndpoint endpoint, const MoveState moveState, - _Out_ int* const pAmountMoved); + _Out_ gsl::not_null const pAmountMoved); #ifdef UNIT_TESTING friend class ::UiaTextRangeTests; diff --git a/src/types/Utf16Parser.cpp b/src/types/Utf16Parser.cpp index 2090af62312..777388c6406 100644 --- a/src/types/Utf16Parser.cpp +++ b/src/types/Utf16Parser.cpp @@ -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) { diff --git a/src/types/WindowUiaProviderBase.cpp b/src/types/WindowUiaProviderBase.cpp index 8faa65ff1f9..63735e34b6a 100644 --- a/src/types/WindowUiaProviderBase.cpp +++ b/src/types/WindowUiaProviderBase.cpp @@ -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(this); - } - else if (riid == __uuidof(IRawElementProviderSimple)) - { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(IRawElementProviderFragment)) - { - *ppInterface = static_cast(this); - } - else if (riid == __uuidof(IRawElementProviderFragmentRoot)) - { - *ppInterface = static_cast(this); + *ppInterface = this; } else { @@ -58,7 +50,7 @@ IFACEMETHODIMP WindowUiaProviderBase::QueryInterface(_In_ REFIID riid, _COM_Outp return E_NOINTERFACE; } - (static_cast(*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(UIA_E_ELEMENTNOTAVAILABLE); + return gsl::narrow_cast(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 diff --git a/src/types/WindowUiaProviderBase.hpp b/src/types/WindowUiaProviderBase.hpp index d78739a511b..3cd68b1a2fa 100644 --- a/src/types/WindowUiaProviderBase.hpp +++ b/src/types/WindowUiaProviderBase.hpp @@ -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, diff --git a/src/types/convert.cpp b/src/types/convert.cpp index 7ca12962c98..c2049ded918 100644 --- a/src/types/convert.cpp +++ b/src/types/convert.cpp @@ -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 pwsOut = std::make_unique(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 psOut = std::make_unique(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> 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(convertedChars[0]); + unsigned char const uch = static_cast(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) diff --git a/src/types/inc/CodepointWidthDetector.hpp b/src/types/inc/CodepointWidthDetector.hpp index 6967ac942bc..0dc7ac8b966 100644 --- a/src/types/inc/CodepointWidthDetector.hpp +++ b/src/types/inc/CodepointWidthDetector.hpp @@ -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 pfnFallback); diff --git a/src/types/inc/GlyphWidth.hpp b/src/types/inc/GlyphWidth.hpp index e12261a6f83..7888915bebd 100644 --- a/src/types/inc/GlyphWidth.hpp +++ b/src/types/inc/GlyphWidth.hpp @@ -13,6 +13,6 @@ Module Name: #include bool IsGlyphFullWidth(const std::wstring_view glyph); -bool IsGlyphFullWidth(const wchar_t wch); +bool IsGlyphFullWidth(const wchar_t wch) noexcept; void SetGlyphWidthFallback(std::function pfnFallback); -void NotifyGlyphWidthFontChanged(); +void NotifyGlyphWidthFontChanged() noexcept; diff --git a/src/types/inc/IInputEvent.hpp b/src/types/inc/IInputEvent.hpp index ded7c903b7b..486971f82e6 100644 --- a/src/types/inc/IInputEvent.hpp +++ b/src/types/inc/IInputEvent.hpp @@ -245,7 +245,7 @@ class KeyEvent : public IInputEvent void SetActiveModifierKeys(const DWORD activeModifierKeys) noexcept; void DeactivateModifierKey(const ModifierKeyState modifierKey) noexcept; void ActivateModifierKey(const ModifierKeyState modifierKey) noexcept; - bool DoActiveModifierKeysMatch(const std::unordered_set& consoleModifiers) const noexcept; + bool DoActiveModifierKeysMatch(const std::unordered_set& consoleModifiers) const; bool IsCommandLineEditingKey() const noexcept; bool IsPopupKey() const noexcept; diff --git a/src/types/inc/UTF8OutPipeReader.hpp b/src/types/inc/UTF8OutPipeReader.hpp index 4383ad0366a..93c1b5975ff 100644 --- a/src/types/inc/UTF8OutPipeReader.hpp +++ b/src/types/inc/UTF8OutPipeReader.hpp @@ -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 @@ class UTF8OutPipeReader final }; // array of bitmasks - constexpr const static BYTE _cmpMasks[]{ + constexpr static std::array _cmpMasks{ 0, // unused _Utf8BitMasks::MaskContinuationByte, _Utf8BitMasks::MaskLeadByteTwoByteSequence, @@ -54,7 +54,7 @@ class UTF8OutPipeReader final }; // array of values for the comparisons - constexpr const static BYTE _cmpOperands[]{ + constexpr static std::array _cmpOperands{ 0, // unused _Utf8BitMasks::IsAsciiByte, // intentionally conflicts with MaskContinuationByte _Utf8BitMasks::IsLeadByteTwoByteSequence, @@ -62,7 +62,7 @@ class UTF8OutPipeReader final }; 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 _buffer; // buffer for the chunk read. + std::array _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 }; diff --git a/src/types/inc/Utf16Parser.hpp b/src/types/inc/Utf16Parser.hpp index d093b3396ea..f48bdc0cda2 100644 --- a/src/types/inc/Utf16Parser.hpp +++ b/src/types/inc/Utf16Parser.hpp @@ -28,7 +28,7 @@ class Utf16Parser final public: static std::vector> 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 diff --git a/src/types/inc/utils.hpp b/src/types/inc/utils.hpp index 8d3cd50cc87..ff1c8dd1781 100644 --- a/src/types/inc/utils.hpp +++ b/src/types/inc/utils.hpp @@ -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(std::clamp(value, + static_cast(min), + static_cast(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& table); - void InitializeCampbellColorTableForConhost(gsl::span& table); - void SwapANSIColorOrderForConhost(gsl::span& table); - void Initialize256ColorTable(gsl::span& table); - void SetColorTableAlpha(gsl::span& table, const BYTE newAlpha); + void InitializeCampbellColorTable(const gsl::span table); + void InitializeCampbellColorTableForConhost(const gsl::span table); + void SwapANSIColorOrderForConhost(const gsl::span table); + void Initialize256ColorTable(const gsl::span 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: + // - + constexpr void SetColorTableAlpha(const gsl::span 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(EndianSwap(static_cast(value))); + return gsl::narrow_cast(EndianSwap(gsl::narrow_cast(value))); } constexpr GUID EndianSwap(GUID value) @@ -57,5 +84,5 @@ namespace Microsoft::Console::Utils return value; } - GUID CreateV5Uuid(const GUID& namespaceGuid, const gsl::span& name); + GUID CreateV5Uuid(const GUID& namespaceGuid, const gsl::span name); } diff --git a/src/types/inc/viewport.hpp b/src/types/inc/viewport.hpp index d9d8d5c2439..25f5b9d7f66 100644 --- a/src/types/inc/viewport.hpp +++ b/src/types/inc/viewport.hpp @@ -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; diff --git a/src/types/ut_types/UtilsTests.cpp b/src/types/ut_types/UtilsTests.cpp index 57cab5c0844..06153aee2dd 100644 --- a/src/types/ut_types/UtilsTests.cpp +++ b/src/types/ut_types/UtilsTests.cpp @@ -52,11 +52,11 @@ void UtilsTests::TestSwapColorPalette() std::array consoleTable; gsl::span terminalTableView = { &terminalTable[0], gsl::narrow(terminalTable.size()) }; - gsl::span consoleTableleView = { &consoleTable[0], gsl::narrow(consoleTable.size()) }; + gsl::span consoleTableView = { &consoleTable[0], gsl::narrow(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]); diff --git a/src/types/utils.cpp b/src/types/utils.cpp index 7b3f6cfd075..bfc3ffe6556 100644 --- a/src/types/utils.cpp +++ b/src/types/utils.cpp @@ -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(std::clamp(value, - static_cast(min), - static_cast(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 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(std::stoul(rStr, nullptr, 16)); - BYTE g = static_cast(std::stoul(gStr, nullptr, 16)); - BYTE b = static_cast(std::stoul(bStr, nullptr, 16)); + const BYTE r = gsl::narrow_cast(std::stoul(rStr, nullptr, 16)); + const BYTE g = gsl::narrow_cast(std::stoul(gStr, nullptr, 16)); + const BYTE b = gsl::narrow_cast(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: // - , throws if the table has less that 16 entries -void Utils::InitializeCampbellColorTable(gsl::span& table) +void Utils::InitializeCampbellColorTable(const gsl::span table) { THROW_HR_IF(E_INVALIDARG, table.size() < 16); @@ -167,7 +153,7 @@ void Utils::InitializeCampbellColorTable(gsl::span& table) // - table: a color table with at least 16 entries // Return Value: // - , throws if the table has less that 16 entries -void Utils::InitializeCampbellColorTableForConhost(gsl::span& table) +void Utils::InitializeCampbellColorTableForConhost(const gsl::span table) { THROW_HR_IF(E_INVALIDARG, table.size() < 16); InitializeCampbellColorTable(table); @@ -180,7 +166,7 @@ void Utils::InitializeCampbellColorTableForConhost(gsl::span& table) // - table: a color table with at least 16 entries // Return Value: // - , throws if the table has less that 16 entries -void Utils::SwapANSIColorOrderForConhost(gsl::span& table) +void Utils::SwapANSIColorOrderForConhost(const gsl::span table) { THROW_HR_IF(E_INVALIDARG, table.size() < 16); std::swap(table[1], table[4]); @@ -196,7 +182,7 @@ void Utils::SwapANSIColorOrderForConhost(gsl::span& table) // - table: a color table with at least 256 entries // Return Value: // - , throws if the table has less that 256 entries -void Utils::Initialize256ColorTable(gsl::span& table) +void Utils::Initialize256ColorTable(const gsl::span table) { THROW_HR_IF(E_INVALIDARG, table.size() < 256); @@ -460,22 +446,6 @@ void Utils::Initialize256ColorTable(gsl::span& 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: -// - -void Utils::SetColorTableAlpha(gsl::span& 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& 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& name) +GUID Utils::CreateV5Uuid(const GUID& namespaceGuid, const gsl::span 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 buffer; THROW_IF_NTSTATUS_FAILED(BCryptFinishHash(hash.get(), buffer.data(), gsl::narrow(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 diff --git a/src/types/viewport.cpp b/src/types/viewport.cpp index cb088c0519a..c6772bfdcc6 100644 --- a/src/types/viewport.cpp +++ b/src/types/viewport.cpp @@ -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;