-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Insert-Replace Mode (IRM) and SM/RM #8689
Conversation
{ | ||
THROW_HR_IF(E_INVALIDARG, index >= _charRow.size()); | ||
THROW_HR_IF(E_INVALIDARG, limitRight.value_or(0) >= _charRow.size()); | ||
size_t currentIndex = index; | ||
|
||
// If we're given a right-side column limit, use it. Otherwise, the write limit is the final column index available in the char row. | ||
const auto finalColumnInRow = limitRight.value_or(_charRow.size() - 1); | ||
const auto iteratorEmitsText = it && it->TextAttrBehavior() != TextAttributeBehavior::StoredOnly; | ||
insert = insert && iteratorEmitsText; // we only support insert mode for textful iterators |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CAVEAT: we should be able to insert attributes, but... nobody has asked for this, so why bother?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if by attribute you mean blink, underline, bold, double wide, or double height, then it's what the ANSI terminal protocol requires, and waiting for somebody to ask for it is probably the wrong approach.
if by attribute you mean something internal that doesn't impact ANSI compatibility, then i'd agree, "why bother?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, this is an implementation detail.
This writer supports text, attributes (ANSI as well as Windows console-specific flags), and combined text+attributes. Attribute-only writing changes the style of text without changing the text itself, and is used to support some Win32 console APIs such as FillConsoleOutputAttribute
.
Since there’s no need for us to do an insert operation on attributes only without simultaneously manipulating the text stored in the buffer, we can avoid the complexity. It would produce an interesting effect, but I am not aware of any VT or Console requirement to do so.
@@ -97,17 +97,29 @@ const UnicodeStorage& ROW::GetUnicodeStorage() const noexcept | |||
// - limitRight - right inclusive column ID for the last write in this row. (optional, will just write to the end of row if nullopt) | |||
// Return Value: | |||
// - iterator to first cell that was not written to this row. | |||
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap, std::optional<size_t> limitRight) | |||
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap, std::optional<size_t> limitRight, bool insert) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DESIGN QUESTION: Should insertion be a property on the OutputCellIterator
instead of forced down into the row?
std::unique_ptr<CharRow> backupCharRow; | ||
std::unique_ptr<ATTR_ROW> backupAttrRow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: Memory profiler shows this causes 0 allocations, but it does incur a minor stack cost.
@@ -2309,6 +2310,11 @@ OutputCellRect SCREEN_INFORMATION::ReadRect(const Viewport viewport) const | |||
// - will throw exception on error. | |||
OutputCellIterator SCREEN_INFORMATION::Write(const OutputCellIterator it) | |||
{ | |||
__assume(!_insertMode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: This did nothing in my testing, but it makes me feel better. The optimizer actually deleted this function and TextBuffer::Write
(and ...::Insert
(!)) because it saw right through our trick. It lifted the boolean load from SCREEN_INFORMATION::_insertMode
directly into WriteCharsLegacy
and passed it down into the fully-realized ROW::Write(..., insert)
(!)
in case my earlier comment on one of the individual changes isn't noticed there, i'll repeat something here: i hope that this PR will be gated by successful completion of the vttest suite, including its insert/delete character/line tests. |
of course! 😄 |
Sorry, now that I'm at a computer I can explain a bit better. Attributes and attribute insertionThe console buffer implementation (shared with Windows Terminal) stores text and "attributes" separately. Attributes are everything you'd expect--graphic renditions as well as cell size (potentially; pending #8664)--and some things you wouldn't, like whether there's an OSC 8 hyperlink or what "grid lines"² are enabled. Today, the The caveat noted above is for the following scenario:
Since it only changes the attributes, ² The Win32 console supports drawing borders around every cell; the bottom border is distinct from underline, the top border is recycled for overline, and the left/right borders are used in some CJK composition scenarios. vttestedit: thanks for reviewing! |
This implementation will absolutely hork UnicodeStorage. It tracks non-dbcs high unicode by row/column index. Shuffling the backing store for the row but not updating UnicodeStorage will make it blast into outer space. We are likely overdue for a UnicodeStorage redesign. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't have a Windows software build environment, so i'm not in a position to test this PR. is there a .EXE i can try?
@vixie sorry, we ended up running into some of our longstanding code rot and this work is, as a result, a bit delayed. I'm keeping it on the docket for 2021 such that we can finally put it to bed, and will keep this thread updated. Once we're in a place where what you test is close to what we want to ship, I'll share a build of conhost/openconsole (without any of the terminal bits) to test with. |
This comment has been minimized.
This comment has been minimized.
What happened to that poor bot? |
@hellow554 This branch is pretty stale, I'm betting the spellcheck rules in this branch don't quite work for the updated version of the bot |
Any chance this sequence will be updated with the latest changes? I think this would be a useful sequence to support. |
So, the significant blocker for IRM is that we didn't have a good way to shift our backing store character-by-character to handle insertion (due to some legacy baggage that we had accumulated over time (" |
Nah, you're totally right. I can't land this in its current form, and it's just clogging the list up until it can land. I'll keep the branch. |
Mike Griese wrote on 2022-07-05 07:08:
since the implementation of this
is likely to change aggressively after #8000
lands, should we
close out this draft for now?
if Terminal would stop identifying itself as "xterm" and instead answer
as "vt100", then we could postpone implementing IRM and SM/RM until
after #8000 lands.
Terminal isn't "xterm" and that problem can be fixed several ways.
…--
P Vixie
|
given this has been open for more than two years and that it's blocked on #8000 which has also been open for two years, can i ask that the TERM variable be set to something other than "xterm-256color" please? that's false, since xterm has insert mode, and this terminal emulator does not. if you won't change it to "vt220" then at least add a configuration setting for TERM. you can revert this when and if this terminal emulator ever actually becomes xterm compatible. |
This pull request adds support for IRM. I chose a brute-force strategy:
every time we insert text into a row, back up the characters and
attributes and stamp them down at the end of the inserted range.
Pros:
CharRowCell
sCons:
single character. Most output inserted is going to be on the order
of single characters. 120 single characters, inserted one by one,
with a memcpy() after each one.
I consider the cons to be acceptable enough for this scenario. It's rare,
and it seems like the most common use is in interactive shells where we
need to operate at "user speed". We can always optimize it later.
I chose to give
SCREEN_INFORMATION
knowledge of whether it was ininsert mode, rather than the text buffer, adapter or any other
component. When insert mode is on, the text buffer is instructed to
insert--a request it passes directly on to
ROW
. I've tried to keepbranch misprediction to a minimum (with some optimizer hints) and reduce
default-case allocations¹.
¹ by using
unique_ptr<...>
to store copiedCharRow
andATTR_ROW
,s.t. there is no cost in the normal case except
2*sizeof(void*)
byteson the stack in
ROW::WriteCells
Closes #1947
Validation
ATTR_ROW
stuff added, pass