mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-12 17:21:03 +00:00
Compare commits
39 Commits
release-1.
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
520a550655 | ||
|
|
84d68f082e | ||
|
|
41796c2409 | ||
|
|
9eb77cf0f1 | ||
|
|
9cbb172323 | ||
|
|
6e2f53b025 | ||
|
|
d1afa2af14 | ||
|
|
e52549ace0 | ||
|
|
60f63b09cc | ||
|
|
64c2e856cc | ||
|
|
bfebcf248d | ||
|
|
4d1570f4b4 | ||
|
|
3a48e19b1d | ||
|
|
cb81e61949 | ||
|
|
e3181e76c9 | ||
|
|
0163878d23 | ||
|
|
c8f0a5e5d5 | ||
|
|
65b457113d | ||
|
|
7237fced16 | ||
|
|
bf3d79e41a | ||
|
|
0cfb4637e2 | ||
|
|
4c96fc08a1 | ||
|
|
e658431c11 | ||
|
|
9453aa5ee1 | ||
|
|
0a1ed70153 | ||
|
|
69d0973f14 | ||
|
|
57094b7d98 | ||
|
|
54dc30411c | ||
|
|
5d8c0d0b9b | ||
|
|
65295796f2 | ||
|
|
d08d21626f | ||
|
|
57280d8961 | ||
|
|
60d2c2e26d | ||
|
|
dff1b94016 | ||
|
|
bf24cdd4b0 | ||
|
|
1209fa40c3 | ||
|
|
dd702c769d | ||
|
|
e94e08c303 | ||
|
|
83466a4381 |
15
.github/actions/spelling/README.md
vendored
Normal file
15
.github/actions/spelling/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# check-spelling/check-spelling configuration
|
||||
|
||||
File | Purpose | Format | Info
|
||||
-|-|-|-
|
||||
[allow/*.txt](allow/) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
|
||||
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
|
||||
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
|
||||
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
|
||||
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
|
||||
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
|
||||
|
||||
Note: you can replace any of these files with a directory by the same name (minus the suffix)
|
||||
and then include multiple files inside that directory (with that suffix) to merge multiple files together.
|
||||
38
.github/actions/spelling/advice.md
vendored
38
.github/actions/spelling/advice.md
vendored
@@ -1,4 +1,4 @@
|
||||
<!-- markdownlint-disable MD033 MD041 -->
|
||||
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
|
||||
<details>
|
||||
<summary>
|
||||
:pencil2: Contributor please read this
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
|
||||
|
||||
:warning: The command is written for posix shells. You can copy the contents of each `perl` command excluding the outer `'` marks and dropping any `'"`/`"'` quotation mark pairs into a file and then run `perl file.pl` from the root of the repository to run the code. Alternatively, you can manually insert the items...
|
||||
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
|
||||
|
||||
If the listed items are:
|
||||
|
||||
@@ -20,31 +20,29 @@ See the `README.md` in each directory for more information.
|
||||
|
||||
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
|
||||
|
||||
<details><summary>:clamp: If you see a bunch of garbage</summary>
|
||||
|
||||
If it relates to a ...
|
||||
<details><summary>well-formed pattern</summary>
|
||||
<details><summary>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
If not, try writing one and adding it to a `patterns/{file}.txt`.
|
||||
Please add a file path to the `excludes.txt` file matching the containing file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
<details><summary>binary-ish string</summary>
|
||||
|
||||
Please add a file path to the `excludes.txt` file instead of just accepting the garbage.
|
||||
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
|
||||
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
../tree/HEAD/README.md) (on whichever branch you're using).
|
||||
</details>
|
||||
|
||||
|
||||
* well-formed pattern.
|
||||
|
||||
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
|
||||
try adding it to the `patterns.txt` file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
24
.github/actions/spelling/allow/allow.txt
vendored
24
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,20 +1,21 @@
|
||||
admins
|
||||
apc
|
||||
allcolors
|
||||
Apc
|
||||
bsd
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
calt
|
||||
CMMI
|
||||
ccmp
|
||||
changelog
|
||||
clickable
|
||||
clig
|
||||
CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
dcs
|
||||
dialytika
|
||||
dje
|
||||
downside
|
||||
@@ -26,36 +27,43 @@ EDDC
|
||||
Enum'd
|
||||
Fitt
|
||||
formattings
|
||||
FTCS
|
||||
ftp
|
||||
fvar
|
||||
gantt
|
||||
gcc
|
||||
geeksforgeeks
|
||||
ghe
|
||||
github
|
||||
gje
|
||||
godbolt
|
||||
hostname
|
||||
hostnames
|
||||
https
|
||||
hyperlink
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
iconify
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
libfuzzer
|
||||
libuv
|
||||
liga
|
||||
lje
|
||||
Llast
|
||||
llvm
|
||||
Lmid
|
||||
locl
|
||||
lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
noreply
|
||||
nje
|
||||
noreply
|
||||
ogonek
|
||||
@@ -76,13 +84,16 @@ runtimes
|
||||
shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
TLDR
|
||||
tokenizes
|
||||
tonos
|
||||
toolset
|
||||
tshe
|
||||
ubuntu
|
||||
uiatextrange
|
||||
UIs
|
||||
und
|
||||
@@ -91,6 +102,7 @@ versioned
|
||||
vsdevcmd
|
||||
We'd
|
||||
wildcards
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
allcolors
|
||||
|
||||
22
.github/actions/spelling/allow/apis.txt
vendored
22
.github/actions/spelling/allow/apis.txt
vendored
@@ -5,6 +5,7 @@ aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
appxrecipe
|
||||
bitfield
|
||||
bitfields
|
||||
BUILDBRANCH
|
||||
@@ -14,6 +15,7 @@ BYCOMMAND
|
||||
BYPOSITION
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
CLOSEAPP
|
||||
cmdletbinding
|
||||
COLORPROPERTY
|
||||
colspan
|
||||
@@ -28,9 +30,14 @@ dataobject
|
||||
dcomp
|
||||
DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
@@ -70,6 +77,7 @@ IDirect
|
||||
IExplorer
|
||||
IFACEMETHOD
|
||||
IFile
|
||||
IGraphics
|
||||
IInheritable
|
||||
IMap
|
||||
IMonarch
|
||||
@@ -84,6 +92,7 @@ istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
@@ -95,12 +104,15 @@ lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUITEMINFOW
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
mptt
|
||||
@@ -136,14 +148,17 @@ OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
QUERYENDSESSION
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
@@ -153,6 +168,7 @@ serializer
|
||||
SETVERSION
|
||||
SHELLEXECUTEINFOW
|
||||
shobjidl
|
||||
SHOWHIDE
|
||||
SHOWMINIMIZED
|
||||
SHOWTIP
|
||||
SINGLEUSE
|
||||
@@ -173,6 +189,8 @@ Stubless
|
||||
Subheader
|
||||
Subpage
|
||||
syscall
|
||||
SYSTEMBACKDROP
|
||||
TABROW
|
||||
TASKBARCREATED
|
||||
TBPF
|
||||
THEMECHANGED
|
||||
@@ -192,6 +210,8 @@ UOI
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
winmain
|
||||
|
||||
8
.github/actions/spelling/allow/names.txt
vendored
8
.github/actions/spelling/allow/names.txt
vendored
@@ -1,8 +1,10 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
dhowett
|
||||
Diviness
|
||||
@@ -22,6 +24,7 @@ Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
@@ -35,7 +38,9 @@ leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
@@ -64,10 +69,13 @@ Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Walisch
|
||||
WDX
|
||||
|
||||
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker for ignoring a comment to the end of the line
|
||||
// #no-spell-check.*$
|
||||
|
||||
# patch hunk comments
|
||||
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||
# git index header
|
||||
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
# cid urls
|
||||
(['"])cid:.*?\g{-1}
|
||||
|
||||
# data url in parens
|
||||
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
|
||||
# data url in quotes
|
||||
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
# data url
|
||||
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# magnet urls
|
||||
magnet:[?=:\w]+
|
||||
|
||||
# magnet urls
|
||||
"magnet:[^"]+"
|
||||
|
||||
# obs:
|
||||
"obs:[^"]*"
|
||||
|
||||
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
|
||||
# In this examples content, I'm using a number of different ways to match things to show various approaches
|
||||
# asciinema
|
||||
\basciinema\.org/a/[0-9a-zA-Z]+
|
||||
|
||||
# apple
|
||||
\bdeveloper\.apple\.com/[-\w?=/]+
|
||||
# Apple music
|
||||
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
|
||||
|
||||
# appveyor api
|
||||
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
|
||||
# appveyor project
|
||||
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
|
||||
|
||||
# Amazon
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
# AWS S3
|
||||
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS execute-api
|
||||
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
|
||||
# AWS ELB
|
||||
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
|
||||
# AWS SNS
|
||||
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS VPC
|
||||
vpc-\w+
|
||||
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
# YouTube music
|
||||
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
|
||||
# YouTube tag
|
||||
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
|
||||
# YouTube image
|
||||
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
|
||||
# Google Accounts
|
||||
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
|
||||
# Google Analytics
|
||||
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||
# Google APIs
|
||||
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||
# Google Storage
|
||||
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||
# Google Calendar
|
||||
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
|
||||
\w+\@group\.calendar\.google\.com\b
|
||||
# Google DataStudio
|
||||
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
|
||||
# The leading `/` here is as opposed to the `\b` above
|
||||
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
|
||||
# Google Docs
|
||||
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
|
||||
# Google Drive
|
||||
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
|
||||
# Google Groups
|
||||
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
|
||||
# Google Maps
|
||||
\bmaps\.google\.com/maps\?[\w&;=]*
|
||||
# Google themes
|
||||
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
# Google CDN
|
||||
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
|
||||
# Goo.gl
|
||||
/goo\.gl/[a-zA-Z0-9]+
|
||||
# Google Chrome Store
|
||||
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
|
||||
# Google Books
|
||||
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
|
||||
# Google Fonts
|
||||
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
|
||||
# Google Forms
|
||||
\bforms\.gle/\w+
|
||||
# Google Scholar
|
||||
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||
# Google Colab Research Drive
|
||||
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||
|
||||
# GitHub SHAs (api)
|
||||
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
# GitHub SHAs
|
||||
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
|
||||
# GitHub wiki
|
||||
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
# githubassets
|
||||
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
|
||||
# gist github
|
||||
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
|
||||
# git.io
|
||||
\bgit\.io/[0-9a-zA-Z]+
|
||||
# GitHub JSON
|
||||
"node_id": "[-a-zA-Z=;:/0-9+]*"
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
# GitLab merge requests
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
|
||||
# GitLab uploads
|
||||
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
|
||||
# GitLab commits
|
||||
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||
|
||||
# binanace
|
||||
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
|
||||
# bitbucket diff
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
|
||||
# bitbucket repositories commits
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
# bitbucket commits
|
||||
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
|
||||
# bit.ly
|
||||
\bbit\.ly/\w+
|
||||
|
||||
# bitrise
|
||||
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
|
||||
|
||||
# bootstrapcdn.com
|
||||
\bbootstrapcdn\.com/[-./\w]+
|
||||
|
||||
# cdn.cloudflare.com
|
||||
\bcdnjs\.cloudflare\.com/[./\w]+
|
||||
|
||||
# circleci
|
||||
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
|
||||
|
||||
# gitter
|
||||
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
|
||||
|
||||
# gravatar
|
||||
\bgravatar\.com/avatar/[0-9a-f]+
|
||||
|
||||
# ibm
|
||||
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
|
||||
|
||||
# imgur
|
||||
\bimgur\.com/[^.]+
|
||||
|
||||
# Internet Archive
|
||||
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
|
||||
|
||||
# discord
|
||||
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
|
||||
|
||||
# Disqus
|
||||
\bdisqus\.com/[-\w/%.()!?&=_]*
|
||||
|
||||
# medium link
|
||||
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
# microsoft store
|
||||
\bmicrosoft\.com/store/apps/\w+
|
||||
|
||||
# mvnrepository.com
|
||||
\bmvnrepository\.com/[-0-9a-z./]+
|
||||
|
||||
# now.sh
|
||||
/[0-9a-z-.]+\.now\.sh\b
|
||||
|
||||
# oracle
|
||||
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
|
||||
|
||||
# chromatic.com
|
||||
/\S+.chromatic.com\S*[")]
|
||||
|
||||
# codacy
|
||||
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
|
||||
|
||||
# compai
|
||||
\bcompai\.pub/v1/png/[0-9a-f]+
|
||||
|
||||
# mailgun api
|
||||
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
|
||||
# mailgun
|
||||
\b[0-9a-z]+.mailgun.org
|
||||
|
||||
# /message-id/
|
||||
/message-id/[-\w@./%]+
|
||||
|
||||
# Reddit
|
||||
\breddit\.com/r/[/\w_]*
|
||||
|
||||
# requestb.in
|
||||
\brequestb\.in/[0-9a-z]+
|
||||
|
||||
# sched
|
||||
\b[a-z0-9]+\.sched\.com\b
|
||||
|
||||
# Slack url
|
||||
slack://[a-zA-Z0-9?&=]+
|
||||
# Slack
|
||||
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
|
||||
# Slack edge
|
||||
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
|
||||
# Slack images
|
||||
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
|
||||
|
||||
# shields.io
|
||||
\bshields\.io/[-\w/%?=&.:+;,]*
|
||||
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# Sentry
|
||||
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||
|
||||
# Twitter markdown
|
||||
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
# Twitter hashtag
|
||||
\btwitter\.com/hashtag/[\w?_=&]*
|
||||
# Twitter status
|
||||
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
|
||||
# Twitter profile images
|
||||
\btwimg\.com/profile_images/[_\w./]*
|
||||
# Twitter media
|
||||
\btwimg\.com/media/[-_\w./?=]*
|
||||
# Twitter link shortened
|
||||
\bt\.co/\w+
|
||||
|
||||
# facebook
|
||||
\bfburl\.com/[0-9a-z_]+
|
||||
# facebook CDN
|
||||
\bfbcdn\.net/[\w/.,]*
|
||||
# facebook watch
|
||||
\bfb\.watch/[0-9A-Za-z]+
|
||||
|
||||
# dropbox
|
||||
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
|
||||
|
||||
# ipfs protocol
|
||||
ipfs://[0-9a-z]*
|
||||
# ipfs url
|
||||
/ipfs/[0-9a-z]*
|
||||
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# loom
|
||||
\bloom\.com/embed/[0-9a-f]+
|
||||
|
||||
# regex101
|
||||
\bregex101\.com/r/[^/\s"]+/\d+
|
||||
|
||||
# figma
|
||||
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
|
||||
|
||||
# freecodecamp.org
|
||||
\bfreecodecamp\.org/[-\w/.]+
|
||||
|
||||
# image.tmdb.org
|
||||
\bimage\.tmdb\.org/[/\w.]+
|
||||
|
||||
# mermaid
|
||||
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
|
||||
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# gitweb
|
||||
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||
|
||||
# HyperKitty lists
|
||||
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||
|
||||
# lists
|
||||
/thread\.html/[^"\s]+
|
||||
|
||||
# list-management
|
||||
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
|
||||
|
||||
# kubectl.kubernetes.io/last-applied-configuration
|
||||
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||
|
||||
# pgp
|
||||
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
|
||||
|
||||
# Spotify
|
||||
\bopen\.spotify\.com/embed/playlist/\w+
|
||||
|
||||
# Mastodon
|
||||
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||
|
||||
# scastie
|
||||
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||
|
||||
# images.unsplash.com
|
||||
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
|
||||
|
||||
# pastebin
|
||||
\bpastebin\.com/[\w/]+
|
||||
|
||||
# heroku
|
||||
\b\w+\.heroku\.com/source/archive/\w+
|
||||
|
||||
# quip
|
||||
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
|
||||
|
||||
# badgen.net
|
||||
\bbadgen\.net/badge/[^")\]'\s]+
|
||||
|
||||
# statuspage.io
|
||||
\w+\.statuspage\.io\b
|
||||
|
||||
# media.giphy.com
|
||||
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
|
||||
|
||||
# tinyurl
|
||||
\btinyurl\.com/\w+
|
||||
|
||||
# getopts
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
# IPv6
|
||||
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||
# c99 hex digits (not the full format, just one I've seen)
|
||||
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
# sha
|
||||
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
# hex in url queries
|
||||
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||
# ssh
|
||||
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
|
||||
|
||||
# PGP
|
||||
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
|
||||
# GPG keys
|
||||
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
|
||||
# Well known gpg keys
|
||||
.well-known/openpgpkey/[\w./]+
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
# integrity
|
||||
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
|
||||
|
||||
# https://www.gnu.org/software/groff/manual/groff.html
|
||||
# man troff content
|
||||
\\f[BCIPR]
|
||||
# '
|
||||
\\\(aq
|
||||
|
||||
# .desktop mime types
|
||||
^MimeTypes?=.*$
|
||||
# .desktop localized entries
|
||||
^[A-Z][a-z]+\[[a-z]+\]=.*$
|
||||
# Localized .desktop content
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# crypt
|
||||
"\$2[ayb]\$.{56}"
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# Input to GitHub JSON
|
||||
content: "[-a-zA-Z=;:/0-9+]*="
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.*/[gim]*\.test\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]*/[gim]*\s*
|
||||
# javascript match regex
|
||||
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||
# javascript regex
|
||||
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
|
||||
# sed regular expressions
|
||||
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||
|
||||
# go install
|
||||
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
|
||||
# kubectl - pods in CrashLoopBackOff
|
||||
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||
|
||||
# kubernetes object suffix
|
||||
-[0-9a-f]{10}-\w{5}\s
|
||||
|
||||
# posthog secrets
|
||||
posthog\.init\((['"])phc_[^"',]+\g{-1},
|
||||
|
||||
# xcode
|
||||
|
||||
# xcodeproject scenes
|
||||
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
|
||||
# font awesome classes
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
# Lorem
|
||||
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
# Note that the next example is no longer necessary if you are using
|
||||
# to match a string starting with a `#`, use a character-class:
|
||||
[#]backwards
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
# Compiler flags (Scala)
|
||||
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
# Compiler flags
|
||||
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||
45
.github/actions/spelling/excludes.txt
vendored
45
.github/actions/spelling/excludes.txt
vendored
@@ -1,28 +1,39 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
|
||||
(?:(?i)\.png$)
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)dirs$
|
||||
(?:^|/)go\.mod$
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)package-lock\.json$
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)sources(?:|\.dep)$
|
||||
SUMS$
|
||||
(?:^|/)vendor/
|
||||
\.a$
|
||||
\.ai$
|
||||
\.avi$
|
||||
\.bmp$
|
||||
\.bz2$
|
||||
\.cer$
|
||||
\.class$
|
||||
\.crl$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
\.drawio$
|
||||
\.DS_Store$
|
||||
\.eot$
|
||||
\.eps$
|
||||
\.exe$
|
||||
\.gif$
|
||||
\.gitattributes$
|
||||
\.graffle$
|
||||
\.gz$
|
||||
\.icns$
|
||||
\.ico$
|
||||
\.jar$
|
||||
\.jks$
|
||||
\.jpeg$
|
||||
\.jpg$
|
||||
\.key$
|
||||
@@ -30,28 +41,53 @@ SUMS$
|
||||
\.lock$
|
||||
\.map$
|
||||
\.min\..
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
\.pdf$
|
||||
\.pem$
|
||||
\.png$
|
||||
\.psd$
|
||||
\.pyc$
|
||||
\.runsettings$
|
||||
\.s$
|
||||
\.sig$
|
||||
\.so$
|
||||
\.svg$
|
||||
\.svgz$
|
||||
\.svgz?$
|
||||
\.tar$
|
||||
\.tgz$
|
||||
\.tiff?$
|
||||
\.ttf$
|
||||
\.vsdx$
|
||||
\.wav$
|
||||
\.webm$
|
||||
\.webp$
|
||||
\.woff
|
||||
\.woff2?$
|
||||
\.xcf$
|
||||
\.xls
|
||||
\.xlsx?$
|
||||
\.xpm$
|
||||
\.yml$
|
||||
\.zip$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.git-blame-ignore-revs\E$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
^build/config/
|
||||
^consolegit2gitfilters\.json$
|
||||
^dep/
|
||||
^doc/reference/master-sequence-list.csv$
|
||||
@@ -77,6 +113,5 @@ SUMS$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
^\.github/actions/spelling/
|
||||
^\.gitignore$
|
||||
^\XamlStyler.json$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
8
.github/actions/spelling/expect/alphabet.txt
vendored
8
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
ABCDEFG
|
||||
ABCDEFGH
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBBBBBBBBBBDDDD
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
CCE
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
@@ -33,7 +26,6 @@ QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
qrstuvwxyz
|
||||
qwerty
|
||||
QWERTYUIOP
|
||||
qwertyuiopasdfg
|
||||
YYYYYYYDDDDDDDDDDD
|
||||
ZAAZZ
|
||||
|
||||
886
.github/actions/spelling/expect/expect.txt
vendored
886
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
23
.github/actions/spelling/expect/web.txt
vendored
23
.github/actions/spelling/expect/web.txt
vendored
@@ -1,29 +1,6 @@
|
||||
http
|
||||
www
|
||||
easyrgb
|
||||
php
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
freedesktop
|
||||
ycombinator
|
||||
robertelder
|
||||
kovidgoyal
|
||||
leonerd
|
||||
fixterms
|
||||
winui
|
||||
appshellintegration
|
||||
mdtauk
|
||||
cppreference
|
||||
gfycat
|
||||
Guake
|
||||
azurewebsites
|
||||
askubuntu
|
||||
dostips
|
||||
viewtopic
|
||||
rosettacode
|
||||
Rexx
|
||||
tldp
|
||||
HOWTO
|
||||
uwspace
|
||||
uwaterloo
|
||||
|
||||
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
|
||||
# \bm_data\b
|
||||
|
||||
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||
# to use this:
|
||||
#\bfit\(
|
||||
|
||||
# s.b. GitHub
|
||||
\bGithub\b
|
||||
|
||||
# s.b. GitLab
|
||||
\bGitlab\b
|
||||
|
||||
# s.b. JavaScript
|
||||
\bJavascript\b
|
||||
|
||||
# s.b. Microsoft
|
||||
\bMicroSoft\b
|
||||
|
||||
# s.b. another
|
||||
\ban[- ]other\b
|
||||
|
||||
# s.b. greater than
|
||||
\bgreater then\b
|
||||
|
||||
# s.b. into
|
||||
#\sin to\s
|
||||
|
||||
# s.b. opt-in
|
||||
\sopt in\s
|
||||
|
||||
# s.b. less than
|
||||
\bless then\b
|
||||
|
||||
# s.b. otherwise
|
||||
\bother[- ]wise\b
|
||||
|
||||
# s.b. nonexistent
|
||||
\bnon existing\b
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. preexisting
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
[Pp]re[- ]emptively
|
||||
|
||||
# s.b. reentrancy
|
||||
[Rr]e[- ]entrancy
|
||||
|
||||
# s.b. reentrant
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# s.b. workaround(s)
|
||||
#\bwork[- ]arounds?\b
|
||||
|
||||
# Reject duplicate words
|
||||
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||
82
.github/actions/spelling/patterns/patterns.txt
vendored
82
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -1,11 +1,6 @@
|
||||
https://(?:(?:[-a-zA-Z0-9?&=]*\.|)microsoft\.com)/[-a-zA-Z0-9?&=_#\/.]*
|
||||
https://aka\.ms/[-a-zA-Z0-9?&=\/_]*
|
||||
https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
|
||||
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
|
||||
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]*
|
||||
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
https?://\S+
|
||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
||||
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
|
||||
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}[Uu]?[Ll]{0,2}\b
|
||||
@@ -28,3 +23,74 @@ vcvars\w*
|
||||
ROY\sG\.\sBIV
|
||||
!(?:(?i)ESC)!\[
|
||||
!(?:(?i)CSI)!(?:\d+(?:;\d+|)m|[ABCDF])
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3831 file-count: 582
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# hit-count: 71 file-count: 35
|
||||
# Compiler flags
|
||||
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
|
||||
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 41 file-count: 28
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 20 file-count: 9
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 10 file-count: 7
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
|
||||
# C/idl types + English ...
|
||||
\s(Guid|long|LONG|that) \g{-1}\s
|
||||
|
||||
# javadoc / .net
|
||||
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# Commit message -- Signed-off-by and friends
|
||||
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
|
||||
|
||||
# Autogenerated revert commit message
|
||||
^This reverts commit [0-9a-f]{40}\.$
|
||||
|
||||
# vtmode
|
||||
--vtmode\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
|
||||
28
.github/actions/spelling/reject.txt
vendored
28
.github/actions/spelling/reject.txt
vendored
@@ -1,22 +1,12 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
^spae$
|
||||
^spaebook$
|
||||
^spaecraft$
|
||||
^spaed$
|
||||
^spaedom$
|
||||
^spaeing$
|
||||
^spaeings$
|
||||
^spae-man$
|
||||
^spaeman$
|
||||
^spaer$
|
||||
^Spaerobee$
|
||||
^spaes$
|
||||
^spaewife$
|
||||
^spaewoman$
|
||||
^spaework$
|
||||
^spaewright$
|
||||
^wether$
|
||||
^wethers$
|
||||
^wetherteg$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
|
||||
132
.github/workflows/spelling2.yml
vendored
132
.github/workflows/spelling2.yml
vendored
@@ -1,20 +1,134 @@
|
||||
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
|
||||
name: Spell checking
|
||||
|
||||
# Comment management is handled through a secondary job, for details see:
|
||||
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
|
||||
#
|
||||
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
|
||||
# it needs `contents: write` in order to add a comment.
|
||||
#
|
||||
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
|
||||
# it needs `pull-requests: write` in order to manipulate those comments.
|
||||
|
||||
# Updating pull request branches is managed via comment handling.
|
||||
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
|
||||
#
|
||||
# These elements work together to make it happen:
|
||||
#
|
||||
# `on.issue_comment`
|
||||
# This event listens to comments by users asking to update the metadata.
|
||||
#
|
||||
# `jobs.update`
|
||||
# This job runs in response to an issue_comment and will push a new commit
|
||||
# to update the spelling metadata.
|
||||
#
|
||||
# `with.experimental_apply_changes_via_bot`
|
||||
# Tells the action to support and generate messages that enable it
|
||||
# to make a commit to update the spelling metadata.
|
||||
#
|
||||
# `with.ssh_key`
|
||||
# In order to trigger workflows when the commit is made, you can provide a
|
||||
# secret (typically, a write-enabled github deploy key).
|
||||
#
|
||||
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Spell checking
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
actions: read
|
||||
outputs:
|
||||
followup: ${{ steps.spelling.outputs.followup }}
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'"
|
||||
concurrency:
|
||||
group: spelling-${{ github.event.pull_request.number || github.ref }}
|
||||
# note: If you use only_check_changed_files, you do not want cancel-in-progress
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: checkout-merge
|
||||
if: "contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
ref: refs/pull/${{github.event.pull_request.number}}/merge
|
||||
- name: checkout
|
||||
if: "!contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2
|
||||
- uses: check-spelling/check-spelling@v0.0.19
|
||||
suppress_push_for_open_pull_request: 1
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
extra_dictionary_limit: 10
|
||||
extra_dictionaries:
|
||||
cspell:software-terms/src/software-terms.txt
|
||||
cspell:python/src/python/python-lib.txt
|
||||
cspell:node/node.txt
|
||||
cspell:cpp/src/stdlib-c.txt
|
||||
cspell:cpp/src/stdlib-cpp.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/src/compiler-msvc.txt
|
||||
cspell:python/src/common/extra.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:cpp/src/lang-keywords.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:python/src/python/python.txt
|
||||
cspell:css/css.txt
|
||||
cspell:cpp/src/stdlib-cmath.txt
|
||||
check_extra_dictionaries: ''
|
||||
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
# If your workflow isn't running on push, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
contents: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
# If you workflow isn't running on pull_request*, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
2
gitbranch.cmd
Normal file
2
gitbranch.cmd
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
git branch | D:\dev\private\OpenConsole\bin\x64\Debug\Scratch.exe --prefix "git checkout "
|
||||
@@ -562,7 +562,7 @@ bool TextBuffer::IncrementCircularBuffer(const bool inVtMode)
|
||||
// to the logical position 0 in the window (cursor coordinates and all other coordinates).
|
||||
if (_isActiveBuffer)
|
||||
{
|
||||
_renderer.TriggerCircling();
|
||||
_renderer.TriggerFlush(true);
|
||||
}
|
||||
|
||||
// Prune hyperlinks to delete obsolete references
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
case ShortcutAction::SetColorScheme:
|
||||
case ShortcutAction::AdjustOpacity:
|
||||
case ShortcutAction::SendInput:
|
||||
{
|
||||
_RunRestorePreviews();
|
||||
break;
|
||||
@@ -140,6 +141,27 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
}
|
||||
|
||||
void TerminalPage::_PreviewSendInput(const Settings::Model::SendInputArgs& args)
|
||||
{
|
||||
const auto backup = _restorePreviewFuncs.empty();
|
||||
|
||||
_ApplyToActiveControls([&](const auto& control) {
|
||||
// // Stash a copy of the original opacity.
|
||||
// auto originalOpacity{ control.BackgroundOpacity() };
|
||||
|
||||
// Apply the new opacity
|
||||
control.PreviewInput(args.Input());
|
||||
|
||||
if (backup)
|
||||
{
|
||||
_restorePreviewFuncs.emplace_back([=]() {
|
||||
// On dismiss:
|
||||
control.PreviewInput(L"");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Handler for the CommandPalette::PreviewAction event. The Command
|
||||
// Palette will raise this even when an action is selected, but _not_
|
||||
@@ -176,6 +198,11 @@ namespace winrt::TerminalApp::implementation
|
||||
_PreviewAdjustOpacity(args.ActionAndArgs().Args().try_as<AdjustOpacityArgs>());
|
||||
break;
|
||||
}
|
||||
case ShortcutAction::SendInput:
|
||||
{
|
||||
_PreviewSendInput(args.ActionAndArgs().Args().try_as<SendInputArgs>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// GH#9818 Other ideas for actions that could be preview-able:
|
||||
|
||||
@@ -236,13 +236,17 @@ namespace winrt::TerminalApp::implementation
|
||||
void CommandPalette::_selectedCommandChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
const auto currentlyVisible{ Visibility() == Visibility::Visible };
|
||||
|
||||
const auto selectedCommand = _filteredActionsView().SelectedItem();
|
||||
const auto filteredCommand{ selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>() };
|
||||
if (_currentMode == CommandPaletteMode::TabSwitchMode)
|
||||
{
|
||||
_switchToTab(filteredCommand);
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode && filteredCommand != nullptr)
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode &&
|
||||
filteredCommand != nullptr &&
|
||||
currentlyVisible)
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
{
|
||||
@@ -1047,7 +1051,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
std::copy(begin(commandsToFilter), end(commandsToFilter), std::back_inserter(actions));
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode || _currentMode == CommandPaletteMode::CommandlineMode)
|
||||
else if (_currentMode == CommandPaletteMode::TabSearchMode ||
|
||||
_currentMode == CommandPaletteMode::ActionMode ||
|
||||
_currentMode == CommandPaletteMode::CommandlineMode)
|
||||
{
|
||||
for (const auto& action : commandsToFilter)
|
||||
{
|
||||
@@ -1314,4 +1320,30 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
ApplicationState::SharedInstance().RecentCommands(single_threaded_vector(std::move(newRecentCommands)));
|
||||
}
|
||||
|
||||
void CommandPalette::PositionManually(Windows::Foundation::Point origin, Windows::Foundation::Size size)
|
||||
{
|
||||
Controls::Grid::SetRow(_backdrop(), 0);
|
||||
Controls::Grid::SetColumn(_backdrop(), 0);
|
||||
Controls::Grid::SetRowSpan(_backdrop(), 2);
|
||||
Controls::Grid::SetColumnSpan(_backdrop(), 3);
|
||||
|
||||
// Set thie Max* versions here, otherwise when there are few results,
|
||||
// the cmdpal will _still_ be 300x300 and filled with empty space
|
||||
_backdrop().MaxWidth(size.Width);
|
||||
_backdrop().MaxHeight(size.Height);
|
||||
|
||||
_backdrop().HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
_backdrop().VerticalAlignment(VerticalAlignment::Stretch);
|
||||
|
||||
// We can fake this. We're only using this method for the autocomplete
|
||||
// version of the cmdpal. Set the BG to acrylic.
|
||||
const auto colorControlStyle{ Resources().Lookup(winrt::box_value(L"CommandPaletteAcrylicBackground")).as<Windows::UI::Xaml::Style>() };
|
||||
_backdrop().Style(colorControlStyle);
|
||||
|
||||
Windows::UI::Xaml::Thickness margins{};
|
||||
margins.Left = origin.X;
|
||||
margins.Top = origin.Y;
|
||||
_backdrop().Margin(margins);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void EnableTabSwitcherMode(const uint32_t startIdx, Microsoft::Terminal::Settings::Model::TabSwitcherMode tabSwitcherMode);
|
||||
void EnableTabSearchMode();
|
||||
|
||||
void PositionManually(Windows::Foundation::Point origin, Windows::Foundation::Size size);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace TerminalApp
|
||||
void EnableTabSwitcherMode(UInt32 startIdx, Microsoft.Terminal.Settings.Model.TabSwitcherMode tabSwitcherMode);
|
||||
void EnableTabSearchMode();
|
||||
|
||||
void PositionManually(Windows.Foundation.Point origin, Windows.Foundation.Size size);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, TabBase> SwitchToTabRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, String> CommandLineExecutionRequested;
|
||||
|
||||
@@ -228,9 +228,21 @@
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Style x:Key="CommandPaletteBackground"
|
||||
<Color x:Key="CommandPaletteBackgroundColor">#333333</Color>
|
||||
<SolidColorBrush x:Key="CommandPaletteSolidBackgroundBrush"
|
||||
Color="{ThemeResource CommandPaletteBackgroundColor}" />
|
||||
<AcrylicBrush x:Key="CommandPaletteAcrylicBackgroundBrush"
|
||||
BackgroundSource="HostBackdrop"
|
||||
FallbackColor="{ThemeResource CommandPaletteBackgroundColor}"
|
||||
TintColor="{ThemeResource CommandPaletteBackgroundColor}"
|
||||
TintOpacity="0.5" />
|
||||
<Style x:Key="CommandPaletteSolidBackground"
|
||||
TargetType="Grid">
|
||||
<Setter Property="Background" Value="#333333" />
|
||||
<Setter Property="Background" Value="{ThemeResource CommandPaletteSolidBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="CommandPaletteAcrylicBackground"
|
||||
TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource CommandPaletteAcrylicBackgroundBrush}" />
|
||||
</Style>
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
@@ -291,9 +303,21 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Style x:Key="CommandPaletteBackground"
|
||||
<Color x:Key="CommandPaletteBackgroundColor">#CCCCCC</Color>
|
||||
<SolidColorBrush x:Key="CommandPaletteSolidBackgroundBrush"
|
||||
Color="{ThemeResource CommandPaletteBackgroundColor}" />
|
||||
<AcrylicBrush x:Key="CommandPaletteAcrylicBackgroundBrush"
|
||||
BackgroundSource="HostBackdrop"
|
||||
FallbackColor="{ThemeResource CommandPaletteBackgroundColor}"
|
||||
TintColor="{ThemeResource CommandPaletteBackgroundColor}"
|
||||
TintOpacity="0.5" />
|
||||
<Style x:Key="CommandPaletteSolidBackground"
|
||||
TargetType="Grid">
|
||||
<Setter Property="Background" Value="#CCCCCC" />
|
||||
<Setter Property="Background" Value="{ThemeResource CommandPaletteSolidBackgroundBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="CommandPaletteAcrylicBackground"
|
||||
TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource CommandPaletteAcrylicBackgroundBrush}" />
|
||||
</Style>
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
@@ -348,11 +372,14 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<Style x:Key="CommandPaletteBackground"
|
||||
<Style x:Key="CommandPaletteSolidBackground"
|
||||
TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource SystemColorWindowColor}" />
|
||||
</Style>
|
||||
|
||||
<StaticResource x:Key="CommandPaletteAcrylicBackground"
|
||||
ResourceKey="CommandPaletteSolidBackground" />
|
||||
|
||||
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border" />
|
||||
@@ -409,7 +436,7 @@
|
||||
Windows10version1903:Shadow="{StaticResource CommandPaletteShadow}"
|
||||
CornerRadius="{ThemeResource OverlayCornerRadius}"
|
||||
PointerPressed="_backdropPointerPressed"
|
||||
Style="{ThemeResource CommandPaletteBackground}">
|
||||
Style="{ThemeResource CommandPaletteSolidBackground}">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
|
||||
@@ -254,6 +254,17 @@ namespace winrt::TerminalApp::implementation
|
||||
CommandPalette().SwitchToTabRequested({ this, &TerminalPage::_OnSwitchToTabRequested });
|
||||
CommandPalette().PreviewAction({ this, &TerminalPage::_PreviewActionHandler });
|
||||
|
||||
AutoCompleteMenu().PositionManually(Windows::Foundation::Point{ 0, 0 }, Windows::Foundation::Size{ 200, 300 });
|
||||
AutoCompleteMenu().RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) {
|
||||
if (AutoCompleteMenu().Visibility() == Visibility::Collapsed)
|
||||
{
|
||||
AutoCompletePopup().IsOpen(false);
|
||||
_FocusActiveControl(nullptr, nullptr);
|
||||
}
|
||||
});
|
||||
AutoCompleteMenu().DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
AutoCompleteMenu().PreviewAction({ this, &TerminalPage::_PreviewActionHandler });
|
||||
|
||||
// Settings AllowDependentAnimations will affect whether animations are
|
||||
// enabled application-wide, so we don't need to check it each time we
|
||||
// want to create an animation.
|
||||
@@ -1281,7 +1292,13 @@ namespace winrt::TerminalApp::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible &&
|
||||
cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
if (const auto p = AutoCompleteMenu(); p.Visibility() == Visibility::Visible &&
|
||||
cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
@@ -1437,6 +1454,8 @@ namespace winrt::TerminalApp::implementation
|
||||
term.SetTaskbarProgress({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler });
|
||||
|
||||
term.ConnectionStateChanged({ get_weak(), &TerminalPage::_ConnectionStateChangedHandler });
|
||||
|
||||
term.MenuChanged({ get_weak(), &TerminalPage::_ControlMenuChangedHandler });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -3911,4 +3930,46 @@ namespace winrt::TerminalApp::implementation
|
||||
applicationState.DismissedMessages(std::move(messages));
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TerminalPage::_ControlMenuChangedHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
||||
auto control{ _GetActiveControl() };
|
||||
if (!control)
|
||||
co_return;
|
||||
|
||||
// May be able to fake this by not creating whole Commands for these
|
||||
// actions, instead just binding them at the cmdpal layer (like tab item
|
||||
// vs action item)
|
||||
auto entries = control.MenuEntries();
|
||||
auto commandsCollection = winrt::single_threaded_vector<Command>();
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
SendInputArgs args{ entry.Input };
|
||||
ActionAndArgs actionAndArgs{ ShortcutAction::SendInput, args };
|
||||
Command command{};
|
||||
command.ActionAndArgs(actionAndArgs);
|
||||
command.Name(entry.Name);
|
||||
|
||||
commandsCollection.Append(command);
|
||||
}
|
||||
|
||||
// CommandPalette has an internal margin of 8, so set to -4,-4 to position closer to the actual line
|
||||
AutoCompleteMenu().PositionManually(Windows::Foundation::Point{ -4, -4 }, Windows::Foundation::Size{ 300, 300 });
|
||||
|
||||
// CommandPalette().EnableCommandPaletteMode(CommandPaletteLaunchMode::Action);
|
||||
|
||||
const til::point cursorPos{ control.CursorPositionInDips() };
|
||||
const auto characterSize{ control.CharacterDimensions() };
|
||||
|
||||
// Position relative to the actual term control
|
||||
AutoCompletePopup().HorizontalOffset(cursorPos.x);
|
||||
AutoCompletePopup().VerticalOffset(cursorPos.y + characterSize.Height);
|
||||
|
||||
AutoCompletePopup().IsOpen(true);
|
||||
// Make visible first, then set commands. Other way around and the list
|
||||
// doesn't actually update the first time (weird)
|
||||
AutoCompleteMenu().Visibility(commandsCollection.Size() > 0 ? Visibility::Visible : Visibility::Collapsed);
|
||||
AutoCompleteMenu().SetCommands(commandsCollection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -410,6 +410,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _RunRestorePreviews();
|
||||
void _PreviewColorScheme(const Microsoft::Terminal::Settings::Model::SetColorSchemeArgs& args);
|
||||
void _PreviewAdjustOpacity(const Microsoft::Terminal::Settings::Model::AdjustOpacityArgs& args);
|
||||
void _PreviewSendInput(const Microsoft::Terminal::Settings::Model::SendInputArgs& args);
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
||||
std::vector<std::function<void()>> _restorePreviewFuncs{};
|
||||
|
||||
@@ -438,6 +439,8 @@ namespace winrt::TerminalApp::implementation
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
|
||||
winrt::fire_and_forget _ControlMenuChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
||||
@@ -168,6 +168,18 @@
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<Popup x:Name="AutoCompletePopup"
|
||||
HorizontalOffset="200"
|
||||
IsOpen="False"
|
||||
ShouldConstrainToRootBounds="False"
|
||||
VerticalOffset="200">
|
||||
<local:CommandPalette x:Name="AutoCompleteMenu"
|
||||
VerticalAlignment="Stretch"
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
</Popup>
|
||||
|
||||
<!--
|
||||
A TeachingTip with IsLightDismissEnabled="True" will immediately
|
||||
dismiss itself if the window is unfocused (In Xaml Islands). This is
|
||||
@@ -199,4 +211,5 @@
|
||||
</mux:TeachingTip.Content>
|
||||
</mux:TeachingTip>
|
||||
</Grid>
|
||||
|
||||
</Page>
|
||||
|
||||
@@ -108,6 +108,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this);
|
||||
_terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged);
|
||||
|
||||
auto pfnMenuChanged = std::bind(&ControlCore::_terminalMenuChanged, this);
|
||||
_terminal->MenuChangedCallback(pfnMenuChanged);
|
||||
|
||||
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
|
||||
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
|
||||
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
|
||||
@@ -190,6 +193,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
});
|
||||
|
||||
_updateMenu = std::make_shared<ThrottledFuncTrailing<>>(
|
||||
_dispatcher,
|
||||
UpdatePatternLocationsInterval,
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto core{ weakThis.get() }; !core->_IsClosing())
|
||||
{
|
||||
core->_MenuChangedHandlers(*core, nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
UpdateSettings(settings, unfocusedAppearance);
|
||||
}
|
||||
|
||||
@@ -1206,6 +1219,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_TaskbarProgressChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalMenuChanged()
|
||||
{
|
||||
_updateMenu->Run();
|
||||
// _MenuChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
bool ControlCore::HasSelection() const
|
||||
{
|
||||
return _terminal->IsSelectionActive();
|
||||
@@ -1695,4 +1714,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// transparency, or our acrylic, or our image.
|
||||
return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty();
|
||||
}
|
||||
|
||||
static Windows::Foundation::Collections::IVector<Control::MenuEntry> _internalMenuToWinRT(const std::vector<DispatchTypes::MenuEntry>& menu)
|
||||
{
|
||||
auto v = winrt::single_threaded_observable_vector<Control::MenuEntry>();
|
||||
for (const auto& entry : menu)
|
||||
{
|
||||
Control::MenuEntry e{};
|
||||
e.Name = winrt::hstring(entry._name);
|
||||
e.Comment = winrt::hstring(entry._comment);
|
||||
e.Input = winrt::hstring(entry._input);
|
||||
v.Append(e);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IVector<Control::MenuEntry> ControlCore::MenuEntries() const
|
||||
{
|
||||
return _internalMenuToWinRT(_terminal->GetMenu());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
int BufferHeight() const;
|
||||
|
||||
bool BracketedPasteEnabled() const noexcept;
|
||||
|
||||
Windows::Foundation::Collections::IVector<Control::MenuEntry> MenuEntries() const;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ITerminalInput
|
||||
@@ -192,6 +195,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TYPED_EVENT(TransparencyChanged, IInspectable, Control::TransparencyChangedEventArgs);
|
||||
TYPED_EVENT(ReceivedOutput, IInspectable, IInspectable);
|
||||
TYPED_EVENT(FoundMatch, IInspectable, Control::FoundResultsArgs);
|
||||
TYPED_EVENT(MenuChanged, IInspectable, IInspectable);
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
@@ -239,6 +243,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
|
||||
std::shared_ptr<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>> _updateScrollBar;
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _updateMenu;
|
||||
|
||||
winrt::fire_and_forget _asyncCloseConnection();
|
||||
|
||||
@@ -259,6 +264,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const int bufferSize);
|
||||
void _terminalCursorPositionChanged();
|
||||
void _terminalTaskbarProgressChanged();
|
||||
void _terminalMenuChanged();
|
||||
#pragma endregion
|
||||
|
||||
#pragma region RendererCallbacks
|
||||
|
||||
@@ -120,6 +120,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, TransparencyChangedEventArgs> TransparencyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReceivedOutput;
|
||||
event Windows.Foundation.TypedEventHandler<Object, FoundResultsArgs> FoundMatch;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> MenuChanged;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
|
||||
namespace Microsoft.Terminal.Control
|
||||
{
|
||||
|
||||
struct MenuEntry
|
||||
{
|
||||
String Name;
|
||||
String Comment;
|
||||
String Input;
|
||||
};
|
||||
|
||||
// These are properties of the TerminalCore that should be queryable by the
|
||||
// rest of the app.
|
||||
interface ICoreState
|
||||
@@ -24,5 +32,8 @@ namespace Microsoft.Terminal.Control
|
||||
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
|
||||
|
||||
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
|
||||
|
||||
IVector<MenuEntry> MenuEntries { get; };
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -470,4 +470,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void TSFInputControl::_formatUpdatingHandler(CoreTextEditContext sender, CoreTextFormatUpdatingEventArgs const& /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
void TSFInputControl::ManuallyDisplayText(const winrt::hstring& text)
|
||||
{
|
||||
_focused = !text.empty();
|
||||
Canvas().Visibility(text.empty() ? Visibility::Collapsed : Visibility::Visible);
|
||||
|
||||
_inputBuffer.clear();
|
||||
// _editContext.NotifyFocusLeave();
|
||||
_activeTextStart = 0;
|
||||
_inComposition = false;
|
||||
|
||||
TextBlock().Text(text);
|
||||
TextBlock().UpdateLayout();
|
||||
TryRedrawCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ClearBuffer();
|
||||
void TryRedrawCanvas();
|
||||
|
||||
void ManuallyDisplayText(const winrt::hstring& text);
|
||||
|
||||
void Close();
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace Microsoft.Terminal.Control
|
||||
void ClearBuffer();
|
||||
void TryRedrawCanvas();
|
||||
|
||||
void ManuallyDisplayText(String text);
|
||||
|
||||
|
||||
void Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +322,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - <none>
|
||||
void TermControl::SendInput(const winrt::hstring& wstr)
|
||||
{
|
||||
PreviewInput(L"");
|
||||
_core.SendInput(wstr);
|
||||
}
|
||||
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
|
||||
@@ -2777,4 +2778,40 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
Microsoft::Terminal::Core::Point TermControl::CursorPositionInDips()
|
||||
{
|
||||
// const auto cursorPosition{ _core.CursorPosition() };
|
||||
|
||||
const til::point cursorPos{ _core.CursorPosition() };
|
||||
|
||||
const til::size fontSize{ til::math::flooring, CharacterDimensions() };
|
||||
|
||||
// Convert text buffer cursor position to client coordinate position
|
||||
// within the window. This point is in _pixels_
|
||||
const til::point clientCursorPos{ cursorPos * fontSize };
|
||||
|
||||
// Get scale factor for view
|
||||
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
|
||||
const til::point clientCursorInDips{ til::math::flooring, clientCursorPos.x / scaleFactor, clientCursorPos.y / scaleFactor };
|
||||
|
||||
// + SwapChainPanel().Margin().Top
|
||||
auto padding{ GetPadding() };
|
||||
til::point relativeToOrigin{ til::math::flooring,
|
||||
clientCursorInDips.x + padding.Left,
|
||||
clientCursorInDips.y + padding.Top
|
||||
};
|
||||
return relativeToOrigin.to_core_point();
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IVector<Control::MenuEntry> TermControl::MenuEntries() const
|
||||
{
|
||||
return _core.MenuEntries();
|
||||
}
|
||||
|
||||
void TermControl::PreviewInput(const winrt::hstring& text)
|
||||
{
|
||||
TSFInputControl().ManuallyDisplayText(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Windows::Foundation::Size CharacterDimensions() const;
|
||||
Windows::Foundation::Size MinimumSize();
|
||||
float SnapDimensionToGrid(const bool widthOrHeight, const float dimension);
|
||||
Microsoft::Terminal::Core::Point CursorPositionInDips();
|
||||
void PreviewInput(const winrt::hstring& text);
|
||||
|
||||
#pragma region ICoreState
|
||||
const uint64_t TaskbarState() const noexcept;
|
||||
@@ -59,6 +61,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool BracketedPasteEnabled() const noexcept;
|
||||
|
||||
double BackgroundOpacity() const;
|
||||
|
||||
Windows::Foundation::Collections::IVector<Control::MenuEntry> MenuEntries() const;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void ScrollViewport(int viewTop);
|
||||
@@ -121,6 +126,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(MenuChanged , IInspectable, IInspectable, _core, MenuChanged);
|
||||
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> MenuChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, Windows.UI.Xaml.RoutedEventArgs> Initialized;
|
||||
// This is an event handler forwarder for the underlying connection.
|
||||
@@ -81,5 +82,9 @@ namespace Microsoft.Terminal.Control
|
||||
// opacity set by the settings should call this instead.
|
||||
Double BackgroundOpacity { get; };
|
||||
|
||||
Microsoft.Terminal.Core.Point CursorPositionInDips { get; };
|
||||
|
||||
void PreviewInput(String text);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,12 @@ namespace Microsoft::Terminal::Core
|
||||
virtual void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) = 0;
|
||||
virtual void PopGraphicsRendition() = 0;
|
||||
|
||||
virtual void UseAlternateScreenBuffer() = 0;
|
||||
virtual void UseMainScreenBuffer() = 0;
|
||||
|
||||
virtual void ClearMenu() = 0;
|
||||
virtual void AddToMenu(const Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry& menu) = 0;
|
||||
|
||||
protected:
|
||||
ITerminalApi() = default;
|
||||
};
|
||||
|
||||
@@ -40,6 +40,7 @@ Terminal::Terminal() :
|
||||
_mutableViewport{ Viewport::Empty() },
|
||||
_title{},
|
||||
_pfnWriteInput{ nullptr },
|
||||
_altBuffer{ nullptr },
|
||||
_scrollOffset{ 0 },
|
||||
_snapOnInput{ true },
|
||||
_altGrAliasing{ true },
|
||||
@@ -85,7 +86,7 @@ void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, Renderer& rende
|
||||
Utils::ClampToShortMax(viewportSize.Y + scrollbackLines, 1) };
|
||||
const TextAttribute attr{};
|
||||
const UINT cursorSize = 12;
|
||||
_buffer = std::make_unique<TextBuffer>(bufferSize, attr, cursorSize, true, renderer);
|
||||
_mainBuffer = std::make_unique<TextBuffer>(bufferSize, attr, cursorSize, true, renderer);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -147,15 +148,17 @@ void Terminal::UpdateSettings(ICoreSettings settings)
|
||||
// size is smaller than where the mutable viewport currently is, we'll want
|
||||
// to make sure to rotate the buffer contents upwards, so the mutable viewport
|
||||
// remains at the bottom of the buffer.
|
||||
if (_buffer)
|
||||
|
||||
// Regenerate the pattern tree for the new buffer size
|
||||
if (_mainBuffer)
|
||||
{
|
||||
// Clear the patterns first
|
||||
_buffer->ClearPatternRecognizers();
|
||||
_mainBuffer->ClearPatternRecognizers();
|
||||
if (settings.DetectURLs())
|
||||
{
|
||||
// Add regex pattern recognizers to the buffer
|
||||
// For now, we only add the URI regex pattern
|
||||
_hyperlinkPatternId = _buffer->AddPatternRecognizer(linkPattern);
|
||||
_hyperlinkPatternId = _mainBuffer->AddPatternRecognizer(linkPattern);
|
||||
UpdatePatternsUnderLock();
|
||||
}
|
||||
else
|
||||
@@ -213,9 +216,12 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_buffer)
|
||||
// We're checking if the main buffer exists here, but then setting the
|
||||
// appearance of the active one. If the main buffer exists, then at least
|
||||
// one buffer exists and _activeBuffer() will work
|
||||
if (_mainBuffer)
|
||||
{
|
||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
|
||||
_activeBuffer().GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
|
||||
}
|
||||
|
||||
_defaultCursorShape = cursorShape;
|
||||
@@ -231,12 +237,38 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
// appropriate HRESULT for failing to resize.
|
||||
[[nodiscard]] HRESULT Terminal::UserResize(const COORD viewportSize) noexcept
|
||||
{
|
||||
const auto oldDimensions = _mutableViewport.Dimensions();
|
||||
const auto oldDimensions = _GetMutableViewport().Dimensions();
|
||||
if (viewportSize == oldDimensions)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Shortcut: if we're in the alt buffer, just resize the
|
||||
// alt buffer and put off resizing the main buffer till we switch back. Fortunately, this is easy. We don't need to
|
||||
// worry about the viewport and scrollback at all! The alt buffer never has
|
||||
// any scrollback, so we just need to resize it and presto, we're done.
|
||||
if (_inAltBuffer())
|
||||
{
|
||||
// stash this resize for the future.
|
||||
_deferredResize = til::size{ viewportSize };
|
||||
|
||||
_altBuffer->GetCursor().StartDeferDrawing();
|
||||
// we're capturing `this` here because when we exit, we want to EndDefer on the (newly created) active buffer.
|
||||
auto endDefer = wil::scope_exit([this]() noexcept { _altBuffer->GetCursor().EndDeferDrawing(); });
|
||||
|
||||
// GH#3494: We don't need to reflow the alt buffer. Apps that use the
|
||||
// alt buffer will redraw themselves. This prevents graphical artifacts.
|
||||
//
|
||||
// This is consistent with VTE
|
||||
RETURN_IF_FAILED(_altBuffer->ResizeTraditional(viewportSize));
|
||||
|
||||
// Since the _mutableViewport is no longer the size of the actual
|
||||
// viewport, then update our _altBufferSize tracker we're using to help
|
||||
// us out here.
|
||||
_altBufferSize = til::size{ viewportSize };
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const auto dx = ::base::ClampSub(viewportSize.X, oldDimensions.X);
|
||||
const short newBufferHeight = ::base::ClampAdd(viewportSize.Y, _scrollbackLines);
|
||||
|
||||
@@ -252,9 +284,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
const bool originalOffsetWasZero = _scrollOffset == 0;
|
||||
|
||||
// skip any drawing updates that might occur until we swap _buffer with the new buffer or if we exit early.
|
||||
_buffer->GetCursor().StartDeferDrawing();
|
||||
// we're capturing _buffer by reference here because when we exit, we want to EndDefer on the current active buffer.
|
||||
auto endDefer = wil::scope_exit([&]() noexcept { _buffer->GetCursor().EndDeferDrawing(); });
|
||||
_mainBuffer->GetCursor().StartDeferDrawing();
|
||||
// we're capturing `this` here because when we exit, we want to EndDefer on the (newly created) active buffer.
|
||||
auto endDefer = wil::scope_exit([this]() noexcept { _mainBuffer->GetCursor().EndDeferDrawing(); });
|
||||
|
||||
// First allocate a new text buffer to take the place of the current one.
|
||||
std::unique_ptr<TextBuffer> newTextBuffer;
|
||||
@@ -265,13 +297,14 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
// but after the resize, we'll want to make sure that the new buffer's
|
||||
// current attributes (the ones used for printing new text) match the
|
||||
// old buffer's.
|
||||
const auto oldBufferAttributes = _buffer->GetCurrentAttributes();
|
||||
const auto oldBufferAttributes = _mainBuffer->GetCurrentAttributes();
|
||||
newTextBuffer = std::make_unique<TextBuffer>(bufferSize,
|
||||
TextAttribute{},
|
||||
0, // temporarily set size to 0 so it won't render.
|
||||
_buffer->IsActiveBuffer(),
|
||||
_buffer->GetRenderer());
|
||||
_mainBuffer->IsActiveBuffer(),
|
||||
_mainBuffer->GetRenderer());
|
||||
|
||||
// start defer drawing on the new buffer
|
||||
newTextBuffer->GetCursor().StartDeferDrawing();
|
||||
|
||||
// Build a PositionInformation to track the position of both the top of
|
||||
@@ -289,7 +322,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
oldRows.visibleViewportTop = newVisibleTop;
|
||||
|
||||
const std::optional<short> oldViewStart{ oldViewportTop };
|
||||
RETURN_IF_FAILED(TextBuffer::Reflow(*_buffer.get(),
|
||||
RETURN_IF_FAILED(TextBuffer::Reflow(*_mainBuffer.get(),
|
||||
*newTextBuffer.get(),
|
||||
_mutableViewport,
|
||||
{ oldRows }));
|
||||
@@ -405,7 +438,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
|
||||
_mutableViewport = Viewport::FromDimensions({ 0, proposedTop }, viewportSize);
|
||||
|
||||
_buffer.swap(newTextBuffer);
|
||||
_mainBuffer.swap(newTextBuffer);
|
||||
|
||||
// GH#3494: Maintain scrollbar position during resize
|
||||
// Make sure that we don't scroll past the mutableViewport at the bottom of the buffer
|
||||
@@ -420,7 +453,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
// GH#5029 - make sure to InvalidateAll here, so that we'll paint the entire visible viewport.
|
||||
try
|
||||
{
|
||||
_buffer->TriggerRedrawAll();
|
||||
_activeBuffer().TriggerRedrawAll();
|
||||
}
|
||||
CATCH_LOG();
|
||||
_NotifyScrollEvent();
|
||||
@@ -432,7 +465,7 @@ void Terminal::Write(std::wstring_view stringView)
|
||||
{
|
||||
auto lock = LockForWriting();
|
||||
|
||||
auto& cursor = _buffer->GetCursor();
|
||||
auto& cursor = _activeBuffer().GetCursor();
|
||||
const til::point cursorPosBefore{ cursor.GetPosition() };
|
||||
|
||||
_stateMachine->ProcessString(stringView);
|
||||
@@ -502,10 +535,10 @@ bool Terminal::IsTrackingMouseInput() const noexcept
|
||||
// - The position
|
||||
std::wstring Terminal::GetHyperlinkAtPosition(const COORD position)
|
||||
{
|
||||
auto attr = _buffer->GetCellDataAt(_ConvertToBufferCell(position))->TextAttr();
|
||||
auto attr = _activeBuffer().GetCellDataAt(_ConvertToBufferCell(position))->TextAttr();
|
||||
if (attr.IsHyperlink())
|
||||
{
|
||||
auto uri = _buffer->GetHyperlinkUriFromId(attr.GetHyperlinkId());
|
||||
auto uri = _activeBuffer().GetHyperlinkUriFromId(attr.GetHyperlinkId());
|
||||
return uri;
|
||||
}
|
||||
// also look through our known pattern locations in our pattern interval tree
|
||||
@@ -516,8 +549,8 @@ std::wstring Terminal::GetHyperlinkAtPosition(const COORD position)
|
||||
const auto end = result->stop;
|
||||
std::wstring uri;
|
||||
|
||||
const auto startIter = _buffer->GetCellDataAt(_ConvertToBufferCell(start.to_win32_coord()));
|
||||
const auto endIter = _buffer->GetCellDataAt(_ConvertToBufferCell(end.to_win32_coord()));
|
||||
const auto startIter = _activeBuffer().GetCellDataAt(_ConvertToBufferCell(start.to_win32_coord()));
|
||||
const auto endIter = _activeBuffer().GetCellDataAt(_ConvertToBufferCell(end.to_win32_coord()));
|
||||
for (auto iter = startIter; iter != endIter; ++iter)
|
||||
{
|
||||
uri += iter->Chars();
|
||||
@@ -535,7 +568,7 @@ std::wstring Terminal::GetHyperlinkAtPosition(const COORD position)
|
||||
// - The hyperlink ID
|
||||
uint16_t Terminal::GetHyperlinkIdAtPosition(const COORD position)
|
||||
{
|
||||
return _buffer->GetCellDataAt(_ConvertToBufferCell(position))->TextAttr().GetHyperlinkId();
|
||||
return _activeBuffer().GetCellDataAt(_ConvertToBufferCell(position))->TextAttr().GetHyperlinkId();
|
||||
}
|
||||
|
||||
// Method description:
|
||||
@@ -732,26 +765,26 @@ void Terminal::_InvalidateFromCoords(const COORD start, const COORD end)
|
||||
if (start.Y == end.Y)
|
||||
{
|
||||
SMALL_RECT region{ start.X, start.Y, end.X, end.Y };
|
||||
_buffer->TriggerRedraw(Viewport::FromInclusive(region));
|
||||
_activeBuffer().TriggerRedraw(Viewport::FromInclusive(region));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto rowSize = gsl::narrow<SHORT>(_buffer->GetRowByOffset(0).size());
|
||||
const auto rowSize = gsl::narrow<SHORT>(_activeBuffer().GetRowByOffset(0).size());
|
||||
|
||||
// invalidate the first line
|
||||
SMALL_RECT region{ start.X, start.Y, gsl::narrow<short>(rowSize - 1), gsl::narrow<short>(start.Y) };
|
||||
_buffer->TriggerRedraw(Viewport::FromInclusive(region));
|
||||
_activeBuffer().TriggerRedraw(Viewport::FromInclusive(region));
|
||||
|
||||
if ((end.Y - start.Y) > 1)
|
||||
{
|
||||
// invalidate the lines in between the first and last line
|
||||
region = SMALL_RECT{ 0, start.Y + 1, gsl::narrow<short>(rowSize - 1), gsl::narrow<short>(end.Y - 1) };
|
||||
_buffer->TriggerRedraw(Viewport::FromInclusive(region));
|
||||
_activeBuffer().TriggerRedraw(Viewport::FromInclusive(region));
|
||||
}
|
||||
|
||||
// invalidate the last line
|
||||
region = SMALL_RECT{ 0, end.Y, end.X, end.Y };
|
||||
_buffer->TriggerRedraw(Viewport::FromInclusive(region));
|
||||
_activeBuffer().TriggerRedraw(Viewport::FromInclusive(region));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -897,41 +930,52 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept
|
||||
|
||||
Viewport Terminal::_GetMutableViewport() const noexcept
|
||||
{
|
||||
return _mutableViewport;
|
||||
// GH#3493: if we're in the alt buffer, then it's possible that the mutable
|
||||
// viewport's size hasn't been updated yet. In that case, use the
|
||||
// temporarily stashed _altBufferSize instead.
|
||||
return _inAltBuffer() ? Viewport::FromDimensions(_altBufferSize.to_win32_coord()) :
|
||||
_mutableViewport;
|
||||
}
|
||||
|
||||
short Terminal::GetBufferHeight() const noexcept
|
||||
{
|
||||
return _mutableViewport.BottomExclusive();
|
||||
return _GetMutableViewport().BottomExclusive();
|
||||
}
|
||||
|
||||
// ViewStartIndex is also the length of the scrollback
|
||||
int Terminal::ViewStartIndex() const noexcept
|
||||
{
|
||||
return _mutableViewport.Top();
|
||||
return _inAltBuffer() ? 0 : _mutableViewport.Top();
|
||||
}
|
||||
|
||||
int Terminal::ViewEndIndex() const noexcept
|
||||
{
|
||||
return _mutableViewport.BottomInclusive();
|
||||
return _inAltBuffer() ? _altBufferSize.height : _mutableViewport.BottomInclusive();
|
||||
}
|
||||
|
||||
// _VisibleStartIndex is the first visible line of the buffer
|
||||
int Terminal::_VisibleStartIndex() const noexcept
|
||||
{
|
||||
return std::max(0, ViewStartIndex() - _scrollOffset);
|
||||
return _inAltBuffer() ? ViewStartIndex() :
|
||||
std::max(0, ViewStartIndex() - _scrollOffset);
|
||||
}
|
||||
|
||||
int Terminal::_VisibleEndIndex() const noexcept
|
||||
{
|
||||
return std::max(0, ViewEndIndex() - _scrollOffset);
|
||||
return _inAltBuffer() ? ViewEndIndex() :
|
||||
std::max(0, ViewEndIndex() - _scrollOffset);
|
||||
}
|
||||
|
||||
Viewport Terminal::_GetVisibleViewport() const noexcept
|
||||
{
|
||||
// GH#3493: if we're in the alt buffer, then it's possible that the mutable
|
||||
// viewport's size hasn't been updated yet. In that case, use the
|
||||
// temporarily stashed _altBufferSize instead.
|
||||
const COORD origin{ 0, gsl::narrow<short>(_VisibleStartIndex()) };
|
||||
const COORD size{ _inAltBuffer() ? _altBufferSize.to_win32_coord() :
|
||||
_mutableViewport.Dimensions() };
|
||||
return Viewport::FromDimensions(origin,
|
||||
_mutableViewport.Dimensions());
|
||||
size);
|
||||
}
|
||||
|
||||
// Writes a string of text to the buffer, then moves the cursor (and viewport)
|
||||
@@ -944,7 +988,7 @@ Viewport Terminal::_GetVisibleViewport() const noexcept
|
||||
// I had to make a bunch of hacks to get Japanese and emoji to work-ish.
|
||||
void Terminal::_WriteBuffer(const std::wstring_view& stringView)
|
||||
{
|
||||
auto& cursor = _buffer->GetCursor();
|
||||
auto& cursor = _activeBuffer().GetCursor();
|
||||
|
||||
// Defer the cursor drawing while we are iterating the string, for a better performance.
|
||||
// We can not waste time displaying a cursor event when we know more text is coming right behind it.
|
||||
@@ -963,8 +1007,8 @@ void Terminal::_WriteBuffer(const std::wstring_view& stringView)
|
||||
// from the stringView to form a single code point.
|
||||
const auto isSurrogate = wch >= 0xD800 && wch <= 0xDFFF;
|
||||
const auto view = stringView.substr(i, isSurrogate ? 2 : 1);
|
||||
const OutputCellIterator it{ view, _buffer->GetCurrentAttributes() };
|
||||
const auto end = _buffer->Write(it);
|
||||
const OutputCellIterator it{ view, _activeBuffer().GetCurrentAttributes() };
|
||||
const auto end = _activeBuffer().Write(it);
|
||||
const auto cellDistance = end.GetCellDistance(it);
|
||||
const auto inputDistance = end.GetInputDistance(it);
|
||||
|
||||
@@ -1006,7 +1050,7 @@ void Terminal::_WriteBuffer(const std::wstring_view& stringView)
|
||||
// Notify UIA of new text.
|
||||
// It's important to do this here instead of in TextBuffer, because here you have access to the entire line of text,
|
||||
// whereas TextBuffer writes it one character at a time via the OutputCellIterator.
|
||||
_buffer->TriggerNewTextNotification(stringView);
|
||||
_activeBuffer().TriggerNewTextNotification(stringView);
|
||||
|
||||
cursor.EndDeferDrawing();
|
||||
}
|
||||
@@ -1015,8 +1059,8 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
{
|
||||
#pragma warning(suppress : 26496) // cpp core checks wants this const but it's modified below.
|
||||
auto proposedCursorPosition = proposedPosition;
|
||||
auto& cursor = _buffer->GetCursor();
|
||||
const Viewport bufferSize = _buffer->GetSize();
|
||||
auto& cursor = _activeBuffer().GetCursor();
|
||||
const Viewport bufferSize = _activeBuffer().GetSize();
|
||||
|
||||
// If we're about to scroll past the bottom of the buffer, instead cycle the
|
||||
// buffer.
|
||||
@@ -1026,7 +1070,7 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
{
|
||||
for (auto dy = 0; dy < newRows; dy++)
|
||||
{
|
||||
_buffer->IncrementCircularBuffer();
|
||||
_activeBuffer().IncrementCircularBuffer();
|
||||
proposedCursorPosition.Y--;
|
||||
rowsPushedOffTopOfBuffer++;
|
||||
|
||||
@@ -1069,7 +1113,8 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
if (scrollAmount > 0)
|
||||
{
|
||||
const auto newViewTop = std::max(0, proposedCursorPosition.Y - (_mutableViewport.Height() - 1));
|
||||
if (newViewTop != _mutableViewport.Top())
|
||||
// In the alt buffer, we never need to adjust _mutableViewport, which is the viewport of the main buffer.
|
||||
if (!_inAltBuffer() && newViewTop != _mutableViewport.Top())
|
||||
{
|
||||
_mutableViewport = Viewport::FromDimensions({ 0, gsl::narrow<short>(newViewTop) },
|
||||
_mutableViewport.Dimensions());
|
||||
@@ -1079,7 +1124,7 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
|
||||
// If the viewport moved, or we circled the buffer, we might need to update
|
||||
// our _scrollOffset
|
||||
if (updatedViewport || newRows != 0)
|
||||
if (!_inAltBuffer() && (updatedViewport || newRows != 0))
|
||||
{
|
||||
const auto oldScrollOffset = _scrollOffset;
|
||||
|
||||
@@ -1093,7 +1138,7 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
// Clamp the range to make sure that we don't scroll way off the top of the buffer
|
||||
_scrollOffset = std::clamp(_scrollOffset,
|
||||
0,
|
||||
_buffer->GetSize().Height() - _mutableViewport.Height());
|
||||
_activeBuffer().GetSize().Height() - _mutableViewport.Height());
|
||||
|
||||
// If the new scroll offset is different, then we'll still want to raise a scroll event
|
||||
updatedViewport = updatedViewport || (oldScrollOffset != _scrollOffset);
|
||||
@@ -1111,12 +1156,17 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
// That didn't change the viewport and therefore the TriggerScroll(void)
|
||||
// method can't detect the delta on its own.
|
||||
COORD delta{ 0, gsl::narrow_cast<short>(-rowsPushedOffTopOfBuffer) };
|
||||
_buffer->TriggerScroll(delta);
|
||||
_activeBuffer().TriggerScroll(delta);
|
||||
}
|
||||
}
|
||||
|
||||
void Terminal::UserScrollViewport(const int viewTop)
|
||||
{
|
||||
if (_inAltBuffer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we're going to modify state here that the renderer could be reading.
|
||||
auto lock = LockForWriting();
|
||||
|
||||
@@ -1130,7 +1180,7 @@ void Terminal::UserScrollViewport(const int viewTop)
|
||||
// We can use the void variant of TriggerScroll here because
|
||||
// we adjusted the viewport so it can detect the difference
|
||||
// from the previous frame drawn.
|
||||
_buffer->TriggerScroll();
|
||||
_activeBuffer().TriggerScroll();
|
||||
}
|
||||
|
||||
int Terminal::GetScrollOffset() noexcept
|
||||
@@ -1218,6 +1268,11 @@ void Microsoft::Terminal::Core::Terminal::TaskbarProgressChangedCallback(std::fu
|
||||
_pfnTaskbarProgressChanged.swap(pfn);
|
||||
}
|
||||
|
||||
void Microsoft::Terminal::Core::Terminal::MenuChangedCallback(std::function<void()> pfn) noexcept
|
||||
{
|
||||
_pfnMenuChanged.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the cursor to be currently on. On/Off is tracked independently of
|
||||
// cursor visibility (hidden/visible). On/off is controlled by the cursor
|
||||
@@ -1229,12 +1284,12 @@ void Microsoft::Terminal::Core::Terminal::TaskbarProgressChangedCallback(std::fu
|
||||
void Terminal::SetCursorOn(const bool isOn)
|
||||
{
|
||||
auto lock = LockForWriting();
|
||||
_buffer->GetCursor().SetIsOn(isOn);
|
||||
_activeBuffer().GetCursor().SetIsOn(isOn);
|
||||
}
|
||||
|
||||
bool Terminal::IsCursorBlinkingAllowed() const noexcept
|
||||
{
|
||||
const auto& cursor = _buffer->GetCursor();
|
||||
const auto& cursor = _activeBuffer().GetCursor();
|
||||
return cursor.IsBlinkingAllowed();
|
||||
}
|
||||
|
||||
@@ -1246,7 +1301,7 @@ bool Terminal::IsCursorBlinkingAllowed() const noexcept
|
||||
void Terminal::UpdatePatternsUnderLock() noexcept
|
||||
{
|
||||
auto oldTree = _patternIntervalTree;
|
||||
_patternIntervalTree = _buffer->GetPatterns(_VisibleStartIndex(), _VisibleEndIndex());
|
||||
_patternIntervalTree = _activeBuffer().GetPatterns(_VisibleStartIndex(), _VisibleEndIndex());
|
||||
_InvalidatePatternTree(oldTree);
|
||||
_InvalidatePatternTree(_patternIntervalTree);
|
||||
}
|
||||
@@ -1343,3 +1398,18 @@ void Terminal::ApplyScheme(const Scheme& colorScheme)
|
||||
|
||||
_renderSettings.MakeAdjustedColorArray();
|
||||
}
|
||||
|
||||
bool Terminal::_inAltBuffer() const noexcept
|
||||
{
|
||||
return _altBuffer != nullptr;
|
||||
}
|
||||
|
||||
TextBuffer& Terminal::_activeBuffer() const noexcept
|
||||
{
|
||||
return _inAltBuffer() ? *_altBuffer : *_mainBuffer;
|
||||
}
|
||||
|
||||
const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry>& Terminal::GetMenu() const
|
||||
{
|
||||
return _menu;
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
|
||||
RenderSettings& GetRenderSettings() noexcept { return _renderSettings; };
|
||||
const RenderSettings& GetRenderSettings() const noexcept { return _renderSettings; };
|
||||
const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry>& GetMenu() const;
|
||||
|
||||
#pragma region ITerminalApi
|
||||
// These methods are defined in TerminalApi.cpp
|
||||
@@ -138,6 +139,13 @@ public:
|
||||
void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
|
||||
void PopGraphicsRendition() override;
|
||||
|
||||
void UseAlternateScreenBuffer() override;
|
||||
void UseMainScreenBuffer() override;
|
||||
|
||||
// void InvokeMenu(const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry>& menu) override;
|
||||
void ClearMenu();
|
||||
void AddToMenu(const Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry& menu);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ITerminalInput
|
||||
@@ -207,6 +215,7 @@ public:
|
||||
void SetCursorPositionChangedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetBackgroundCallback(std::function<void(const til::color)> pfn) noexcept;
|
||||
void TaskbarProgressChangedCallback(std::function<void()> pfn) noexcept;
|
||||
void MenuChangedCallback(std::function<void()> pfn) noexcept;
|
||||
|
||||
void SetCursorOn(const bool isOn);
|
||||
bool IsCursorBlinkingAllowed() const noexcept;
|
||||
@@ -274,6 +283,7 @@ private:
|
||||
std::function<void()> _pfnCursorPositionChanged;
|
||||
std::function<void(const std::optional<til::color>)> _pfnTabColorChanged;
|
||||
std::function<void()> _pfnTaskbarProgressChanged;
|
||||
std::function<void()> _pfnMenuChanged;
|
||||
|
||||
RenderSettings _renderSettings;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
@@ -321,10 +331,14 @@ private:
|
||||
|
||||
// TODO: These members are not shared by an alt-buffer. They should be
|
||||
// encapsulated, such that a Terminal can have both a main and alt buffer.
|
||||
std::unique_ptr<TextBuffer> _buffer;
|
||||
std::unique_ptr<TextBuffer> _mainBuffer;
|
||||
std::unique_ptr<TextBuffer> _altBuffer;
|
||||
Microsoft::Console::Types::Viewport _mutableViewport;
|
||||
SHORT _scrollbackLines;
|
||||
|
||||
til::size _altBufferSize;
|
||||
std::optional<til::size> _deferredResize{ std::nullopt };
|
||||
|
||||
// _scrollOffset is the number of lines above the viewport that are currently visible
|
||||
// If _scrollOffset is 0, then the visible region of the buffer is the viewport.
|
||||
int _scrollOffset;
|
||||
@@ -353,6 +367,8 @@ private:
|
||||
};
|
||||
std::optional<KeyEventCodes> _lastKeyEventCodes;
|
||||
|
||||
std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry> _menu;
|
||||
|
||||
static WORD _ScanCodeFromVirtualKey(const WORD vkey) noexcept;
|
||||
static WORD _VirtualKeyFromScanCode(const WORD scanCode) noexcept;
|
||||
static WORD _VirtualKeyFromCharacter(const wchar_t ch) noexcept;
|
||||
@@ -375,6 +391,9 @@ private:
|
||||
|
||||
void _NotifyTerminalCursorPositionChanged() noexcept;
|
||||
|
||||
bool _inAltBuffer() const noexcept;
|
||||
TextBuffer& _activeBuffer() const noexcept;
|
||||
|
||||
#pragma region TextSelection
|
||||
// These methods are defined in TerminalSelection.cpp
|
||||
std::vector<SMALL_RECT> _GetSelectionRects() const noexcept;
|
||||
|
||||
@@ -18,7 +18,7 @@ void Terminal::PrintString(std::wstring_view stringView)
|
||||
|
||||
TextAttribute Terminal::GetTextAttributes() const
|
||||
{
|
||||
return _buffer->GetCurrentAttributes();
|
||||
return _activeBuffer().GetCurrentAttributes();
|
||||
}
|
||||
|
||||
bool Terminal::ReturnResponse(std::wstring_view responseString)
|
||||
@@ -33,12 +33,12 @@ bool Terminal::ReturnResponse(std::wstring_view responseString)
|
||||
|
||||
void Terminal::SetTextAttributes(const TextAttribute& attrs)
|
||||
{
|
||||
_buffer->SetCurrentAttributes(attrs);
|
||||
_activeBuffer().SetCurrentAttributes(attrs);
|
||||
}
|
||||
|
||||
Viewport Terminal::GetBufferSize()
|
||||
{
|
||||
return _buffer->GetSize();
|
||||
return _activeBuffer().GetSize();
|
||||
}
|
||||
|
||||
void Terminal::SetCursorPosition(short x, short y)
|
||||
@@ -49,12 +49,12 @@ void Terminal::SetCursorPosition(short x, short y)
|
||||
const short absoluteY = viewOrigin.Y + y;
|
||||
COORD newPos{ absoluteX, absoluteY };
|
||||
viewport.Clamp(newPos);
|
||||
_buffer->GetCursor().SetPosition(newPos);
|
||||
_activeBuffer().GetCursor().SetPosition(newPos);
|
||||
}
|
||||
|
||||
COORD Terminal::GetCursorPosition()
|
||||
{
|
||||
const auto absoluteCursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto absoluteCursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
const auto viewport = _GetMutableViewport();
|
||||
const auto viewOrigin = viewport.Origin();
|
||||
const short relativeX = absoluteCursorPos.X - viewOrigin.X;
|
||||
@@ -73,11 +73,11 @@ COORD Terminal::GetCursorPosition()
|
||||
// - <none>
|
||||
void Terminal::CursorLineFeed(const bool withReturn)
|
||||
{
|
||||
auto cursorPos = _buffer->GetCursor().GetPosition();
|
||||
auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
|
||||
// since we explicitly just moved down a row, clear the wrap status on the
|
||||
// row we just came from
|
||||
_buffer->GetRowByOffset(cursorPos.Y).SetWrapForced(false);
|
||||
_activeBuffer().GetRowByOffset(cursorPos.Y).SetWrapForced(false);
|
||||
|
||||
cursorPos.Y++;
|
||||
if (withReturn)
|
||||
@@ -101,10 +101,12 @@ void Terminal::DeleteCharacter(const size_t count)
|
||||
{
|
||||
SHORT dist;
|
||||
THROW_IF_FAILED(SizeTToShort(count, &dist));
|
||||
const auto cursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
const auto copyToPos = cursorPos;
|
||||
const COORD copyFromPos{ cursorPos.X + dist, cursorPos.Y };
|
||||
const auto sourceWidth = _mutableViewport.RightExclusive() - copyFromPos.X;
|
||||
const auto viewport = _GetMutableViewport();
|
||||
|
||||
const auto sourceWidth = viewport.RightExclusive() - copyFromPos.X;
|
||||
SHORT width;
|
||||
THROW_IF_FAILED(UIntToShort(sourceWidth, &width));
|
||||
|
||||
@@ -121,8 +123,8 @@ void Terminal::DeleteCharacter(const size_t count)
|
||||
// Iterate over the source cell data and copy it over to the target
|
||||
do
|
||||
{
|
||||
const auto data = OutputCell(*(_buffer->GetCellDataAt(sourcePos)));
|
||||
_buffer->Write(OutputCellIterator({ &data, 1 }), targetPos);
|
||||
const auto data = OutputCell(*(_activeBuffer().GetCellDataAt(sourcePos)));
|
||||
_activeBuffer().Write(OutputCellIterator({ &data, 1 }), targetPos);
|
||||
} while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection));
|
||||
}
|
||||
|
||||
@@ -143,10 +145,11 @@ void Terminal::InsertCharacter(const size_t count)
|
||||
// TODO: Github issue #2163
|
||||
SHORT dist;
|
||||
THROW_IF_FAILED(SizeTToShort(count, &dist));
|
||||
const auto cursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
const auto copyFromPos = cursorPos;
|
||||
const COORD copyToPos{ cursorPos.X + dist, cursorPos.Y };
|
||||
const auto sourceWidth = _mutableViewport.RightExclusive() - copyFromPos.X;
|
||||
const auto viewport = _GetMutableViewport();
|
||||
const auto sourceWidth = viewport.RightExclusive() - copyFromPos.X;
|
||||
SHORT width;
|
||||
THROW_IF_FAILED(UIntToShort(sourceWidth, &width));
|
||||
|
||||
@@ -164,21 +167,21 @@ void Terminal::InsertCharacter(const size_t count)
|
||||
// Iterate over the source cell data and copy it over to the target
|
||||
do
|
||||
{
|
||||
const auto data = OutputCell(*(_buffer->GetCellDataAt(sourcePos)));
|
||||
_buffer->Write(OutputCellIterator({ &data, 1 }), targetPos);
|
||||
const auto data = OutputCell(*(_activeBuffer().GetCellDataAt(sourcePos)));
|
||||
_activeBuffer().Write(OutputCellIterator({ &data, 1 }), targetPos);
|
||||
} while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection));
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _buffer->GetCurrentAttributes(), dist);
|
||||
_buffer->Write(eraseIter, cursorPos);
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), dist);
|
||||
_activeBuffer().Write(eraseIter, cursorPos);
|
||||
}
|
||||
|
||||
void Terminal::EraseCharacters(const size_t numChars)
|
||||
{
|
||||
const auto absoluteCursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto absoluteCursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
const auto viewport = _GetMutableViewport();
|
||||
const short distanceToRight = viewport.RightExclusive() - absoluteCursorPos.X;
|
||||
const short fillLimit = std::min(static_cast<short>(numChars), distanceToRight);
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _buffer->GetCurrentAttributes(), fillLimit);
|
||||
_buffer->Write(eraseIter, absoluteCursorPos);
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), fillLimit);
|
||||
_activeBuffer().Write(eraseIter, absoluteCursorPos);
|
||||
}
|
||||
|
||||
// Method description:
|
||||
@@ -193,7 +196,7 @@ void Terminal::EraseCharacters(const size_t numChars)
|
||||
// - true if succeeded, false otherwise
|
||||
bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType)
|
||||
{
|
||||
const auto cursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
const auto viewport = _GetMutableViewport();
|
||||
COORD startPos = { 0 };
|
||||
startPos.Y = cursorPos.Y;
|
||||
@@ -218,10 +221,10 @@ bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::Dispatch
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _buffer->GetCurrentAttributes(), nlength);
|
||||
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), nlength);
|
||||
|
||||
// Explicitly turn off end-of-line wrap-flag-setting when erasing cells.
|
||||
_buffer->Write(eraseIter, startPos, false);
|
||||
_activeBuffer().Write(eraseIter, startPos, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -236,22 +239,33 @@ bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::Dispatch
|
||||
bool Terminal::EraseInDisplay(const DispatchTypes::EraseType eraseType)
|
||||
{
|
||||
// Store the relative cursor position so we can restore it later after we move the viewport
|
||||
const auto cursorPos = _buffer->GetCursor().GetPosition();
|
||||
const auto cursorPos = _activeBuffer().GetCursor().GetPosition();
|
||||
#pragma warning(suppress : 26496) // This is written by ConvertToOrigin, cpp core checks is wrong saying it should be const.
|
||||
auto relativeCursor = cursorPos;
|
||||
_mutableViewport.ConvertToOrigin(&relativeCursor);
|
||||
const auto viewport = _GetMutableViewport();
|
||||
|
||||
viewport.ConvertToOrigin(&relativeCursor);
|
||||
|
||||
// Initialize the new location of the viewport
|
||||
// the top and bottom parameters are determined by the eraseType
|
||||
SMALL_RECT newWin;
|
||||
newWin.Left = _mutableViewport.Left();
|
||||
newWin.Right = _mutableViewport.RightExclusive();
|
||||
newWin.Left = viewport.Left();
|
||||
newWin.Right = viewport.RightExclusive();
|
||||
|
||||
if (eraseType == DispatchTypes::EraseType::All)
|
||||
{
|
||||
// If we're in the alt buffer, take a shortcut. Just increment the buffer enough to cycle the whole thing out and start fresh. This
|
||||
if (_inAltBuffer())
|
||||
{
|
||||
for (auto i = 0; i < viewport.Height(); i++)
|
||||
{
|
||||
_activeBuffer().IncrementCircularBuffer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// In this case, we simply move the viewport down, effectively pushing whatever text was on the screen into the scrollback
|
||||
// and thus 'erasing' the text visible to the user
|
||||
const auto coordLastChar = _buffer->GetLastNonSpaceCharacter(_mutableViewport);
|
||||
const auto coordLastChar = _activeBuffer().GetLastNonSpaceCharacter(viewport);
|
||||
if (coordLastChar.X == 0 && coordLastChar.Y == 0)
|
||||
{
|
||||
// Nothing to clear, just return
|
||||
@@ -261,38 +275,38 @@ bool Terminal::EraseInDisplay(const DispatchTypes::EraseType eraseType)
|
||||
short sNewTop = coordLastChar.Y + 1;
|
||||
|
||||
// Increment the circular buffer only if the new location of the viewport would be 'below' the buffer
|
||||
const short delta = (sNewTop + _mutableViewport.Height()) - (_buffer->GetSize().Height());
|
||||
const short delta = (sNewTop + viewport.Height()) - (_activeBuffer().GetSize().Height());
|
||||
for (auto i = 0; i < delta; i++)
|
||||
{
|
||||
_buffer->IncrementCircularBuffer();
|
||||
_activeBuffer().IncrementCircularBuffer();
|
||||
sNewTop--;
|
||||
}
|
||||
|
||||
newWin.Top = sNewTop;
|
||||
newWin.Bottom = sNewTop + _mutableViewport.Height();
|
||||
newWin.Bottom = sNewTop + viewport.Height();
|
||||
}
|
||||
else if (eraseType == DispatchTypes::EraseType::Scrollback)
|
||||
{
|
||||
// We only want to erase the scrollback, and leave everything else on the screen as it is
|
||||
// so we grab the text in the viewport and rotate it up to the top of the buffer
|
||||
COORD scrollFromPos{ 0, 0 };
|
||||
_mutableViewport.ConvertFromOrigin(&scrollFromPos);
|
||||
_buffer->ScrollRows(scrollFromPos.Y, _mutableViewport.Height(), -scrollFromPos.Y);
|
||||
viewport.ConvertFromOrigin(&scrollFromPos);
|
||||
_activeBuffer().ScrollRows(scrollFromPos.Y, viewport.Height(), -scrollFromPos.Y);
|
||||
|
||||
// Since we only did a rotation, the text that was in the scrollback is now _below_ where we are going to move the viewport
|
||||
// and we have to make sure we erase that text
|
||||
const auto eraseStart = _mutableViewport.Height();
|
||||
const auto eraseEnd = _buffer->GetLastNonSpaceCharacter(_mutableViewport).Y;
|
||||
const auto eraseStart = viewport.Height();
|
||||
const auto eraseEnd = _activeBuffer().GetLastNonSpaceCharacter(viewport).Y;
|
||||
for (SHORT i = eraseStart; i <= eraseEnd; i++)
|
||||
{
|
||||
_buffer->GetRowByOffset(i).Reset(_buffer->GetCurrentAttributes());
|
||||
_activeBuffer().GetRowByOffset(i).Reset(_activeBuffer().GetCurrentAttributes());
|
||||
}
|
||||
|
||||
// Reset the scroll offset now because there's nothing for the user to 'scroll' to
|
||||
_scrollOffset = 0;
|
||||
|
||||
newWin.Top = 0;
|
||||
newWin.Bottom = _mutableViewport.Height();
|
||||
newWin.Bottom = viewport.Height();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,7 +364,7 @@ void Terminal::SetColorTableEntry(const size_t tableIndex, const COLORREF color)
|
||||
}
|
||||
|
||||
// Repaint everything - the colors might have changed
|
||||
_buffer->TriggerRedrawAll();
|
||||
_activeBuffer().TriggerRedrawAll();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -412,8 +426,8 @@ void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
|
||||
return;
|
||||
}
|
||||
|
||||
_buffer->GetCursor().SetType(finalCursorType);
|
||||
_buffer->GetCursor().SetBlinkingAllowed(shouldBlink);
|
||||
_activeBuffer().GetCursor().SetType(finalCursorType);
|
||||
_activeBuffer().GetCursor().SetBlinkingAllowed(shouldBlink);
|
||||
}
|
||||
|
||||
void Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled)
|
||||
@@ -426,7 +440,7 @@ void Terminal::SetRenderMode(const RenderSettings::Mode mode, const bool enabled
|
||||
_renderSettings.SetRenderMode(mode, enabled);
|
||||
|
||||
// Repaint everything - the colors will have changed
|
||||
_buffer->TriggerRedrawAll();
|
||||
_activeBuffer().TriggerRedrawAll();
|
||||
}
|
||||
|
||||
void Terminal::EnableXtermBracketedPasteMode(const bool enabled)
|
||||
@@ -447,12 +461,12 @@ bool Terminal::IsVtInputEnabled() const
|
||||
|
||||
void Terminal::SetCursorVisibility(const bool visible)
|
||||
{
|
||||
_buffer->GetCursor().SetIsVisible(visible);
|
||||
_activeBuffer().GetCursor().SetIsVisible(visible);
|
||||
}
|
||||
|
||||
void Terminal::EnableCursorBlinking(const bool enable)
|
||||
{
|
||||
_buffer->GetCursor().SetBlinkingAllowed(enable);
|
||||
_activeBuffer().GetCursor().SetBlinkingAllowed(enable);
|
||||
|
||||
// GH#2642 - From what we've gathered from other terminals, when blinking is
|
||||
// disabled, the cursor should remain On always, and have the visibility
|
||||
@@ -460,7 +474,7 @@ void Terminal::EnableCursorBlinking(const bool enable)
|
||||
// to disable blinking, the cursor stays stuck On. At this point, only the
|
||||
// cursor visibility property controls whether the user can see it or not.
|
||||
// (Yes, the cursor can be On and NOT Visible)
|
||||
_buffer->GetCursor().SetIsOn(true);
|
||||
_activeBuffer().GetCursor().SetIsOn(true);
|
||||
}
|
||||
|
||||
void Terminal::CopyToClipboard(std::wstring_view content)
|
||||
@@ -477,11 +491,11 @@ void Terminal::CopyToClipboard(std::wstring_view content)
|
||||
// - <none>
|
||||
void Terminal::AddHyperlink(std::wstring_view uri, std::wstring_view params)
|
||||
{
|
||||
auto attr = _buffer->GetCurrentAttributes();
|
||||
const auto id = _buffer->GetHyperlinkId(uri, params);
|
||||
auto attr = _activeBuffer().GetCurrentAttributes();
|
||||
const auto id = _activeBuffer().GetHyperlinkId(uri, params);
|
||||
attr.SetHyperlinkId(id);
|
||||
_buffer->SetCurrentAttributes(attr);
|
||||
_buffer->AddHyperlinkToMap(uri, id);
|
||||
_activeBuffer().SetCurrentAttributes(attr);
|
||||
_activeBuffer().AddHyperlinkToMap(uri, id);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -490,9 +504,9 @@ void Terminal::AddHyperlink(std::wstring_view uri, std::wstring_view params)
|
||||
// - <none>
|
||||
void Terminal::EndHyperlink()
|
||||
{
|
||||
auto attr = _buffer->GetCurrentAttributes();
|
||||
auto attr = _activeBuffer().GetCurrentAttributes();
|
||||
attr.SetHyperlinkId(0);
|
||||
_buffer->SetCurrentAttributes(attr);
|
||||
_activeBuffer().SetCurrentAttributes(attr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -565,7 +579,7 @@ std::wstring_view Terminal::GetWorkingDirectory()
|
||||
// - <none>
|
||||
void Terminal::PushGraphicsRendition(const VTParameters options)
|
||||
{
|
||||
_sgrStack.Push(_buffer->GetCurrentAttributes(), options);
|
||||
_sgrStack.Push(_activeBuffer().GetCurrentAttributes(), options);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -577,6 +591,149 @@ void Terminal::PushGraphicsRendition(const VTParameters options)
|
||||
// - <none>
|
||||
void Terminal::PopGraphicsRendition()
|
||||
{
|
||||
const TextAttribute current = _buffer->GetCurrentAttributes();
|
||||
_buffer->SetCurrentAttributes(_sgrStack.Pop(current));
|
||||
const TextAttribute current = _activeBuffer().GetCurrentAttributes();
|
||||
_activeBuffer().SetCurrentAttributes(_sgrStack.Pop(current));
|
||||
}
|
||||
|
||||
void Terminal::UseAlternateScreenBuffer()
|
||||
{
|
||||
// the new alt buffer is exactly the size of the viewport.
|
||||
_altBufferSize = til::size{ _mutableViewport.Dimensions() };
|
||||
|
||||
const auto cursorSize = _mainBuffer->GetCursor().GetSize();
|
||||
|
||||
// Create a new alt buffer
|
||||
_altBuffer = std::make_unique<TextBuffer>(_altBufferSize.to_win32_coord(),
|
||||
TextAttribute{},
|
||||
cursorSize,
|
||||
true,
|
||||
_mainBuffer->GetRenderer());
|
||||
_mainBuffer->SetAsActiveBuffer(false);
|
||||
|
||||
// Copy our cursor state to the new buffer's cursor
|
||||
{
|
||||
// Update the alt buffer's cursor style, visibility, and position to match our own.
|
||||
auto& myCursor = _mainBuffer->GetCursor();
|
||||
auto& tgtCursor = _altBuffer->GetCursor();
|
||||
tgtCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
|
||||
tgtCursor.SetIsVisible(myCursor.IsVisible());
|
||||
tgtCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
||||
|
||||
// The new position should match the viewport-relative position of the main buffer.
|
||||
auto tgtCursorPos = myCursor.GetPosition();
|
||||
tgtCursorPos.Y -= _mutableViewport.Top();
|
||||
tgtCursor.SetPosition(tgtCursorPos);
|
||||
}
|
||||
|
||||
// update all the hyperlinks on the screen
|
||||
UpdatePatternsUnderLock();
|
||||
|
||||
// GH#3321: Make sure we let the TerminalInput know that we switched
|
||||
// buffers. This might affect how we interpret certain mouse events.
|
||||
_terminalInput->UseAlternateScreenBuffer();
|
||||
|
||||
// Update scrollbars
|
||||
_NotifyScrollEvent();
|
||||
|
||||
// redraw the screen
|
||||
try
|
||||
{
|
||||
_activeBuffer().TriggerRedrawAll();
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
void Terminal::UseMainScreenBuffer()
|
||||
{
|
||||
// Short-circuit: do nothing.
|
||||
if (!_inAltBuffer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy our cursor state back to the main buffer's cursor
|
||||
{
|
||||
// Update the alt buffer's cursor style, visibility, and position to match our own.
|
||||
auto& myCursor = _altBuffer->GetCursor();
|
||||
auto& tgtCursor = _mainBuffer->GetCursor();
|
||||
tgtCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
|
||||
tgtCursor.SetIsVisible(myCursor.IsVisible());
|
||||
tgtCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
||||
|
||||
// The new position should match the viewport-relative position of the main buffer.
|
||||
// This is the equal and opposite effect of what we did in UseAlternateScreenBuffer
|
||||
auto tgtCursorPos = myCursor.GetPosition();
|
||||
tgtCursorPos.Y += _mutableViewport.Top();
|
||||
tgtCursor.SetPosition(tgtCursorPos);
|
||||
}
|
||||
|
||||
_mainBuffer->SetAsActiveBuffer(true);
|
||||
|
||||
// destroy the alt buffer
|
||||
_altBuffer = nullptr;
|
||||
|
||||
if (_deferredResize.has_value())
|
||||
{
|
||||
LOG_IF_FAILED(UserResize(_deferredResize.value().to_win32_coord()));
|
||||
_deferredResize = std::nullopt;
|
||||
}
|
||||
|
||||
// update all the hyperlinks on the screen
|
||||
UpdatePatternsUnderLock();
|
||||
|
||||
// GH#3321: Make sure we let the TerminalInput know that we switched
|
||||
// buffers. This might affect how we interpret certain mouse events.
|
||||
_terminalInput->UseMainScreenBuffer();
|
||||
|
||||
// Update scrollbars
|
||||
_NotifyScrollEvent();
|
||||
|
||||
// redraw the screen
|
||||
try
|
||||
{
|
||||
_activeBuffer().TriggerRedrawAll();
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
void Terminal::ClearMenu()
|
||||
{
|
||||
_menu.clear();
|
||||
|
||||
if (_pfnMenuChanged)
|
||||
{
|
||||
_pfnMenuChanged();
|
||||
}
|
||||
}
|
||||
void Terminal::AddToMenu(const Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry& entry)
|
||||
{
|
||||
// entry;
|
||||
// for (const auto& entry : menu)
|
||||
// {
|
||||
auto n = entry._name;
|
||||
n;
|
||||
auto a = 9;
|
||||
a++;
|
||||
a;
|
||||
|
||||
_menu.push_back(entry);
|
||||
|
||||
if (_pfnMenuChanged)
|
||||
{
|
||||
_pfnMenuChanged();
|
||||
}
|
||||
// }
|
||||
}
|
||||
// void Terminal::InvokeMenu(const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry>& menu)
|
||||
// {
|
||||
// menu;
|
||||
// for (const auto& entry : menu)
|
||||
// {
|
||||
// auto n = entry._name;
|
||||
// n;
|
||||
// auto a = 9;
|
||||
// a++;
|
||||
// a;
|
||||
|
||||
// }
|
||||
// // DebugBreak();
|
||||
// }
|
||||
|
||||
@@ -597,6 +597,128 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Performs a Windows Terminal action
|
||||
// Arguments:
|
||||
// - string: contains the parameters that define which action we do
|
||||
// Return Value:
|
||||
// - true
|
||||
bool TerminalDispatch::DoWindowsTerminalAction(const std::wstring_view string)
|
||||
{
|
||||
// unsigned int state = 0;
|
||||
// unsigned int progress = 0;
|
||||
|
||||
const auto parts = Utils::SplitString(string, L';');
|
||||
unsigned int subParam = 0;
|
||||
|
||||
if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto at_or_empty = [](const std::vector<std::wstring_view>& parts, const size_t i) -> std::wstring_view {
|
||||
if (parts.size() > i)
|
||||
return til::at(parts, i);
|
||||
else
|
||||
return std::wstring_view{};
|
||||
};
|
||||
// TODO! 1 is menucomplete
|
||||
// sequence format is
|
||||
//
|
||||
// OSC 9001 ; 1 ; [name GS comment GS input GS ... US ]* ST
|
||||
//
|
||||
// So `string` is "1;[name GS comment GS input GS ... US]*"
|
||||
// * `string[2:]` is the list of records.
|
||||
// * Split those by US, then iterate and construct entries
|
||||
// * split by GS and take whatever we have.
|
||||
if (subParam == 0)
|
||||
{
|
||||
_terminalApi.ClearMenu();
|
||||
}
|
||||
if (subParam == 1)
|
||||
{
|
||||
// if (parts.size() >= 2)
|
||||
// {
|
||||
// // A state parameter is defined, parse it out
|
||||
// const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state);
|
||||
// if (!stateSuccess && !til::at(parts, 1).empty())
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// if (parts.size() >= 3)
|
||||
// {
|
||||
// // A progress parameter is also defined, parse it out
|
||||
// const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress);
|
||||
// if (!progressSuccess && !til::at(parts, 2).empty())
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (state > TaskbarMaxState)
|
||||
// {
|
||||
// // state is out of bounds, return false
|
||||
// return false;
|
||||
// }
|
||||
// if (progress > TaskbarMaxProgress)
|
||||
// {
|
||||
// // progress is greater than the maximum allowed value, clamp it to the max
|
||||
// progress = TaskbarMaxProgress;
|
||||
// }
|
||||
// _terminalApi.SetTaskbarProgress(static_cast<DispatchTypes::TaskbarState>(state), progress);
|
||||
// return true;
|
||||
|
||||
if (parts.size() <= 1)
|
||||
{
|
||||
// // Shortcut: OSC 9001 ; 1 ST
|
||||
// // clear the entries.
|
||||
// const std::vector<DispatchTypes::MenuEntry> menu;
|
||||
// _terminalApi.AppendToMenu(menu);
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::vector<DispatchTypes::MenuEntry> menu;
|
||||
|
||||
const std::wstring_view entryString{ string.substr(2) };
|
||||
// const auto entries = Utils::SplitString(string, L'\x7F'); // US - unit separator
|
||||
// for (const auto& entryString : entries)
|
||||
// {
|
||||
const auto params{ Utils::SplitString(entryString, L'\x7F') }; // DEL
|
||||
|
||||
DispatchTypes::MenuEntry entry{ at_or_empty(params, 0), at_or_empty(params, 1), at_or_empty(params, 2) };
|
||||
|
||||
// menu.push_back(std::move(entry));
|
||||
// }
|
||||
|
||||
_terminalApi.AddToMenu(entry);
|
||||
}
|
||||
}
|
||||
// // 9 is SetWorkingDirectory, which informs the terminal about the current working directory.
|
||||
// else if (subParam == 9)
|
||||
// {
|
||||
// if (parts.size() >= 2)
|
||||
// {
|
||||
// const auto path = til::at(parts, 1);
|
||||
// // The path should be surrounded with '"' according to the documentation of ConEmu.
|
||||
// // An example: 9;"D:/"
|
||||
// if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3)
|
||||
// {
|
||||
// _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // If we fail to find the surrounding quotation marks, we'll give the path a try anyway.
|
||||
// // ConEmu also does this.
|
||||
// _terminalApi.SetWorkingDirectory(path);
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper to send a string reply to the input stream of the console.
|
||||
// - Used by various commands where the program attached would like a reply to one of the commands issued.
|
||||
@@ -658,6 +780,9 @@ bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param,
|
||||
case DispatchTypes::ModeParams::W32IM_Win32InputMode:
|
||||
success = EnableWin32InputMode(enable);
|
||||
break;
|
||||
case DispatchTypes::ModeParams::ASB_AlternateScreenBuffer:
|
||||
success = enable ? UseAlternateScreenBuffer() : UseMainScreenBuffer();
|
||||
break;
|
||||
default:
|
||||
// If no functions to call, overall dispatch was a failure.
|
||||
success = false;
|
||||
@@ -786,3 +911,84 @@ bool TerminalDispatch::HardReset()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DECSC - Saves the current "cursor state" into a memory buffer. This
|
||||
// includes the cursor position, origin mode, graphic rendition, and
|
||||
// active character set.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True.
|
||||
bool TerminalDispatch::CursorSaveState()
|
||||
{
|
||||
// TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this
|
||||
// is more elaborate.
|
||||
const auto attributes = _terminalApi.GetTextAttributes();
|
||||
COORD coordCursor = _terminalApi.GetCursorPosition();
|
||||
// The cursor is given to us by the API as relative to current viewport top.
|
||||
|
||||
// VT is also 1 based, not 0 based, so correct by 1.
|
||||
auto& savedCursorState = _savedCursorState.at(_usingAltBuffer);
|
||||
savedCursorState.Column = coordCursor.X + 1;
|
||||
savedCursorState.Row = coordCursor.Y + 1;
|
||||
savedCursorState.Attributes = attributes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DECRC - Restores a saved "cursor state" from the DECSC command back into
|
||||
// the console state. This includes the cursor position, origin mode, graphic
|
||||
// rendition, and active character set.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True.
|
||||
bool TerminalDispatch::CursorRestoreState()
|
||||
{
|
||||
// TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this
|
||||
// is more elaborate.
|
||||
auto& savedCursorState = _savedCursorState.at(_usingAltBuffer);
|
||||
|
||||
auto row = savedCursorState.Row;
|
||||
const auto col = savedCursorState.Column;
|
||||
|
||||
// The saved coordinates are always absolute, so we need reset the origin mode temporarily.
|
||||
CursorPosition(row, col);
|
||||
|
||||
// Restore text attributes.
|
||||
_terminalApi.SetTextAttributes(savedCursorState.Attributes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - ASBSET - Creates and swaps to the alternate screen buffer. In virtual terminals, there exists both a "main"
|
||||
// screen buffer and an alternate. ASBSET creates a new alternate, and switches to it. If there is an already
|
||||
// existing alternate, it is discarded.
|
||||
// Arguments:
|
||||
// - None
|
||||
// Return Value:
|
||||
// - True.
|
||||
bool TerminalDispatch::UseAlternateScreenBuffer()
|
||||
{
|
||||
CursorSaveState();
|
||||
_terminalApi.UseAlternateScreenBuffer();
|
||||
_usingAltBuffer = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - ASBRST - From the alternate buffer, returns to the main screen buffer.
|
||||
// From the main screen buffer, does nothing. The alternate is discarded.
|
||||
// Arguments:
|
||||
// - None
|
||||
// Return Value:
|
||||
// - True.
|
||||
bool TerminalDispatch::UseMainScreenBuffer()
|
||||
{
|
||||
_terminalApi.UseMainScreenBuffer();
|
||||
_usingAltBuffer = false;
|
||||
CursorRestoreState();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ public:
|
||||
bool CarriageReturn() override;
|
||||
bool SetWindowTitle(std::wstring_view title) override;
|
||||
|
||||
bool UseAlternateScreenBuffer() override; // ASBSET
|
||||
bool UseMainScreenBuffer() override; // ASBRST
|
||||
|
||||
bool HorizontalTabSet() override; // HTS
|
||||
bool ForwardTab(const size_t numTabs) override; // CHT, HT
|
||||
bool BackwardsTab(const size_t numTabs) override; // CBT
|
||||
@@ -81,13 +84,33 @@ public:
|
||||
bool EndHyperlink() override;
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view string) override;
|
||||
bool DoWindowsTerminalAction(const std::wstring_view string) override;
|
||||
|
||||
bool CursorSaveState() override;
|
||||
bool CursorRestoreState() override;
|
||||
|
||||
private:
|
||||
::Microsoft::Terminal::Core::ITerminalApi& _terminalApi;
|
||||
|
||||
// Dramatically simplified version of AdaptDispatch::CursorState
|
||||
struct CursorState
|
||||
{
|
||||
unsigned int Row = 1;
|
||||
unsigned int Column = 1;
|
||||
TextAttribute Attributes = {};
|
||||
};
|
||||
|
||||
std::vector<bool> _tabStopColumns;
|
||||
bool _initDefaultTabStops = true;
|
||||
|
||||
// We have two instances of the saved cursor state, because we need
|
||||
// one for the main buffer (at index 0), and another for the alt buffer
|
||||
// (at index 1). The _usingAltBuffer property keeps tracks of which
|
||||
// buffer is active, so can be used as an index into this array to
|
||||
// obtain the saved state that should be currently active.
|
||||
std::array<CursorState, 2> _savedCursorState;
|
||||
bool _usingAltBuffer = false;
|
||||
|
||||
size_t _SetRgbColorsHelper(const ::Microsoft::Console::VirtualTerminal::VTParameters options,
|
||||
TextAttribute& attr,
|
||||
const bool isForeground);
|
||||
|
||||
@@ -54,7 +54,7 @@ std::vector<SMALL_RECT> Terminal::_GetSelectionRects() const noexcept
|
||||
|
||||
try
|
||||
{
|
||||
return _buffer->GetTextRects(_selection->start, _selection->end, _blockSelection, false);
|
||||
return _activeBuffer().GetTextRects(_selection->start, _selection->end, _blockSelection, false);
|
||||
}
|
||||
CATCH_LOG();
|
||||
return result;
|
||||
@@ -182,7 +182,7 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional<SelectionE
|
||||
// - the new start/end for a selection
|
||||
std::pair<COORD, COORD> Terminal::_PivotSelection(const COORD targetPos, bool& targetStart) const
|
||||
{
|
||||
if (targetStart = _buffer->GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0)
|
||||
if (targetStart = _activeBuffer().GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0)
|
||||
{
|
||||
// target is before pivot
|
||||
// treat target as start
|
||||
@@ -207,7 +207,7 @@ std::pair<COORD, COORD> Terminal::_ExpandSelectionAnchors(std::pair<COORD, COORD
|
||||
COORD start = anchors.first;
|
||||
COORD end = anchors.second;
|
||||
|
||||
const auto bufferSize = _buffer->GetSize();
|
||||
const auto bufferSize = _activeBuffer().GetSize();
|
||||
switch (_multiClickSelectionMode)
|
||||
{
|
||||
case SelectionExpansion::Line:
|
||||
@@ -215,8 +215,8 @@ std::pair<COORD, COORD> Terminal::_ExpandSelectionAnchors(std::pair<COORD, COORD
|
||||
end = { bufferSize.RightInclusive(), end.Y };
|
||||
break;
|
||||
case SelectionExpansion::Word:
|
||||
start = _buffer->GetWordStart(start, _wordDelimiters);
|
||||
end = _buffer->GetWordEnd(end, _wordDelimiters);
|
||||
start = _activeBuffer().GetWordStart(start, _wordDelimiters);
|
||||
end = _activeBuffer().GetWordEnd(end, _wordDelimiters);
|
||||
break;
|
||||
case SelectionExpansion::Char:
|
||||
default:
|
||||
@@ -325,7 +325,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
|
||||
_scrollOffset -= amtBelowView;
|
||||
}
|
||||
_NotifyScrollEvent();
|
||||
_buffer->TriggerScroll();
|
||||
_activeBuffer().TriggerScroll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,22 +334,22 @@ void Terminal::_MoveByChar(SelectionDirection direction, COORD& pos)
|
||||
switch (direction)
|
||||
{
|
||||
case SelectionDirection::Left:
|
||||
_buffer->GetSize().DecrementInBounds(pos);
|
||||
pos = _buffer->GetGlyphStart(til::point{ pos }).to_win32_coord();
|
||||
_activeBuffer().GetSize().DecrementInBounds(pos);
|
||||
pos = _activeBuffer().GetGlyphStart(til::point{ pos }).to_win32_coord();
|
||||
break;
|
||||
case SelectionDirection::Right:
|
||||
_buffer->GetSize().IncrementInBounds(pos);
|
||||
pos = _buffer->GetGlyphEnd(til::point{ pos }).to_win32_coord();
|
||||
_activeBuffer().GetSize().IncrementInBounds(pos);
|
||||
pos = _activeBuffer().GetGlyphEnd(til::point{ pos }).to_win32_coord();
|
||||
break;
|
||||
case SelectionDirection::Up:
|
||||
{
|
||||
const auto bufferSize{ _buffer->GetSize() };
|
||||
const auto bufferSize{ _activeBuffer().GetSize() };
|
||||
pos = { pos.X, std::clamp(base::ClampSub<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
|
||||
break;
|
||||
}
|
||||
case SelectionDirection::Down:
|
||||
{
|
||||
const auto bufferSize{ _buffer->GetSize() };
|
||||
const auto bufferSize{ _activeBuffer().GetSize() };
|
||||
pos = { pos.X, std::clamp(base::ClampAdd<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
|
||||
break;
|
||||
}
|
||||
@@ -361,19 +361,19 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
|
||||
switch (direction)
|
||||
{
|
||||
case SelectionDirection::Left:
|
||||
const auto wordStartPos{ _buffer->GetWordStart(pos, _wordDelimiters) };
|
||||
if (_buffer->GetSize().CompareInBounds(_selection->pivot, pos) < 0)
|
||||
const auto wordStartPos{ _activeBuffer().GetWordStart(pos, _wordDelimiters) };
|
||||
if (_activeBuffer().GetSize().CompareInBounds(_selection->pivot, pos) < 0)
|
||||
{
|
||||
// If we're moving towards the pivot, move one more cell
|
||||
pos = wordStartPos;
|
||||
_buffer->GetSize().DecrementInBounds(pos);
|
||||
_activeBuffer().GetSize().DecrementInBounds(pos);
|
||||
}
|
||||
else if (wordStartPos == pos)
|
||||
{
|
||||
// already at the beginning of the current word,
|
||||
// move to the beginning of the previous word
|
||||
_buffer->GetSize().DecrementInBounds(pos);
|
||||
pos = _buffer->GetWordStart(pos, _wordDelimiters);
|
||||
_activeBuffer().GetSize().DecrementInBounds(pos);
|
||||
pos = _activeBuffer().GetWordStart(pos, _wordDelimiters);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -382,19 +382,19 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
|
||||
}
|
||||
break;
|
||||
case SelectionDirection::Right:
|
||||
const auto wordEndPos{ _buffer->GetWordEnd(pos, _wordDelimiters) };
|
||||
if (_buffer->GetSize().CompareInBounds(pos, _selection->pivot) < 0)
|
||||
const auto wordEndPos{ _activeBuffer().GetWordEnd(pos, _wordDelimiters) };
|
||||
if (_activeBuffer().GetSize().CompareInBounds(pos, _selection->pivot) < 0)
|
||||
{
|
||||
// If we're moving towards the pivot, move one more cell
|
||||
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
|
||||
_buffer->GetSize().IncrementInBounds(pos);
|
||||
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
|
||||
_activeBuffer().GetSize().IncrementInBounds(pos);
|
||||
}
|
||||
else if (wordEndPos == pos)
|
||||
{
|
||||
// already at the end of the current word,
|
||||
// move to the end of the next word
|
||||
_buffer->GetSize().IncrementInBounds(pos);
|
||||
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
|
||||
_activeBuffer().GetSize().IncrementInBounds(pos);
|
||||
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -404,18 +404,18 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
|
||||
break;
|
||||
case SelectionDirection::Up:
|
||||
_MoveByChar(direction, pos);
|
||||
pos = _buffer->GetWordStart(pos, _wordDelimiters);
|
||||
pos = _activeBuffer().GetWordStart(pos, _wordDelimiters);
|
||||
break;
|
||||
case SelectionDirection::Down:
|
||||
_MoveByChar(direction, pos);
|
||||
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
|
||||
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)
|
||||
{
|
||||
const auto bufferSize{ _buffer->GetSize() };
|
||||
const auto bufferSize{ _activeBuffer().GetSize() };
|
||||
switch (direction)
|
||||
{
|
||||
case SelectionDirection::Left:
|
||||
@@ -426,15 +426,15 @@ void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)
|
||||
break;
|
||||
case SelectionDirection::Up:
|
||||
{
|
||||
const auto viewportHeight{ _mutableViewport.Height() };
|
||||
const auto viewportHeight{ _GetMutableViewport().Height() };
|
||||
const auto newY{ base::ClampSub<short, short>(pos.Y, viewportHeight) };
|
||||
pos = newY < bufferSize.Top() ? bufferSize.Origin() : COORD{ pos.X, newY };
|
||||
break;
|
||||
}
|
||||
case SelectionDirection::Down:
|
||||
{
|
||||
const auto viewportHeight{ _mutableViewport.Height() };
|
||||
const auto mutableBottom{ _mutableViewport.BottomInclusive() };
|
||||
const auto viewportHeight{ _GetMutableViewport().Height() };
|
||||
const auto mutableBottom{ _GetMutableViewport().BottomInclusive() };
|
||||
const auto newY{ base::ClampAdd<short, short>(pos.Y, viewportHeight) };
|
||||
pos = newY > mutableBottom ? COORD{ bufferSize.RightInclusive(), mutableBottom } : COORD{ pos.X, newY };
|
||||
break;
|
||||
@@ -444,7 +444,7 @@ void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)
|
||||
|
||||
void Terminal::_MoveByBuffer(SelectionDirection direction, COORD& pos)
|
||||
{
|
||||
const auto bufferSize{ _buffer->GetSize() };
|
||||
const auto bufferSize{ _activeBuffer().GetSize() };
|
||||
switch (direction)
|
||||
{
|
||||
case SelectionDirection::Left:
|
||||
@@ -453,7 +453,7 @@ void Terminal::_MoveByBuffer(SelectionDirection direction, COORD& pos)
|
||||
break;
|
||||
case SelectionDirection::Right:
|
||||
case SelectionDirection::Down:
|
||||
pos = { bufferSize.RightInclusive(), _mutableViewport.BottomInclusive() };
|
||||
pos = { bufferSize.RightInclusive(), _GetMutableViewport().BottomInclusive() };
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -489,7 +489,7 @@ const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool sin
|
||||
const auto includeCRLF = !singleLine || _blockSelection;
|
||||
const auto trimTrailingWhitespace = !singleLine && (!_blockSelection || _trimBlockSelection);
|
||||
const auto formatWrappedRows = _blockSelection;
|
||||
return _buffer->GetText(includeCRLF, trimTrailingWhitespace, selectionRects, GetAttributeColors, formatWrappedRows);
|
||||
return _activeBuffer().GetText(includeCRLF, trimTrailingWhitespace, selectionRects, GetAttributeColors, formatWrappedRows);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -502,7 +502,7 @@ COORD Terminal::_ConvertToBufferCell(const COORD viewportPos) const
|
||||
{
|
||||
const auto yPos = base::ClampedNumeric<short>(_VisibleStartIndex()) + viewportPos.Y;
|
||||
COORD bufferPos = { viewportPos.X, yPos };
|
||||
_buffer->GetSize().Clamp(bufferPos);
|
||||
_activeBuffer().GetSize().Clamp(bufferPos);
|
||||
return bufferPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ COORD Terminal::GetTextBufferEndPosition() const noexcept
|
||||
|
||||
const TextBuffer& Terminal::GetTextBuffer() noexcept
|
||||
{
|
||||
return *_buffer;
|
||||
return _activeBuffer();
|
||||
}
|
||||
|
||||
const FontInfo& Terminal::GetFontInfo() noexcept
|
||||
@@ -40,19 +40,19 @@ void Terminal::SetFontInfo(const FontInfo& fontInfo)
|
||||
|
||||
COORD Terminal::GetCursorPosition() const noexcept
|
||||
{
|
||||
const auto& cursor = _buffer->GetCursor();
|
||||
const auto& cursor = _activeBuffer().GetCursor();
|
||||
return cursor.GetPosition();
|
||||
}
|
||||
|
||||
bool Terminal::IsCursorVisible() const noexcept
|
||||
{
|
||||
const auto& cursor = _buffer->GetCursor();
|
||||
const auto& cursor = _activeBuffer().GetCursor();
|
||||
return cursor.IsVisible() && !cursor.IsPopupShown();
|
||||
}
|
||||
|
||||
bool Terminal::IsCursorOn() const noexcept
|
||||
{
|
||||
const auto& cursor = _buffer->GetCursor();
|
||||
const auto& cursor = _activeBuffer().GetCursor();
|
||||
return cursor.IsOn();
|
||||
}
|
||||
|
||||
@@ -63,18 +63,18 @@ ULONG Terminal::GetCursorPixelWidth() const noexcept
|
||||
|
||||
ULONG Terminal::GetCursorHeight() const noexcept
|
||||
{
|
||||
return _buffer->GetCursor().GetSize();
|
||||
return _activeBuffer().GetCursor().GetSize();
|
||||
}
|
||||
|
||||
CursorType Terminal::GetCursorStyle() const noexcept
|
||||
{
|
||||
return _buffer->GetCursor().GetType();
|
||||
return _activeBuffer().GetCursor().GetType();
|
||||
}
|
||||
|
||||
bool Terminal::IsCursorDoubleWidth() const
|
||||
{
|
||||
const auto position = _buffer->GetCursor().GetPosition();
|
||||
TextBufferTextIterator it(TextBufferCellIterator(*_buffer, position));
|
||||
const auto position = _activeBuffer().GetCursor().GetPosition();
|
||||
TextBufferTextIterator it(TextBufferCellIterator(_activeBuffer(), position));
|
||||
return IsGlyphFullWidth(*it);
|
||||
}
|
||||
|
||||
@@ -90,12 +90,12 @@ const bool Terminal::IsGridLineDrawingAllowed() noexcept
|
||||
|
||||
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkUri(uint16_t id) const noexcept
|
||||
{
|
||||
return _buffer->GetHyperlinkUriFromId(id);
|
||||
return _activeBuffer().GetHyperlinkUriFromId(id);
|
||||
}
|
||||
|
||||
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkCustomId(uint16_t id) const noexcept
|
||||
{
|
||||
return _buffer->GetCustomIdFromId(id);
|
||||
return _activeBuffer().GetCustomIdFromId(id);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -174,7 +174,7 @@ void Terminal::SelectNewRegion(const COORD coordStart, const COORD coordEnd)
|
||||
|
||||
if (notifyScrollChange)
|
||||
{
|
||||
_buffer->TriggerScroll();
|
||||
_activeBuffer().TriggerScroll();
|
||||
_NotifyScrollEvent();
|
||||
}
|
||||
|
||||
@@ -227,5 +227,5 @@ const bool Terminal::IsUiaDataInitialized() const noexcept
|
||||
// when a screen reader requests it. However, the terminal might not be fully
|
||||
// initialized yet. So we use this to check if any crucial components of
|
||||
// UiaData are not yet initialized.
|
||||
return !!_buffer;
|
||||
return !!_mainBuffer;
|
||||
}
|
||||
|
||||
@@ -713,6 +713,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
BASIC_FACTORY(RenameTabArgs);
|
||||
BASIC_FACTORY(SwapPaneArgs);
|
||||
BASIC_FACTORY(SplitPaneArgs);
|
||||
BASIC_FACTORY(SendInputArgs);
|
||||
BASIC_FACTORY(SetFocusModeArgs);
|
||||
BASIC_FACTORY(SetFullScreenArgs);
|
||||
BASIC_FACTORY(SetMaximizedArgs);
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
|
||||
[default_interface] runtimeclass SendInputArgs : IActionArgs
|
||||
{
|
||||
SendInputArgs(String input);
|
||||
String Input { get; };
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
Command();
|
||||
|
||||
String Name { get; };
|
||||
ActionAndArgs ActionAndArgs { get; };
|
||||
String Name;
|
||||
ActionAndArgs ActionAndArgs;
|
||||
Microsoft.Terminal.Control.KeyChord Keys { get; };
|
||||
void RegisterKey(Microsoft.Terminal.Control.KeyChord keys);
|
||||
String KeyChordText { get; };
|
||||
|
||||
@@ -222,6 +222,9 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
|
||||
|
||||
TEST_METHOD(ClearBufferSignal);
|
||||
|
||||
TEST_METHOD(SimpleAltBufferTest);
|
||||
TEST_METHOD(AltBufferToAltBufferTest);
|
||||
|
||||
private:
|
||||
bool _writeCallback(const char* const pch, size_t const cch);
|
||||
void _flushFirstFrame();
|
||||
@@ -322,7 +325,7 @@ void ConptyRoundtripTests::_clearConpty()
|
||||
|
||||
// After we resize, make sure to get the new textBuffers
|
||||
return { &ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetTextBuffer(),
|
||||
term->_buffer.get() };
|
||||
term->_mainBuffer.get() };
|
||||
}
|
||||
|
||||
void ConptyRoundtripTests::ConptyOutputTestCanary()
|
||||
@@ -344,7 +347,7 @@ void ConptyRoundtripTests::SimpleWriteOutputTest()
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -367,7 +370,7 @@ void ConptyRoundtripTests::WriteTwoLinesUsesNewline()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -402,7 +405,7 @@ void ConptyRoundtripTests::WriteAFewSimpleLines()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -443,7 +446,7 @@ void ConptyRoundtripTests::TestWrappingALongString()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
_checkConptyOutput = false;
|
||||
@@ -494,7 +497,7 @@ void ConptyRoundtripTests::TestAdvancedWrapping()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
const auto initialTermView = term->GetViewport();
|
||||
|
||||
_flushFirstFrame();
|
||||
@@ -559,7 +562,7 @@ void ConptyRoundtripTests::TestExactWrappingWithoutSpaces()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
const auto initialTermView = term->GetViewport();
|
||||
|
||||
@@ -621,7 +624,7 @@ void ConptyRoundtripTests::TestExactWrappingWithSpaces()
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
const auto initialTermView = term->GetViewport();
|
||||
|
||||
_flushFirstFrame();
|
||||
@@ -683,7 +686,7 @@ void ConptyRoundtripTests::MoveCursorAtEOL()
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
_flushFirstFrame();
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
@@ -762,7 +765,7 @@ void ConptyRoundtripTests::TestResizeHeight()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
const auto initialHostView = si.GetViewport();
|
||||
const auto initialTermView = term->GetViewport();
|
||||
const auto initialTerminalBufferHeight = term->GetTextBuffer().GetSize().Height();
|
||||
@@ -962,7 +965,7 @@ void ConptyRoundtripTests::PassthroughCursorShapeImmediately()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -989,7 +992,7 @@ void ConptyRoundtripTests::PassthroughClearScrollback()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1066,7 +1069,7 @@ void ConptyRoundtripTests::PassthroughClearAll()
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
auto& sm = si.GetStateMachine();
|
||||
|
||||
@@ -1153,7 +1156,7 @@ void ConptyRoundtripTests::PassthroughHardReset()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1217,7 +1220,7 @@ void ConptyRoundtripTests::OutputWrappedLinesAtTopOfBuffer()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1265,7 +1268,7 @@ void ConptyRoundtripTests::OutputWrappedLinesAtBottomOfBuffer()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1398,7 +1401,7 @@ void ConptyRoundtripTests::ScrollWithChangesInMiddle()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1499,7 +1502,7 @@ void ConptyRoundtripTests::ScrollWithMargins()
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
const auto initialTermView = term->GetViewport();
|
||||
|
||||
Log::Comment(L"Flush first frame.");
|
||||
@@ -1743,7 +1746,7 @@ void ConptyRoundtripTests::DontWrapMoveCursorInSingleFrame()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1836,7 +1839,7 @@ void ConptyRoundtripTests::ClearHostTrickeryTest()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -1944,7 +1947,7 @@ void ConptyRoundtripTests::OverstrikeAtBottomOfBuffer()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2022,7 +2025,7 @@ void ConptyRoundtripTests::MarginsWithStatusLine()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2113,7 +2116,7 @@ void ConptyRoundtripTests::OutputWrappedLineWithSpace()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2179,7 +2182,7 @@ void ConptyRoundtripTests::OutputWrappedLineWithSpaceAtBottomOfBuffer()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2334,8 +2337,6 @@ void ConptyRoundtripTests::BreakLinesOnCursorMovement()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& termTb = *term->_buffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
// Any of the cursor movements that use a LF will actually hard break the
|
||||
@@ -2475,8 +2476,9 @@ void ConptyRoundtripTests::BreakLinesOnCursorMovement()
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"========== Checking the terminal buffer state ==========");
|
||||
|
||||
verifyBuffer(termTb, til::rect{ term->_mutableViewport.ToInclusive() });
|
||||
// GH#3492: Now that we support the alt buffer, make sure to validate the
|
||||
// _alt buffer's_ contents.
|
||||
verifyBuffer(*term->_altBuffer, til::rect{ term->_mutableViewport.ToInclusive() });
|
||||
}
|
||||
|
||||
void ConptyRoundtripTests::TestCursorInDeferredEOLPositionOnNewLineWithSpaces()
|
||||
@@ -2488,7 +2490,7 @@ void ConptyRoundtripTests::TestCursorInDeferredEOLPositionOnNewLineWithSpaces()
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
const auto termView = term->GetViewport();
|
||||
|
||||
_flushFirstFrame();
|
||||
@@ -2549,7 +2551,7 @@ void ConptyRoundtripTests::ResizeRepaintVimExeBuffer()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2678,7 +2680,7 @@ void ConptyRoundtripTests::ClsAndClearHostClearsScrollbackTest()
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
auto& sm = si.GetStateMachine();
|
||||
|
||||
@@ -2833,7 +2835,7 @@ void ConptyRoundtripTests::TestResizeWithCookedRead()
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -2894,7 +2896,7 @@ void ConptyRoundtripTests::ResizeInitializeBufferWithDefaultAttrs()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3021,7 +3023,7 @@ void ConptyRoundtripTests::NewLinesAtBottomWithBackground()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3191,7 +3193,7 @@ void ConptyRoundtripTests::WrapNewLineAtBottom()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3349,7 +3351,7 @@ void ConptyRoundtripTests::WrapNewLineAtBottomLikeMSYS()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3533,7 +3535,7 @@ void ConptyRoundtripTests::DeleteWrappedWord()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3625,7 +3627,7 @@ void ConptyRoundtripTests::HyperlinkIdConsistency()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3690,7 +3692,7 @@ void ConptyRoundtripTests::ClearBufferSignal()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_buffer.get();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
@@ -3705,12 +3707,11 @@ void ConptyRoundtripTests::ClearBufferSignal()
|
||||
// B's are in red-on-yellow
|
||||
|
||||
sm.ProcessString(L"\x1b[?25l");
|
||||
sm.ProcessString(L"\x1b[?34;42m");
|
||||
sm.ProcessString(L"\x1b[34;42m");
|
||||
sm.ProcessString(std::wstring(50, L'A'));
|
||||
sm.ProcessString(L" ");
|
||||
sm.ProcessString(L"\x1b[?31;43m");
|
||||
sm.ProcessString(L"\x1b[31;43m");
|
||||
sm.ProcessString(std::wstring(50, L'B'));
|
||||
sm.ProcessString(L"\x1b[?m");
|
||||
sm.ProcessString(L"\x1b[?25h");
|
||||
|
||||
auto verifyBuffer = [&](const TextBuffer& tb, const til::rect& viewport, const bool before) {
|
||||
@@ -3752,3 +3753,318 @@ void ConptyRoundtripTests::ClearBufferSignal()
|
||||
Log::Comment(L"========== Checking the terminal buffer state (after) ==========");
|
||||
verifyBuffer(*termTb, til::rect{ term->_mutableViewport.ToInclusive() }, false);
|
||||
}
|
||||
|
||||
void ConptyRoundtripTests::SimpleAltBufferTest()
|
||||
{
|
||||
Log::Comment(L"A test for entering and exiting the alt buffer, via conpty. "
|
||||
L"Ensures cursor is in the right place, and contents are "
|
||||
L"restored accordingly.");
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& renderer = *g.pRender;
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
_checkConptyOutput = false;
|
||||
_logConpty = true;
|
||||
|
||||
// Print two lines of text:
|
||||
// |AAAAAAAA | <break>
|
||||
// |BBBBBBBB_ | <break>
|
||||
// (cursor on the '_')
|
||||
// A's are in blue-on-green,
|
||||
// B's are in red-on-yellow
|
||||
|
||||
// A one line version: (more or less)
|
||||
//
|
||||
// printf "\x1b[2J\x1b[H" ; printf
|
||||
// "\x1b[?25l\x1b[34;42mAAAAA\n\x1b[31;43mBBBBB\x1b[?25h" ; sleep 2 ; printf
|
||||
// "\x1b[?1049h" ; sleep 2 ; printf "CCCCC" ; sleep 2 ; printf "\x1b[?1049l"
|
||||
// ; sleep 2
|
||||
|
||||
sm.ProcessString(L"\x1b[?25l");
|
||||
sm.ProcessString(L"\x1b[34;42m");
|
||||
sm.ProcessString(std::wstring(50, L'A'));
|
||||
sm.ProcessString(L"\n");
|
||||
sm.ProcessString(L"\x1b[31;43m");
|
||||
sm.ProcessString(std::wstring(50, L'B'));
|
||||
sm.ProcessString(L"\x1b[?25h");
|
||||
|
||||
// Four frames here:
|
||||
// * After text is printed to main buffer
|
||||
// * after we go to the alt buffer
|
||||
// * print more to the alt buffer
|
||||
// * after we go back to the buffer
|
||||
|
||||
enum class Frame : int
|
||||
{
|
||||
InMainBufferBefore = 0,
|
||||
InAltBufferBefore,
|
||||
InAltBufferAfter,
|
||||
InMainBufferAfter
|
||||
};
|
||||
|
||||
auto verifyBuffer = [&](const TextBuffer& tb, const til::rect& viewport, const Frame frame) {
|
||||
const short width = viewport.narrow_width<short>();
|
||||
auto iter0 = tb.GetCellDataAt({ 0, 0 });
|
||||
auto iter1 = tb.GetCellDataAt({ 0, 1 });
|
||||
switch (frame)
|
||||
{
|
||||
case Frame::InMainBufferBefore:
|
||||
case Frame::InMainBufferAfter:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L"A", iter0, 0, 50);
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, static_cast<size_t>(width - 50));
|
||||
|
||||
TestUtils::VerifySpanOfText(L"B", iter1, 0, 50);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, static_cast<size_t>(width - 50));
|
||||
COORD expectedCursor{ 50, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
case Frame::InAltBufferBefore:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, width);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, width);
|
||||
|
||||
COORD expectedCursor{ 50, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
case Frame::InAltBufferAfter:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, width);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, 50u);
|
||||
TestUtils::VerifySpanOfText(L"C", iter1, 0, 5u);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, static_cast<size_t>(width - 55));
|
||||
|
||||
COORD expectedCursor{ 55, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Log::Comment(L"========== Checking the host buffer state (InMainBufferBefore) ==========");
|
||||
verifyBuffer(*hostTb, til::rect{ si.GetViewport().ToInclusive() }, Frame::InMainBufferBefore);
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InMainBufferBefore) ==========");
|
||||
VERIFY_ARE_EQUAL(0, term->_GetMutableViewport().Top());
|
||||
verifyBuffer(*termTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InMainBufferBefore);
|
||||
|
||||
Log::Comment(L"========== Switch to the alt buffer ==========");
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
sm.ProcessString(L"\x1b[?1049h");
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
auto& siAlt = gci.GetActiveOutputBuffer();
|
||||
auto* hostAltTb = &siAlt.GetTextBuffer();
|
||||
auto* termAltTb = &term->_activeBuffer();
|
||||
|
||||
VERIFY_IS_TRUE(term->_inAltBuffer());
|
||||
VERIFY_ARE_NOT_EQUAL(termAltTb, termTb);
|
||||
|
||||
Log::Comment(L"========== Checking the host buffer state (InAltBufferBefore) ==========");
|
||||
verifyBuffer(*hostAltTb, til::rect{ siAlt.GetViewport().ToInclusive() }, Frame::InAltBufferBefore);
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InAltBufferBefore) ==========");
|
||||
VERIFY_ARE_EQUAL(0, term->_GetMutableViewport().Top());
|
||||
verifyBuffer(*termAltTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InAltBufferBefore);
|
||||
|
||||
Log::Comment(L"========== Add some text to the alt buffer ==========");
|
||||
|
||||
sm.ProcessString(L"CCCCC");
|
||||
Log::Comment(L"========== Checking the host buffer state (InAltBufferAfter) ==========");
|
||||
verifyBuffer(*hostAltTb, til::rect{ siAlt.GetViewport().ToInclusive() }, Frame::InAltBufferAfter);
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InAltBufferAfter) ==========");
|
||||
VERIFY_ARE_EQUAL(0, term->_GetMutableViewport().Top());
|
||||
verifyBuffer(*termAltTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InAltBufferAfter);
|
||||
|
||||
Log::Comment(L"========== Back to the main buffer ==========");
|
||||
|
||||
sm.ProcessString(L"\x1b[?1049l");
|
||||
Log::Comment(L"========== Checking the host buffer state (InMainBufferAfter) ==========");
|
||||
verifyBuffer(*hostTb, til::rect{ si.GetViewport().ToInclusive() }, Frame::InMainBufferAfter);
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InMainBufferAfter) ==========");
|
||||
VERIFY_ARE_EQUAL(0, term->_GetMutableViewport().Top());
|
||||
verifyBuffer(*termTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InMainBufferAfter);
|
||||
}
|
||||
|
||||
void ConptyRoundtripTests::AltBufferToAltBufferTest()
|
||||
{
|
||||
Log::Comment(L"When we request the alt buffer when we're already in the alt buffer, we should still clear it out and replace it.");
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& renderer = *g.pRender;
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
auto* hostTb = &si.GetTextBuffer();
|
||||
auto* termTb = term->_mainBuffer.get();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
_checkConptyOutput = false;
|
||||
_logConpty = true;
|
||||
|
||||
// Print two lines of text:
|
||||
// |AAAAAAAA | <break>
|
||||
// |BBBBBBBB_ | <break>
|
||||
// (cursor on the '_')
|
||||
// A's are in blue-on-green,
|
||||
// B's are in red-on-yellow
|
||||
|
||||
// A one line version: (more or less)
|
||||
//
|
||||
// printf "\x1b[2J\x1b[H" ; printf
|
||||
// "\x1b[?25l\x1b[34;42mAAAAA\n\x1b[31;43mBBBBB\x1b[?25h" ; sleep 2 ; printf
|
||||
// "\x1b[?1049h" ; sleep 2 ; printf "CCCCC" ; sleep 2 ; printf "\x1b[?1049h"
|
||||
// ; sleep 2
|
||||
|
||||
sm.ProcessString(L"\x1b[?25l");
|
||||
sm.ProcessString(L"\x1b[34;42m");
|
||||
sm.ProcessString(std::wstring(50, L'A'));
|
||||
sm.ProcessString(L"\n");
|
||||
sm.ProcessString(L"\x1b[31;43m");
|
||||
sm.ProcessString(std::wstring(50, L'B'));
|
||||
sm.ProcessString(L"\x1b[?25h");
|
||||
|
||||
// Four frames here:
|
||||
// * After text is printed to main buffer
|
||||
// * after we go to the alt buffer
|
||||
// * print more to the alt buffer
|
||||
// * after we go back to the buffer
|
||||
|
||||
enum class Frame : int
|
||||
{
|
||||
InMainBufferBefore = 0,
|
||||
InAltBufferBefore,
|
||||
InAltBufferAfter,
|
||||
StillInAltBuffer
|
||||
};
|
||||
|
||||
auto verifyBuffer = [&](const TextBuffer& tb, const til::rect& viewport, const Frame frame) {
|
||||
const short width = viewport.narrow_width<short>();
|
||||
auto iter0 = tb.GetCellDataAt({ 0, 0 });
|
||||
auto iter1 = tb.GetCellDataAt({ 0, 1 });
|
||||
switch (frame)
|
||||
{
|
||||
case Frame::InMainBufferBefore:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L"A", iter0, 0, 50);
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, static_cast<size_t>(width - 50));
|
||||
|
||||
TestUtils::VerifySpanOfText(L"B", iter1, 0, 50);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, static_cast<size_t>(width - 50));
|
||||
COORD expectedCursor{ 50, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
case Frame::InAltBufferBefore:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, width);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, width);
|
||||
|
||||
COORD expectedCursor{ 50, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
case Frame::InAltBufferAfter:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, width);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, 50u);
|
||||
TestUtils::VerifySpanOfText(L"C", iter1, 0, 5u);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, static_cast<size_t>(width - 55));
|
||||
|
||||
COORD expectedCursor{ 55, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
case Frame::StillInAltBuffer:
|
||||
{
|
||||
TestUtils::VerifySpanOfText(L" ", iter0, 0, width);
|
||||
TestUtils::VerifySpanOfText(L" ", iter1, 0, width);
|
||||
|
||||
COORD expectedCursor{ 55, 1 };
|
||||
VERIFY_ARE_EQUAL(expectedCursor, tb.GetCursor().GetPosition());
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Log::Comment(L"========== Checking the host buffer state (InMainBufferBefore) ==========");
|
||||
verifyBuffer(*hostTb, til::rect{ si.GetViewport().ToInclusive() }, Frame::InMainBufferBefore);
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InMainBufferBefore) ==========");
|
||||
verifyBuffer(*termTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InMainBufferBefore);
|
||||
|
||||
Log::Comment(L"========== Switch to the alt buffer ==========");
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
sm.ProcessString(L"\x1b[?1049h");
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
auto* siAlt = &gci.GetActiveOutputBuffer();
|
||||
auto* hostAltTb = &siAlt->GetTextBuffer();
|
||||
auto* termAltTb = &term->_activeBuffer();
|
||||
|
||||
VERIFY_IS_TRUE(term->_inAltBuffer());
|
||||
VERIFY_ARE_NOT_EQUAL(termAltTb, termTb);
|
||||
|
||||
Log::Comment(L"========== Checking the host buffer state (InAltBufferBefore) ==========");
|
||||
verifyBuffer(*hostAltTb, til::rect{ siAlt->GetViewport().ToInclusive() }, Frame::InAltBufferBefore);
|
||||
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InAltBufferBefore) ==========");
|
||||
verifyBuffer(*termAltTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InAltBufferBefore);
|
||||
|
||||
Log::Comment(L"========== Add some text to the alt buffer ==========");
|
||||
|
||||
sm.ProcessString(L"CCCCC");
|
||||
Log::Comment(L"========== Checking the host buffer state (InAltBufferAfter) ==========");
|
||||
verifyBuffer(*hostAltTb, til::rect{ siAlt->GetViewport().ToInclusive() }, Frame::InAltBufferAfter);
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"========== Checking the terminal buffer state (InAltBufferAfter) ==========");
|
||||
verifyBuffer(*termAltTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::InAltBufferAfter);
|
||||
|
||||
Log::Comment(L"========== Stay in the alt buffer, what happens? ==========");
|
||||
|
||||
sm.ProcessString(L"\x1b[?1049h");
|
||||
Log::Comment(L"Painting the frame");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
siAlt = &gci.GetActiveOutputBuffer();
|
||||
hostAltTb = &siAlt->GetTextBuffer();
|
||||
termAltTb = &term->_activeBuffer();
|
||||
|
||||
Log::Comment(L"========== Checking the host buffer state (StillInAltBuffer) ==========");
|
||||
verifyBuffer(*hostAltTb, til::rect{ siAlt->GetViewport().ToInclusive() }, Frame::StillInAltBuffer);
|
||||
|
||||
Log::Comment(L"========== Checking the terminal buffer state (StillInAltBuffer) ==========");
|
||||
verifyBuffer(*termAltTb, til::rect{ term->_GetMutableViewport().ToInclusive() }, Frame::StillInAltBuffer);
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ void ScrollTest::TestNotifyScrolling()
|
||||
Log::Comment(L"Watch out - this test takes a while to run, and won't "
|
||||
L"output anything unless in encounters an error. This is expected.");
|
||||
|
||||
auto& termTb = *_term->_buffer;
|
||||
auto& termTb = *_term->_mainBuffer;
|
||||
auto& termSm = *_term->_stateMachine;
|
||||
|
||||
const auto totalBufferSize = termTb.GetSize().Height();
|
||||
|
||||
@@ -138,29 +138,29 @@ void TerminalApiTest::CursorVisibility()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsBlinkingAllowed());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed());
|
||||
|
||||
term.SetCursorOn(false);
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_FALSE(term._buffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsBlinkingAllowed());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_FALSE(term._mainBuffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed());
|
||||
|
||||
term.SetCursorOn(true);
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsBlinkingAllowed());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed());
|
||||
|
||||
term.SetCursorVisibility(false);
|
||||
VERIFY_IS_FALSE(term._buffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsBlinkingAllowed());
|
||||
VERIFY_IS_FALSE(term._mainBuffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed());
|
||||
|
||||
term.SetCursorOn(false);
|
||||
VERIFY_IS_FALSE(term._buffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_FALSE(term._buffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._buffer->GetCursor().IsBlinkingAllowed());
|
||||
VERIFY_IS_FALSE(term._mainBuffer->GetCursor().IsVisible());
|
||||
VERIFY_IS_FALSE(term._mainBuffer->GetCursor().IsOn());
|
||||
VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed());
|
||||
}
|
||||
|
||||
void TerminalApiTest::CursorVisibilityViaStateMachine()
|
||||
@@ -170,7 +170,7 @@ void TerminalApiTest::CursorVisibilityViaStateMachine()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
auto& tbi = *(term._buffer);
|
||||
auto& tbi = *(term._mainBuffer);
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
auto& cursor = tbi.GetCursor();
|
||||
|
||||
@@ -222,7 +222,7 @@ void TerminalApiTest::CheckDoubleWidthCursor()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
auto& tbi = *(term._buffer);
|
||||
auto& tbi = *(term._mainBuffer);
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
auto& cursor = tbi.GetCursor();
|
||||
|
||||
@@ -266,7 +266,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
auto& tbi = *(term._buffer);
|
||||
auto& tbi = *(term._mainBuffer);
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
// Process the opening osc 8 sequence
|
||||
@@ -292,7 +292,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
auto& tbi = *(term._buffer);
|
||||
auto& tbi = *(term._mainBuffer);
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
// Process the opening osc 8 sequence
|
||||
@@ -320,7 +320,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
|
||||
DummyRenderer renderer{ &term };
|
||||
term.Create({ 100, 100 }, 0, renderer);
|
||||
|
||||
auto& tbi = *(term._buffer);
|
||||
auto& tbi = *(term._mainBuffer);
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
// Process the opening osc 8 sequence
|
||||
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
|
||||
void TerminalBufferTests::TestSimpleBufferWriting()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
|
||||
@@ -98,7 +98,7 @@ void TerminalBufferTests::TestSimpleBufferWriting()
|
||||
|
||||
void TerminalBufferTests::TestWrappingCharByChar()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
auto& cursor = termTb.GetCursor();
|
||||
@@ -137,7 +137,7 @@ void TerminalBufferTests::TestWrappingCharByChar()
|
||||
|
||||
void TerminalBufferTests::TestWrappingALongString()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
auto& cursor = termTb.GetCursor();
|
||||
@@ -171,7 +171,7 @@ void TerminalBufferTests::TestWrappingALongString()
|
||||
|
||||
void TerminalBufferTests::DontSnapToOutputTest()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
|
||||
@@ -253,7 +253,7 @@ void TerminalBufferTests::DontSnapToOutputTest()
|
||||
|
||||
void TerminalBufferTests::_SetTabStops(std::list<short> columns, bool replace)
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
auto& cursor = termTb.GetCursor();
|
||||
|
||||
@@ -275,7 +275,7 @@ void TerminalBufferTests::_SetTabStops(std::list<short> columns, bool replace)
|
||||
std::list<short> TerminalBufferTests::_GetTabStops()
|
||||
{
|
||||
std::list<short> columns;
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
const auto lastColumn = initialView.RightInclusive();
|
||||
@@ -321,7 +321,7 @@ void TerminalBufferTests::TestResetClearTabStops()
|
||||
|
||||
void TerminalBufferTests::TestAddTabStop()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
auto& cursor = termTb.GetCursor();
|
||||
|
||||
@@ -366,7 +366,7 @@ void TerminalBufferTests::TestAddTabStop()
|
||||
|
||||
void TerminalBufferTests::TestClearTabStop()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
auto& cursor = termTb.GetCursor();
|
||||
|
||||
@@ -475,7 +475,7 @@ void TerminalBufferTests::TestClearTabStop()
|
||||
|
||||
void TerminalBufferTests::TestGetForwardTab()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
const auto initialView = term->GetViewport();
|
||||
auto& cursor = termTb.GetCursor();
|
||||
@@ -545,7 +545,7 @@ void TerminalBufferTests::TestGetForwardTab()
|
||||
|
||||
void TerminalBufferTests::TestGetReverseTab()
|
||||
{
|
||||
auto& termTb = *term->_buffer;
|
||||
auto& termTb = *term->_mainBuffer;
|
||||
auto& termSm = *term->_stateMachine;
|
||||
auto& cursor = termTb.GetCursor();
|
||||
|
||||
|
||||
@@ -380,6 +380,16 @@ bool VtIo::IsUsingVt() const
|
||||
return hr;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT VtIo::SwitchScreenBuffer(const bool useAltBuffer)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (_pVtRenderEngine)
|
||||
{
|
||||
hr = _pVtRenderEngine->SwitchScreenBuffer(useAltBuffer);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void VtIo::CloseInput()
|
||||
{
|
||||
// This will release the lock when it goes out of scope
|
||||
|
||||
@@ -36,6 +36,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
[[nodiscard]] HRESULT SuppressResizeRepaint();
|
||||
[[nodiscard]] HRESULT SetCursorPosition(const COORD coordCursor);
|
||||
|
||||
[[nodiscard]] HRESULT SwitchScreenBuffer(const bool useAltBuffer);
|
||||
|
||||
void CloseInput();
|
||||
void CloseOutput();
|
||||
|
||||
|
||||
@@ -718,9 +718,8 @@ void SCREEN_INFORMATION::SetViewportSize(const COORD* const pcoordSize)
|
||||
|
||||
if (_psiMainBuffer)
|
||||
{
|
||||
const auto bufferSize = GetBufferSize().Dimensions();
|
||||
|
||||
_psiMainBuffer->SetViewportSize(&bufferSize);
|
||||
_psiMainBuffer->_fAltWindowChanged = false;
|
||||
_psiMainBuffer->_deferredPtyResize = til::size{ GetBufferSize().Dimensions() };
|
||||
}
|
||||
}
|
||||
_InternalSetViewportSize(pcoordSize, false, false);
|
||||
@@ -1489,6 +1488,8 @@ bool SCREEN_INFORMATION::IsMaximizedY() const
|
||||
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
|
||||
[[nodiscard]] NTSTATUS SCREEN_INFORMATION::ResizeTraditional(const COORD coordNewScreenSize)
|
||||
{
|
||||
_textBuffer->GetCursor().StartDeferDrawing();
|
||||
auto endDefer = wil::scope_exit([&]() noexcept { _textBuffer->GetCursor().EndDeferDrawing(); });
|
||||
return NTSTATUS_FROM_HRESULT(_textBuffer->ResizeTraditional(coordNewScreenSize));
|
||||
}
|
||||
|
||||
@@ -1532,7 +1533,15 @@ bool SCREEN_INFORMATION::IsMaximizedY() const
|
||||
CommandLine::Instance().EndAllPopups();
|
||||
|
||||
const bool fWrapText = gci.GetWrapText();
|
||||
if (fWrapText)
|
||||
// GH#3493: Don't reflow the alt buffer.
|
||||
//
|
||||
// VTE only rewraps the contents of the (normal screen + its scrollback
|
||||
// buffer) on a resize event. It doesn't rewrap the contents of the
|
||||
// alternate screen. The alternate screen is used by applications which
|
||||
// repaint it after a resize event. So it doesn't really matter. However, in
|
||||
// that short time window, after resizing the terminal but before the
|
||||
// application catches up, this prevents vertical lines
|
||||
if (fWrapText && !_IsAltBuffer())
|
||||
{
|
||||
status = ResizeWithReflow(coordNewScreenSize);
|
||||
}
|
||||
@@ -1942,6 +1951,15 @@ const SCREEN_INFORMATION& SCREEN_INFORMATION::GetMainBuffer() const
|
||||
s_RemoveScreenBuffer(psiOldAltBuffer); // this will also delete the old alt buffer
|
||||
}
|
||||
|
||||
// GH#381: When we switch into the alt buffer:
|
||||
// * flush the current frame, to clear out anything that we prepared for this buffer.
|
||||
// * Emit a ?1049h/l to the remote side, to let them know that we've switched buffers.
|
||||
if (gci.IsInVtIoMode() && ServiceLocator::LocateGlobals().pRender)
|
||||
{
|
||||
ServiceLocator::LocateGlobals().pRender->TriggerFlush(false);
|
||||
LOG_IF_FAILED(gci.GetVtIo()->SwitchScreenBuffer(true));
|
||||
}
|
||||
|
||||
::SetActiveScreenBuffer(*psiNewAltBuffer);
|
||||
|
||||
// Kind of a hack until we have proper signal channels: If the client app wants window size events, send one for
|
||||
@@ -1972,6 +1990,22 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
|
||||
psiMain->ProcessResizeWindow(&(psiMain->_rcAltSavedClientNew), &(psiMain->_rcAltSavedClientOld));
|
||||
psiMain->_fAltWindowChanged = false;
|
||||
}
|
||||
else if (_psiMainBuffer->_deferredPtyResize.has_value())
|
||||
{
|
||||
const COORD newSize = _psiMainBuffer->_deferredPtyResize.value().to_win32_coord();
|
||||
_psiMainBuffer->SetViewportSize(&newSize);
|
||||
_psiMainBuffer->_deferredPtyResize = std::nullopt;
|
||||
}
|
||||
|
||||
// GH#381: When we switch into the main buffer:
|
||||
// * flush the current frame, to clear out anything that we prepared for this buffer.
|
||||
// * Emit a ?1049h/l to the remote side, to let them know that we've switched buffers.
|
||||
if (gci.IsInVtIoMode() && ServiceLocator::LocateGlobals().pRender)
|
||||
{
|
||||
ServiceLocator::LocateGlobals().pRender->TriggerFlush(false);
|
||||
LOG_IF_FAILED(gci.GetVtIo()->SwitchScreenBuffer(false));
|
||||
}
|
||||
|
||||
::SetActiveScreenBuffer(*psiMain);
|
||||
psiMain->UpdateScrollBars(); // The alt had disabled scrollbars, re-enable them
|
||||
|
||||
|
||||
@@ -297,6 +297,8 @@ private:
|
||||
|
||||
bool _ignoreLegacyEquivalentVTAttributes;
|
||||
|
||||
std::optional<til::size> _deferredPtyResize{ std::nullopt };
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TextBufferIteratorTests;
|
||||
friend class ScreenBufferTests;
|
||||
|
||||
@@ -63,12 +63,6 @@ BgfxEngine::BgfxEngine(PVOID SharedViewBase, LONG DisplayHeight, LONG DisplayWid
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT BgfxEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT BgfxEngine::PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
*pForcePaint = false;
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
|
||||
@@ -130,7 +130,7 @@ constexpr HRESULT vec2_narrow(U x, U y, AtlasEngine::vec2<T>& out) noexcept
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT AtlasEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
[[nodiscard]] HRESULT AtlasEngine::InvalidateFlush(_In_ const bool /*circled*/, _Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint);
|
||||
*pForcePaint = false;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateTitle(std::wstring_view proposedTitle) noexcept override;
|
||||
[[nodiscard]] HRESULT NotifyNewText(const std::wstring_view newText) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override;
|
||||
|
||||
@@ -82,3 +82,19 @@ void RenderEngineBase::WaitUntilCanRender() noexcept
|
||||
// Throttle the render loop a bit by default (~60 FPS), improving throughput.
|
||||
Sleep(8);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Notifies us that we're about to circle the buffer, giving us a chance to
|
||||
// force a repaint before the buffer contents are lost.
|
||||
// - The default implementation of flush, is to do nothing for most renderers.
|
||||
// Arguments:
|
||||
// - circled - ignored
|
||||
// - pForcePaint - Always filled with false
|
||||
// Return Value:
|
||||
// - S_FALSE because we don't use this.
|
||||
[[nodiscard]] HRESULT RenderEngineBase::InvalidateFlush(_In_ const bool /*circled*/, _Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint);
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
@@ -456,14 +456,14 @@ void Renderer::TriggerScroll(const COORD* const pcoordDelta)
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Renderer::TriggerCircling()
|
||||
void Renderer::TriggerFlush(const bool circling)
|
||||
{
|
||||
const auto rects = _GetSelectionRects();
|
||||
|
||||
FOREACH_ENGINE(pEngine)
|
||||
{
|
||||
bool fEngineRequestsRepaint = false;
|
||||
HRESULT hr = pEngine->InvalidateCircling(&fEngineRequestsRepaint);
|
||||
HRESULT hr = pEngine->InvalidateFlush(circling, &fEngineRequestsRepaint);
|
||||
LOG_IF_FAILED(hr);
|
||||
|
||||
LOG_IF_FAILED(pEngine->InvalidateSelection(rects));
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Microsoft::Console::Render
|
||||
void TriggerScroll();
|
||||
void TriggerScroll(const COORD* const pcoordDelta);
|
||||
|
||||
void TriggerCircling();
|
||||
void TriggerFlush(const bool circling);
|
||||
void TriggerTitleChange();
|
||||
|
||||
void TriggerNewTextNotification(const std::wstring_view newText);
|
||||
|
||||
@@ -1200,20 +1200,6 @@ try
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
// Routine Description:
|
||||
// - This currently has no effect in this renderer.
|
||||
// Arguments:
|
||||
// - pForcePaint - Always filled with false
|
||||
// Return Value:
|
||||
// - 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;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Gets the area in pixels of the surface we are targeting
|
||||
// Arguments:
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
|
||||
@@ -109,21 +109,6 @@ HRESULT GdiEngine::InvalidateAll() noexcept
|
||||
RETURN_HR(InvalidateSystem(&rc));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Notifies us that we're about to circle the buffer, giving us a chance to
|
||||
// force a repaint before the buffer contents are lost. The GDI renderer
|
||||
// doesn't care if we lose text - we're only painting visible text anyways,
|
||||
// so we return false.
|
||||
// Arguments:
|
||||
// - Receives a bool indicating if we should force the repaint.
|
||||
// Return Value:
|
||||
// - S_FALSE - we succeeded, but the result was false.
|
||||
HRESULT GdiEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Notifies us that we're about to be torn down. This gives us a last chance
|
||||
// to force a repaint before the buffer contents are lost. The GDI renderer
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] virtual HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateScroll(const COORD* pcoordDelta) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateAll() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateCircling(_Out_ bool* pForcePaint) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateTitle(std::wstring_view proposedTitle) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT NotifyNewText(const std::wstring_view newText) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept = 0;
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace Microsoft::Console::Render
|
||||
|
||||
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
void WaitUntilCanRender() noexcept override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -168,20 +168,6 @@ CATCH_RETURN();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - This currently has no effect in this renderer.
|
||||
// Arguments:
|
||||
// - pForcePaint - Always filled with false
|
||||
// Return Value:
|
||||
// - S_FALSE because we don't use this.
|
||||
[[nodiscard]] HRESULT UiaEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint);
|
||||
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT UiaEngine::NotifyNewText(const std::wstring_view newText) noexcept
|
||||
try
|
||||
{
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT NotifyNewText(const std::wstring_view newText) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBackground() noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept override;
|
||||
|
||||
@@ -434,6 +434,17 @@ using namespace Microsoft::Console::Render;
|
||||
return _Write("\x1b[?9001h");
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Send a sequence to the connected terminal to switch to the alternate or main screen buffer.
|
||||
// Arguments:
|
||||
// - useAltBuffer: if true, switch to the malt buffer, otherwise to the main buffer.
|
||||
// Return Value:
|
||||
// - S_OK if we succeeded, else an appropriate HRESULT for failing to allocate or write.
|
||||
[[nodiscard]] HRESULT VtEngine::_SwitchScreenBuffer(const bool useAltBuffer) noexcept
|
||||
{
|
||||
return _Write(useAltBuffer ? "\x1b[?1049h" : "\x1b[?1049l");
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Formats and writes a sequence to add a hyperlink to the terminal buffer
|
||||
// Arguments:
|
||||
|
||||
@@ -105,7 +105,7 @@ CATCH_RETURN();
|
||||
// - Receives a bool indicating if we should force the repaint.
|
||||
// Return Value:
|
||||
// - S_OK
|
||||
[[nodiscard]] HRESULT VtEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
[[nodiscard]] HRESULT VtEngine::InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
// If we're in the middle of a resize request, don't try to immediately start a frame.
|
||||
if (_inResizeRequest)
|
||||
@@ -118,7 +118,7 @@ CATCH_RETURN();
|
||||
|
||||
// Keep track of the fact that we circled, we'll need to do some work on
|
||||
// end paint to specifically handle this.
|
||||
_circled = true;
|
||||
_circled = circled;
|
||||
}
|
||||
|
||||
_trace.TraceTriggerCircling(*pForcePaint);
|
||||
|
||||
@@ -527,3 +527,10 @@ HRESULT VtEngine::RequestWin32Input() noexcept
|
||||
RETURN_IF_FAILED(_Flush());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT VtEngine::SwitchScreenBuffer(const bool useAltBuffer) noexcept
|
||||
{
|
||||
RETURN_IF_FAILED(_SwitchScreenBuffer(useAltBuffer));
|
||||
RETURN_IF_FAILED(_Flush());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSystem(const RECT* prcDirtyClient) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBackground() noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> clusters, COORD coord, bool fTrimLeft, bool lineWrapped) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferGridLines(GridLineSet lines, COLORREF color, size_t cchLine, COORD coordTarget) noexcept override;
|
||||
@@ -85,6 +85,7 @@ namespace Microsoft::Console::Render
|
||||
void SetTerminalCursorTextPosition(const COORD coordCursor) noexcept;
|
||||
[[nodiscard]] virtual HRESULT ManuallyClearScrollback() noexcept;
|
||||
[[nodiscard]] HRESULT RequestWin32Input() noexcept;
|
||||
[[nodiscard]] HRESULT SwitchScreenBuffer(const bool useAltBuffer) noexcept;
|
||||
|
||||
protected:
|
||||
wil::unique_hfile _hFile;
|
||||
@@ -196,6 +197,7 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT _ListenForDSR() noexcept;
|
||||
|
||||
[[nodiscard]] HRESULT _RequestWin32Input() noexcept;
|
||||
[[nodiscard]] HRESULT _SwitchScreenBuffer(const bool useAltBuffer) noexcept;
|
||||
|
||||
[[nodiscard]] virtual HRESULT _MoveCursor(const COORD coord) noexcept = 0;
|
||||
[[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const TextAttribute& textAttributes) noexcept;
|
||||
|
||||
@@ -191,12 +191,6 @@ bool WddmConEngine::IsInitialized()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT WddmConEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
*pForcePaint = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT WddmConEngine::PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept
|
||||
{
|
||||
*pForcePaint = false;
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
|
||||
@@ -477,4 +477,14 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
|
||||
constexpr short s_sDECCOLMSetColumns = 132;
|
||||
constexpr short s_sDECCOLMResetColumns = 80;
|
||||
|
||||
struct MenuEntry
|
||||
{
|
||||
std::wstring _name;
|
||||
std::wstring _comment;
|
||||
std::wstring _input;
|
||||
MenuEntry(std::wstring_view name, std::wstring_view comment, std::wstring_view input) :
|
||||
_name{ name }, _comment{ comment }, _input{ input }
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ public:
|
||||
virtual bool EndHyperlink() = 0;
|
||||
|
||||
virtual bool DoConEmuAction(const std::wstring_view string) = 0;
|
||||
virtual bool DoWindowsTerminalAction(const std::wstring_view string) = 0;
|
||||
|
||||
virtual StringHandler DownloadDRCS(const size_t fontNumber,
|
||||
const VTParameter startChar,
|
||||
|
||||
@@ -2222,6 +2222,16 @@ bool AdaptDispatch::DoConEmuAction(const std::wstring_view /*string*/) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ascribes to the ITermDispatch interface
|
||||
// - Not actually used in conhost
|
||||
// Return Value:
|
||||
// - false (so that the command gets flushed to terminal)
|
||||
bool AdaptDispatch::DoWindowsTerminalAction(const std::wstring_view /*string*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - DECDLD - Downloads one or more characters of a dynamically redefinable
|
||||
// character set (DRCS) with a specified pixel pattern. The pixel array is
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
bool EndHyperlink() override;
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view string) noexcept override;
|
||||
bool DoWindowsTerminalAction(const std::wstring_view string) noexcept override;
|
||||
|
||||
StringHandler DownloadDRCS(const size_t fontNumber,
|
||||
const VTParameter startChar,
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
bool EndHyperlink() override { return false; }
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view /*string*/) override { return false; }
|
||||
bool DoWindowsTerminalAction(const std::wstring_view /*string*/) override { return false; }
|
||||
|
||||
StringHandler DownloadDRCS(const size_t /*fontNumber*/,
|
||||
const VTParameter /*startChar*/,
|
||||
|
||||
@@ -829,6 +829,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
||||
success = _dispatch->DoConEmuAction(string);
|
||||
break;
|
||||
}
|
||||
case OscActionCodes::WindowsTerminalAction:
|
||||
{
|
||||
success = _dispatch->DoWindowsTerminalAction(string);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// If no functions to call, overall dispatch was a failure.
|
||||
success = false;
|
||||
|
||||
@@ -184,7 +184,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
SetClipboard = 52,
|
||||
ResetForegroundColor = 110, // Not implemented
|
||||
ResetBackgroundColor = 111, // Not implemented
|
||||
ResetCursorColor = 112
|
||||
ResetCursorColor = 112,
|
||||
WindowsTerminalAction = 9001
|
||||
};
|
||||
|
||||
bool _GetOscTitle(const std::wstring_view string,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Scratch</RootNamespace>
|
||||
<ProjectName>Scratch</ProjectName>
|
||||
<TargetName>Scratch</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
@@ -21,6 +21,14 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- subsume fmt, one of our dependencies, into contypes. -->
|
||||
<ProjectReference Include="..\..\dep\fmt\fmt.vcxproj">
|
||||
<Project>{6bae5851-50d5-4934-8d5e-30361a8a40f3}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="..\..\common.build.post.props" />
|
||||
<Import Project="..\..\common.build.tests.props" />
|
||||
|
||||
@@ -1,10 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../inc/LibraryIncludes.h"
|
||||
|
||||
// #include <windows.h>
|
||||
// #include <stdio.h>
|
||||
// #include <iostream>
|
||||
|
||||
#define GS L"\x1D"
|
||||
#define US L"\x1F"
|
||||
#define DEL L"\x7F"
|
||||
#define ST L"\x07"
|
||||
|
||||
std::wstring trim(const std::wstring& str,
|
||||
const std::wstring& whitespace = L" \t")
|
||||
{
|
||||
const auto strBegin = str.find_first_not_of(whitespace);
|
||||
if (strBegin == std::wstring::npos)
|
||||
return L""; // no content
|
||||
|
||||
const auto strEnd = str.find_last_not_of(whitespace);
|
||||
const auto strRange = strEnd - strBegin + 1;
|
||||
|
||||
return str.substr(strBegin, strRange);
|
||||
}
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
|
||||
int __cdecl wmain(int argc, WCHAR* argv[])
|
||||
{
|
||||
wprintf(L"\x1b]9001;0\x07");
|
||||
|
||||
std::wstring prefix{};
|
||||
std::wstring suffix{};
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
std::wstring arg{ argv[i] };
|
||||
if (arg == L"--prefix" && (i + 1) <= argc)
|
||||
{
|
||||
prefix = argv[i + 1];
|
||||
i++;
|
||||
}
|
||||
else if (arg == L"--suffix" && (i + 1) <= argc)
|
||||
{
|
||||
suffix = argv[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::wstring line; std::getline(std::wcin, line);)
|
||||
{
|
||||
std::wstring trimmed{ trim(line) };
|
||||
std::wstring command{ fmt::format(L"{}{}{}", prefix, trimmed, suffix) };
|
||||
std::wstring entry{ fmt::format(L"\x1b]9001;1;{}\x7f{}\x7f{}\x7f{}\x07", trimmed, L"a comment", command, L"whatever extras we want") };
|
||||
wprintf(entry.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user