This fixes a bug when moving backwards by word that resulted in #7742.
This also includes...
- a minor refactor that leverages `GetWordStart` in `MoveToPreviousWord`
- additional unit tests for movement by word
- a feature test comprised of the referenced bug report
`MoveToPreviousWord()` would...
- move backwards for each whitespace character
- then, move backwards for each regular character
This would actually result in moving to the beginning of the current "word" (as defined by a11y).
We actually need to do this process twice:
- the first time gets you to the beginning of the current word
- attempt to move back by one character
- the second time gets you to the beginning of the previous word
Rather than implementing 4 while loops, we leverage `GetWordStart()` to
attempt to move to the beginning of the previous word. We call it twice
(as described above). The logic is unchanged, but we instead reuse a
function that has already undergone more testing.
To make sure this works as expected, additional unit tests were
introduced covering "MoveByWord" in the TextBuffer.
## Validation Steps Performed
Added test for repro steps.
Added unit tests for movement by word.
Closes#7742
til::static_map can't be constexpr until we move to C++20.
It can't be constexpr because std::sort isn't constexpr until then.
This poses a problem: if we start using it and treating it like a map,
we'll incur a potentially high cost in static initialization in both
code size in .text and runtime.
This commit introduces presorted_static_map, which is static_map except
that it doesn't automatically sort its keys. That's the only difference.
At this point, it's just a maplike interface to a constant array of
pairs that does a binary search. It should be used for small tables that
are used infrequently enough as to not warrant their cost in code size
or initialization time. It should also be used for tables that aren't
going to be edited much by developers (like the color table in #7578.)
Sometimes when we were sliding the viewport to fit inside the buffer, we
would end up with left > right.
That would cause us to crash down the line when rendering.
Fixes MSFT:28387423
Fixes#7744
DestListLogoUri cannot handle paths that are separated with / unless
they're actually URLs. We have to guess somewhat whether something is a
file path and if it appears to be one, normalize it.
Fixes#7706
`EndExclusive` represents the end of the buffer. This is designed to not
point to any data on the buffer. UiaTextRange would point to this
`EndExclusive` and then attempt to move based on it. However, since it
does not point to any data, it could experience undefined behavior or
(inevitably) crash from running out of bounds.
This PR specifically checks for expansion and movement at that point,
and prevents us from moving beyond it. There are plans in the future to
define the "end" as the last character in the buffer. Until then, this
solution will suffice and provide correct behavior that doesn't crash.
## Validation Steps Performed
Performed the referenced bugs' repro steps and added test coverage.
Closes MSFT-20458595
Closes#7663Closes#7664
This PR adds support for the _blink_ graphic rendition attribute. When a
character is output with this attribute set, it "blinks" at a regular
interval, by cycling its color between the normal rendition and a dimmer
shade of that color.
The majority of the blinking mechanism is encapsulated in a new
`BlinkingState` class, which is shared between the Terminal and Conhost
implementations. This class keeps track of the position in the blinking
cycle, which determines whether characters are rendered as normal or
faint.
In Windows Terminal, the state is stored in the `Terminal` class, and in
Conhost it's stored in the `CONSOLE_INFORMATION` class. In both cases,
the `IsBlinkingFaint` method is used to determine the current blinking
rendition, and that is passed on as a parameter to the
`TextAttribute::CalculateRgbColors` method when these classes are
looking up attribute colors.
Prior to calculating the colors, the current attribute is also passed to
the `RecordBlinkingUsage` method, which keeps track of whether there are
actually any blink attributes in use. This is used to determine whether
the screen needs to be refreshed when the blinking cycle toggles between
the normal and faint renditions.
The refresh itself is handled by the `ToggleBlinkingRendition` method,
which is triggered by a timer. In Conhost this is just piggybacking on
the existing cursor blink timer, but in Windows Terminal it needs to
have its own separate timer, since the cursor timer is reset whenever a
key is pressed, which is not something we want for attribute blinking.
Although the `ToggleBlinkingRendition` is called at the same rate as the
cursor blinking, we actually only want the cells to blink at half that
frequency. We thus have a counter that cycles through four phases, and
blinking is rendered as faint for two of those four. Then every two
cycles - when the state changes - a redraw is triggered, but only if
there are actually blinking attributes in use (as previously recorded).
As mentioned earlier, the blinking frequency is based on the cursor
blink rate, so that means it'll automatically be disabled if a user has
set their cursor blink rate to none. It can also be disabled by turning
off the _Show animations in Windows_ option. In Conhost these settings
take effect immediately, but in Windows Terminal they only apply when a
new tab is opened.
This PR also adds partial support for the `SGR 6` _rapid blink_
attribute. This is not used by DEC terminals, but was defined in the
ECMA/ANSI standards. It's not widely supported, but many terminals just
it implement it as an alias for the regular `SGR 5` blink attribute, so
that's what I've done here too.
## Validation Steps Performed
I've checked the _Graphic rendition test pattern_ in Vttest, and
compared our representation of the blink attribute to that of an actual
DEC VT220 terminal as seen on [YouTube]. With the right color scheme
it's a reasonably close match.
[YouTube]: https://www.youtube.com/watch?v=03Pz5AmxbE4&t=1m55sCloses#7388
Some IME implementations do not produce composition strings, and their
users have come to rely on the cursor that conhost traditionally left on
until a composition string showed up. We shouldn't hide the cursor until
we get a string (as opposed to hiding it when composition begins) so as
to not break those IMEs.
Related to #6207.
Fixes MSFT:29219348
Currently, `CommandPalette` creates and maintains the `SwitchToTab`
commands used for the ATS. When `Command` goes into the
TerminalSettingsModel, the palette won't be able to access `Command`'s
implementation type, making it difficult for `CommandPalette` to tell
`Command` to listen to `Tab` for changes.
This PR changes the relationship up so `Tab` now manages its
`SwitchToTab` command, and `CommandPalette` just plops the command from
`Tab` into its list.
Add `ToJson()` to the `ConversionTrait`s in JsonUtils. This can be used
to serialize settings objects into JSON.
As a proof of concept, `ToJson` and `UpdateJson` were added to
`ColorScheme`.
Getters and setters for members and colors in the color table were added
and polished.
## References
#1564 - Settings UI
`ColorScheme` is a particularly easy example of serialization because it
has _no fallback_.
Added a few tests for JSON serializers.
## Summary of the Pull Request
This fixes a typo in the `HyperlinkIdConsistency` unit test which was causing that test to fail. It was mistakenly using a `/` instead of `\` for the string terminator sequences.
## References
The test initially worked because of a bug in the state machine parser, but that bug was recently fixed in PR #7340.
## PR Checklist
* [x] Closes#7654
* [x] CLA signed.
* [x] Tests passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan.
## Validation Steps Performed
I've run the test again and it now passes.
C1 control characters are now first converted to their 7 bit equivalent.
This allows us to unify the logic of C1 and C0 escape handling. This
also adds support for SOS/PM/APC string.
* Unify the logic for C1 and C0 escape handling by converting C1 to C0
beforehand. This adds support for various C1 characters, including
IND(8/4), NEL(8/5), HTS(8/8), RI(8/13), SS2(8/14), SS3(8/15),
OSC(9/13), etc.
* Add support for SOS/PM/APC escape sequences. Fixes#7032
* Use "Variable Length String" logic to unify the string termination
handling of OSC, DCS and SOS/PM/APC. This fixes an issue where OSC
action is successfully dispatched even when terminated with non-ST
character. Introduced by #6328, the DCS PassThrough is spared from
this issue. This PR puts them together and add test cases for them.
References:
https://vt100.net/docs/vt510-rm/chapter4.htmlhttps://vt100.net/emu/dec_ansi_parserCloses#7032Closes#7317
`KeyMapping` was introduced to break up `AppKeyBindings`. `KeyMapping`
records the keybindings from the JSON and lets you query them.
`AppKeyBindings` now just holds a `ShortcutActionDispatcher` to run
actions, and a `KeyMapping` to record/query your existing keybindings.
This refactor allows `KeyMapping` to be moved to the
TerminalSettingsModel, and `ShortcutActionDispatcher` and
`AppKeyBindings` will stay in TerminalApp.
`AppKeyBindings` had to be passed down to a terminal via
`TerminalSettings`. Since each settings object had its own
responsibility to update/create a `TerminalSettings` object, I moved all
of that logic to `TerminalSettings`. This helps with the
TerminalSettingsModel refactor, and makes the construction of
`TerminalSettings` a bit cleaner and more centralized.
## References
#885 - this is all in preparation for the TerminalSettingsModel
## Validation Steps Performed
- [x] Tests passed
- [X] Deployment succeeded
Clang (10) has no trouble optimizing the COLORREF conversion operator to
a simple 32-bit load with mask (!) even though it's a series of bit
shifts across multiple struct members.
MSVC (19.24) doesn't make the same optimization decision, and it emits
three 8-bit loads and some shifting.
In any case, the optimization only applies at -O2 (clang) and above.
In this commit, we leverage the spec-legality of using unions for type
conversions and the overlap of four uint8_ts and a uint32_t to make the
conversion very obvious to both compilers.
x86_64 msvc | O0 | O1 | O2
------------|----|----|--------------------
shifts | 12 | 11 | 11 (fully inlined)
union | 5 | 1 | 1 (fully inlined)
x86_64 clang | O0 | O1 | O2 + O3
-------------|----|----|--------------------
shifts | 14 | 5 | 1 (fully inlined)
union | 9 | 3 | 1 (fully inlined)
j4james brought up some concerns about til::color's minor wastefulness
in https://github.com/microsoft/terminal/pull/7578#discussion_r487355989.
This is a clear, simple transformation that saves us a few instructions
in a relatively common case, so I'm accepting a micro-optimization even
though we don't have data showing this to be a hot spot.
Now that CascadiaSettings is a WinRT object, we need to update the error
handling a bit. Making it a WinRT object limits our errors to be
hresults. So we moved all the error handling down a layer to when we
load the settings object.
- Warnings encountered during validation are saved to `Warnings()`.
- Errors encountered during validation are saved to `GetLoadingError()`.
- Deserialization errors (mainly from JsonUtils) are saved to
`GetDeserializationErrorMessage()`.
## References
#7141 - CascadiaSettings is a settings object
#885 - this makes ripping out CascadiaSettings into
TerminalSettingsModel much easier
## Validation Steps Performed
* [x] Tests passed
- [x] Deployment succeeded
- tested with invalid JSON (deserialization error)
- tested with missing DefaultProfile (validation error)
If a user clicks a link that is either invalid (cannot be parsed) or has
a scheme we do not support (like file or mailto (for now)), we open up a
dialog box telling them the issue.
References #5001
- Render hyperlinks with a dashed underline
- Render hovered hyperlinks with a solid underline
- Show URI tooltip on hover
TermControl now has a canvas that contains a tiny border to which a
tooltip is attached. When we hover over hyperlinked text, we move the
border to the mouse location and update the tooltip content with the
URI.
Introduced a new underline type (HyperlinkUnderline), supports rendering
for it, and uses it to render hyperlinks. HyperlinkUnderline is usually
a dashed underline, but when a link is hovered, all text with the same
hyperlink ID is rendered with a solid underline.
References #5001
This fixes an issue where two CPRs could end up corrupted in the input
buffer. An application that sent two CPRs back-to-back could
end up reading the first few characters of the first prepended CPR
before handing us another CPR. We would dutifully prepend it to the
buffer, causing them to overlap.
```
^[^[2;2R[1;1R
^^ ^^^^^ First CPR
^^^^^^ Second CPR
```
The end result of this corruption is that a requesting application
would receive an unbidden `R` on stdin; for vim, this would trigger
replace mode immediately on startup.
Response prepending was implemented in !997738 without much comment.
There's very little in the way of audit trail as to why we switched.
Michael believes that we wanted to make sure that applications got DSR
responses immediately. It had the unfortunate side effect of causing
subsequence CPRs across cursor moves to come out in the wrong order.
I discussed our options with him, and he suggested that we could
implement a priority queue in InputBuffer and make sure that "response"
input was dispatched to a client application before any application- or
user-generated input. This was deemed to be too much work.
We decided that DSR responses getting top billing was likely to be a
stronger guarantee than most terminals are capable of giving, and that
we should be fine if we just switch it back to append.
Thanks to @k-takata, @tekki and @brammool for the investigation on the
vim side.
Fixes#1637.
This commit leverages C++/WinRT's final_release [extension point] to
pull the final destruction of ConptyConnection off onto a background
thread.
We've been seeing some deadlocks during teardown where the output thread
(holding the last owning reference to the connection) was trying to
destruct the threadpool wait while the threadpool wait was
simultaneously running its callback and waiting for the output thread to
terminate. It turns out that trying to release a threadpool wait while
it's running a callback that's blocked on you will absolutely result in
a deadlock.
Fixes#7392.
[extension point]: https://devblogs.microsoft.com/oldnewthing/20191018-00/?p=103010
CascadiaSettings is now a WinRT object in the TerminalApp project.
## References
#7141 - CascadiaSettings is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project
This one _looks_ big, but most of it is really just propagating the
changes to the tests. In fact, you can probably save yourself some time
because the tests were about an hour of Find&Replace.
`CascadiaSettings::GetCurrentAppSettings()` was only being used in
Pane.cpp. So I ripped out the 3 lines of code and stuffed them in there.
Follow-up work:
- There's a few places in AppLogic where I `get_self` to be able to get
the warnings out. This will go away in the next PR (wrapping up #885)
## Validation Steps Performed
- [x] Tests passed
- [X] Deployment succeeded
Closes#7141
By setting the jumplist entries to launch `WindowsTerminal.exe` out of
the package root, we've inadvertently made WindowsTerminalDev emit jump
list entries that launch the _unpackaged_ version of Terminal.
We can fix this by copying the code from the shell extension that
determines which version of the executable to launch -- wt, wtd or
WindowsTerminal -- depending on the context under which it was invoked.
Fixes#7554
Conhost expands UIA text ranges when moved. This means that degenerate
ranges become non-degenerate after movement, leading to odd behaviour
from UIA clients. This PR doesn't expand degenerate ranges, but rather
keeps them degenerate by moving `_end` to the newly-changed `_start`.
Tested in the NVDA Python console (cases with `setEndPoint` and
`compareEndPoints` described in #7342). Also ran the logic by
@michaeldcurran.
Closes#7342
Almost definitely addresses nvaccess/nvda#11288 (although I'll need to
test with my Braille display). Also fixes an issue privately reported to
me by @simon818 with copy/paste from review cursor which originally lead
me to believe the issue was with `moveEndPointByRange`.
This PR is about the behavior of DECSCUSR. This PR changes the meaning
of DECSCUSR 0 to restore the cursor style back to user default. This
differs from what VT spec says but it’s used in popular terminal
emulators like iTerm2 and VTE-based ones. See #1604.
Another change is that for parameter greater than 6, DECSCUSR should be
ignored, instead of restoring the cursor to legacy. This PR fixes it.
See #7382.
Fixes#1604.
This commit introduces Jumplist customization and an item for each
profile to the Jumplist. Selecting an entry in the jumplist will pretty
much just execute `wt.exe -p "{profile guid}"`, and so a new Terminal
will open with the selected profile.
Closes#576
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_onecore_dep_uxp dd0c54d9abd94dea1ffe956373a4c20b30a6151e
Related work items: MSFT-26187783
When attempting to select a text range from a different text buffer (such as a standard text range when in alt mode), conhost crashes. This PR checks for this case and returns `E_FAIL` instead, preventing this crash.
## PR Checklist
* [x] Closes unfiled crash issue
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Passes manual test below
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
## Validation Steps Performed
Ran the following lines in the NVDA Python console (NVDA+control+z) before and after this PR, and observed that Conhost no longer crashes after the change:
``` Python console
>>> # SSH to a remote Linux system
>>> ti=nav.makeTextInfo("caret")
>>> ti.move("line", -2)
-2
>>> # Switch away from the NVDA Python console, and run Nano in conhost. Then:
>>> ti.updateSelection() # Calls select() on the underlying UIA text range
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "NVDAObjects\UIA\__init__.pyc", line 790, in updateSelection
File "comtypesMonkeyPatches.pyc", line 26, in __call__
_ctypes.COMError: (-2147220991, 'An event was unable to invoke any of the subscribers', (None, None, None, 0, None))
```
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Conhost can now support OSC8 sequences (as specified [here](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)). Terminal also supports those sequences and additionally hyperlinks can be opened by Ctrl+LeftClicking on them.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#204
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [X] Closes#204
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Added support to:
- parse OSC8 sequences and extract URIs from them (conhost and terminal)
- add hyperlink uri data to textbuffer/screeninformation, associated with a hyperlink id (conhost and terminal)
- attach hyperlink ids to text to allow for uri extraction from the textbuffer/screeninformation (conhost and terminal)
- process ctrl+leftclick to open a hyperlink in the clicked region if present
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Open up a PowerShell tab and type
```PowerShell
${ESC}=[char]27
Write-Host "${ESC}]8;;https://github.com/microsoft/terminal${ESC}\This is a link!${ESC}]8;;${ESC}\"
```
Ctrl+LeftClick on the link correctly brings you to the terminal page on github
![hyperlink](https://user-images.githubusercontent.com/26824113/89953536-45a6f580-dbfd-11ea-8e0d-8a3cd25c634a.gif)
GlobalAppSettings is now a WinRT object in the TerminalApp project.
## References
#7141 - GlobalAppSettings is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project
## PR Checklist
* [x] Tests passed
## Detailed Description of the Pull Request / Additional comments
This one was probably the easiest thus far.
The only weird thing is how we handle InitialPosition. Today, we lose a
little bit of fidelity when we convert from LaunchPosition (int) -->
Point (float) --> RECT (long). The current change converts
LaunchPosition (optional<long>) --> InitialPosition (long) --> RECT
(long).
NOTE: Though I could use LaunchPosition to go directly from TermApp to
AppHost, I decided to introduce InitialPosition because LaunchPosition
will be a part of TerminalSettingsModel soon.
## Validation Steps Performed
- [x] Tests passed
- [x] Deployment succeeded
Profile is now a WinRT object in the TerminalApp project.
As with ColorScheme, all of the serialization logic is not exposed via
the idl. TerminalSetingsModel will handle it when it's all moved over.
I removed the "Get" and "Set" prefixes from all of the Profile
functions. It just makes more sense to use the `GETSET_PROPERTY` macro
to do most of the work for us.
`CloseOnExitMode` is now an enum off of the Profile.idl.
`std::optional<wstring>` got converted to `hstring` (as opposed to
`IReference<hstring>`). `IReference<hstring>` is not valid to MIDL.
## References
#7141 - Profile is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project
## Validation Steps Performed
- [x] Tests passed
- [x] Deployment succeeded
Closes#7435