Compare commits
19 commits
main
...
dev/miniks
Author | SHA1 | Date | |
---|---|---|---|
466b80496d | |||
af2712b09e | |||
d2372342e2 | |||
e59f2b8477 | |||
60ef914956 | |||
cdc5a6a747 | |||
9b8c9d4f51 | |||
69538c4ab3 | |||
324c0942c8 | |||
c65161d60e | |||
b591355103 | |||
a1c1d5cc09 | |||
67d591b11d | |||
a692bb2f0f | |||
f00ffb0291 | |||
33e9a9b22a | |||
8114fa0dd0 | |||
00ca3f204c | |||
1ed8ef0847 |
|
@ -1,3 +1,4 @@
|
||||||
|
<!-- markdownlint-disable MD033 MD041 -->
|
||||||
<details>
|
<details>
|
||||||
<summary>
|
<summary>
|
||||||
:pencil2: Contributor please read this
|
:pencil2: Contributor please read this
|
||||||
|
@ -8,9 +9,10 @@ By default the command suggestion will generate a file named based on your commi
|
||||||
: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. 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...
|
||||||
|
|
||||||
If the listed items are:
|
If the listed items are:
|
||||||
|
|
||||||
* ... **misspelled**, then please *correct* them instead of using the command.
|
* ... **misspelled**, then please *correct* them instead of using the command.
|
||||||
* ... *names*, please add them to `.github/actions/spelling/dictionary/names.txt`.
|
* ... *names*, please add them to `.github/actions/spelling/allow/names.txt`.
|
||||||
* ... APIs, you can add them to a file in `.github/actions/spelling/dictionary/`.
|
* ... APIs, you can add them to a file in `.github/actions/spelling/allow/`.
|
||||||
* ... just things you're using, please add them to an appropriate file in `.github/actions/spelling/expect/`.
|
* ... just things you're using, please add them to an appropriate file in `.github/actions/spelling/expect/`.
|
||||||
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spelling/patterns/`.
|
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spelling/patterns/`.
|
||||||
|
|
||||||
|
@ -18,10 +20,31 @@ 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:
|
: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:
|
||||||
|
|
||||||
:clamp: If you see a bunch of garbage and it relates to a binary-ish string, please add a file path to the `.github/actions/spelling/excludes.txt` file instead of just accepting the garbage.
|
<details><summary>:clamp: If you see a bunch of garbage</summary>
|
||||||
|
|
||||||
|
If it relates to a ...
|
||||||
|
<details><summary>well-formed pattern</summary>
|
||||||
|
|
||||||
|
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
|
||||||
|
|
||||||
|
If not, try writing one and adding it to a `patterns/{file}.txt`.
|
||||||
|
|
||||||
|
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.
|
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](https://github.com/microsoft/terminal/blob/main/README.md) (on whichever branch you're using).
|
`^` 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>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
</details>
|
</details>
|
|
@ -1,4 +1,4 @@
|
||||||
# Dictionaries are lists of words to accept unconditionally
|
# Allow files are lists of words to accept unconditionally
|
||||||
|
|
||||||
While check spelling will complain about an expected word
|
While check spelling will complain about an expected word
|
||||||
which is no longer present, you can include things here even if
|
which is no longer present, you can include things here even if
|
||||||
|
@ -8,11 +8,11 @@ E.g., you could include a list of system APIs here, or potential
|
||||||
contributors (so that if a future commit includes their name,
|
contributors (so that if a future commit includes their name,
|
||||||
it'll be accepted).
|
it'll be accepted).
|
||||||
|
|
||||||
### Files
|
## Files
|
||||||
|
|
||||||
| File | Description |
|
| File | Description |
|
||||||
| ---- | ----------- |
|
| ---- | ----------- |
|
||||||
| [Dictionary](dictionary.txt) | Primary US English dictionary |
|
| [Allow](allow.txt) | Supplements to the dictionary |
|
||||||
| [Chinese](chinese.txt) | Chinese words |
|
| [Chinese](chinese.txt) | Chinese words |
|
||||||
| [Japanese](japanese.txt) | Japanese words |
|
| [Japanese](japanese.txt) | Japanese words |
|
||||||
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
77
.github/actions/spelling/allow/allow.txt
vendored
Normal file
77
.github/actions/spelling/allow/allow.txt
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
apc
|
||||||
|
calt
|
||||||
|
ccmp
|
||||||
|
changelog
|
||||||
|
cybersecurity
|
||||||
|
Apc
|
||||||
|
clickable
|
||||||
|
clig
|
||||||
|
copyable
|
||||||
|
dalet
|
||||||
|
dcs
|
||||||
|
Dcs
|
||||||
|
dialytika
|
||||||
|
dje
|
||||||
|
downside
|
||||||
|
downsides
|
||||||
|
dze
|
||||||
|
dzhe
|
||||||
|
Enum'd
|
||||||
|
Fitt
|
||||||
|
formattings
|
||||||
|
ftp
|
||||||
|
fvar
|
||||||
|
geeksforgeeks
|
||||||
|
ghe
|
||||||
|
gje
|
||||||
|
hostname
|
||||||
|
hostnames
|
||||||
|
hyperlink
|
||||||
|
hyperlinking
|
||||||
|
hyperlinks
|
||||||
|
img
|
||||||
|
It'd
|
||||||
|
kje
|
||||||
|
liga
|
||||||
|
lje
|
||||||
|
locl
|
||||||
|
lorem
|
||||||
|
Llast
|
||||||
|
Lmid
|
||||||
|
Lorigin
|
||||||
|
maxed
|
||||||
|
mkmk
|
||||||
|
mru
|
||||||
|
noreply
|
||||||
|
nje
|
||||||
|
ogonek
|
||||||
|
ok'd
|
||||||
|
overlined
|
||||||
|
postmodern
|
||||||
|
ptys
|
||||||
|
qof
|
||||||
|
qps
|
||||||
|
rclt
|
||||||
|
reimplementation
|
||||||
|
reserialization
|
||||||
|
reserialize
|
||||||
|
reserializes
|
||||||
|
rlig
|
||||||
|
runtimes
|
||||||
|
shcha
|
||||||
|
slnt
|
||||||
|
Sos
|
||||||
|
timestamped
|
||||||
|
TLDR
|
||||||
|
tokenizes
|
||||||
|
tonos
|
||||||
|
tshe
|
||||||
|
uiatextrange
|
||||||
|
UIs
|
||||||
|
und
|
||||||
|
unregister
|
||||||
|
versioned
|
||||||
|
We'd
|
||||||
|
wildcards
|
||||||
|
yeru
|
||||||
|
zhe
|
|
@ -1,19 +1,37 @@
|
||||||
ACCEPTFILES
|
ACCEPTFILES
|
||||||
ACCESSDENIED
|
ACCESSDENIED
|
||||||
|
alignas
|
||||||
alignof
|
alignof
|
||||||
|
APPLYTOSUBMENUS
|
||||||
bitfield
|
bitfield
|
||||||
bitfields
|
bitfields
|
||||||
|
BUILDBRANCH
|
||||||
|
BUILDMSG
|
||||||
|
BUILDNUMBER
|
||||||
|
BYPOSITION
|
||||||
|
charconv
|
||||||
CLASSNOTAVAILABLE
|
CLASSNOTAVAILABLE
|
||||||
cmdletbinding
|
cmdletbinding
|
||||||
COLORPROPERTY
|
COLORPROPERTY
|
||||||
|
colspan
|
||||||
|
COMDLG
|
||||||
|
comparand
|
||||||
|
cstdint
|
||||||
CXICON
|
CXICON
|
||||||
CYICON
|
CYICON
|
||||||
D2DERR_SHADER_COMPILE_FAILED
|
|
||||||
dataobject
|
dataobject
|
||||||
|
dcomp
|
||||||
DERR
|
DERR
|
||||||
|
dlldata
|
||||||
|
DONTADDTORECENT
|
||||||
|
DWORDLONG
|
||||||
|
enumset
|
||||||
environstrings
|
environstrings
|
||||||
EXPCMDFLAGS
|
EXPCMDFLAGS
|
||||||
EXPCMDSTATE
|
EXPCMDSTATE
|
||||||
|
filetime
|
||||||
|
FILTERSPEC
|
||||||
|
FORCEFILESYSTEM
|
||||||
FORCEMINIMIZE
|
FORCEMINIMIZE
|
||||||
frac
|
frac
|
||||||
fullkbd
|
fullkbd
|
||||||
|
@ -23,7 +41,9 @@ GETHIGHCONTRAST
|
||||||
Hashtable
|
Hashtable
|
||||||
HIGHCONTRASTON
|
HIGHCONTRASTON
|
||||||
HIGHCONTRASTW
|
HIGHCONTRASTW
|
||||||
|
hotkeys
|
||||||
href
|
href
|
||||||
|
hrgn
|
||||||
IActivation
|
IActivation
|
||||||
IApp
|
IApp
|
||||||
IAppearance
|
IAppearance
|
||||||
|
@ -31,90 +51,144 @@ IAsync
|
||||||
IBind
|
IBind
|
||||||
IBox
|
IBox
|
||||||
IClass
|
IClass
|
||||||
IConnection
|
|
||||||
IComparable
|
IComparable
|
||||||
|
IComparer
|
||||||
|
IConnection
|
||||||
ICustom
|
ICustom
|
||||||
IDialog
|
IDialog
|
||||||
IDirect
|
IDirect
|
||||||
IExplorer
|
IExplorer
|
||||||
|
IFACEMETHOD
|
||||||
|
IFile
|
||||||
IInheritable
|
IInheritable
|
||||||
IMap
|
IMap
|
||||||
IObject
|
IObject
|
||||||
|
iosfwd
|
||||||
IPackage
|
IPackage
|
||||||
IPeasant
|
IPeasant
|
||||||
|
isspace
|
||||||
|
ISetup
|
||||||
IStorage
|
IStorage
|
||||||
istream
|
istream
|
||||||
IStringable
|
IStringable
|
||||||
ITab
|
ITab
|
||||||
ITaskbar
|
ITaskbar
|
||||||
|
IUri
|
||||||
IVirtual
|
IVirtual
|
||||||
|
KEYSELECT
|
||||||
LCID
|
LCID
|
||||||
llabs
|
llabs
|
||||||
llu
|
llu
|
||||||
localtime
|
localtime
|
||||||
lround
|
lround
|
||||||
LSHIFT
|
LSHIFT
|
||||||
MULTIPLEUSE
|
MENUCOMMAND
|
||||||
|
MENUDATA
|
||||||
|
MENUINFO
|
||||||
|
memicmp
|
||||||
|
mptt
|
||||||
|
mov
|
||||||
msappx
|
msappx
|
||||||
MULTIPLEUSE
|
MULTIPLEUSE
|
||||||
NCHITTEST
|
NCHITTEST
|
||||||
NCLBUTTONDBLCLK
|
NCLBUTTONDBLCLK
|
||||||
NCRBUTTONDBLCLK
|
NCRBUTTONDBLCLK
|
||||||
|
NIF
|
||||||
|
NIN
|
||||||
NOAGGREGATION
|
NOAGGREGATION
|
||||||
NOASYNC
|
NOASYNC
|
||||||
|
NOCHANGEDIR
|
||||||
NOPROGRESS
|
NOPROGRESS
|
||||||
NOREDIRECTIONBITMAP
|
NOREDIRECTIONBITMAP
|
||||||
|
NOREPEAT
|
||||||
|
NOTIFYBYPOS
|
||||||
|
NOTIFYICON
|
||||||
|
NOTIFYICONDATA
|
||||||
ntprivapi
|
ntprivapi
|
||||||
oaidl
|
oaidl
|
||||||
ocidl
|
ocidl
|
||||||
|
ODR
|
||||||
|
offsetof
|
||||||
|
osver
|
||||||
|
OSVERSIONINFOEXW
|
||||||
otms
|
otms
|
||||||
OUTLINETEXTMETRICW
|
OUTLINETEXTMETRICW
|
||||||
overridable
|
overridable
|
||||||
PAGESCROLL
|
PAGESCROLL
|
||||||
|
PICKFOLDERS
|
||||||
pmr
|
pmr
|
||||||
|
rcx
|
||||||
REGCLS
|
REGCLS
|
||||||
RETURNCMD
|
RETURNCMD
|
||||||
REGCLS
|
|
||||||
rfind
|
rfind
|
||||||
roundf
|
roundf
|
||||||
RSHIFT
|
RSHIFT
|
||||||
rx
|
|
||||||
schandle
|
schandle
|
||||||
semver
|
semver
|
||||||
serializer
|
serializer
|
||||||
|
SETVERSION
|
||||||
|
SHELLEXECUTEINFOW
|
||||||
shobjidl
|
shobjidl
|
||||||
SHOWMINIMIZED
|
SHOWMINIMIZED
|
||||||
|
SHOWTIP
|
||||||
|
SINGLEUSE
|
||||||
SIZENS
|
SIZENS
|
||||||
smoothstep
|
smoothstep
|
||||||
GETDESKWALLPAPER
|
|
||||||
SHELLEXECUTEINFOW
|
|
||||||
snprintf
|
snprintf
|
||||||
spsc
|
spsc
|
||||||
sregex
|
sregex
|
||||||
|
SRWLOC
|
||||||
|
SRWLOCK
|
||||||
STDCPP
|
STDCPP
|
||||||
|
STDMETHOD
|
||||||
strchr
|
strchr
|
||||||
|
strcpy
|
||||||
|
streambuf
|
||||||
|
strtoul
|
||||||
|
Stubless
|
||||||
Subheader
|
Subheader
|
||||||
Subpage
|
Subpage
|
||||||
UPDATEINIFILE
|
|
||||||
syscall
|
syscall
|
||||||
|
TASKBARCREATED
|
||||||
TBPF
|
TBPF
|
||||||
THEMECHANGED
|
THEMECHANGED
|
||||||
|
tlg
|
||||||
tmp
|
tmp
|
||||||
tolower
|
tolower
|
||||||
|
toupper
|
||||||
TTask
|
TTask
|
||||||
TVal
|
TVal
|
||||||
tx
|
UChar
|
||||||
UPDATEINIFILE
|
UPDATEINIFILE
|
||||||
userenv
|
userenv
|
||||||
wcsstr
|
wcsstr
|
||||||
wcstoui
|
wcstoui
|
||||||
|
winmain
|
||||||
|
wmemcmp
|
||||||
wpc
|
wpc
|
||||||
wsregex
|
wsregex
|
||||||
|
wwinmain
|
||||||
|
xchg
|
||||||
XDocument
|
XDocument
|
||||||
XElement
|
XElement
|
||||||
|
xfacet
|
||||||
|
xhash
|
||||||
|
XIcon
|
||||||
|
xiosbase
|
||||||
|
xlocale
|
||||||
|
xlocbuf
|
||||||
|
xlocinfo
|
||||||
xlocmes
|
xlocmes
|
||||||
xlocmon
|
xlocmon
|
||||||
xlocnum
|
xlocnum
|
||||||
xloctime
|
xloctime
|
||||||
|
XMax
|
||||||
|
xmemory
|
||||||
XParse
|
XParse
|
||||||
|
xpath
|
||||||
|
xstddef
|
||||||
xstring
|
xstring
|
||||||
|
xtree
|
||||||
|
xutility
|
||||||
|
YIcon
|
||||||
|
YMax
|
117
.github/actions/spelling/allow/colors.txt
vendored
Normal file
117
.github/actions/spelling/allow/colors.txt
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
alice
|
||||||
|
aliceblue
|
||||||
|
antiquewhite
|
||||||
|
blanchedalmond
|
||||||
|
blueviolet
|
||||||
|
burlywood
|
||||||
|
cadetblue
|
||||||
|
cornflowerblue
|
||||||
|
cornsilk
|
||||||
|
cyan
|
||||||
|
darkblue
|
||||||
|
darkcyan
|
||||||
|
darkgoldenrod
|
||||||
|
darkgray
|
||||||
|
darkgreen
|
||||||
|
darkgrey
|
||||||
|
darkkhaki
|
||||||
|
darkmagenta
|
||||||
|
darkolivegreen
|
||||||
|
darkorange
|
||||||
|
darkorchid
|
||||||
|
darkred
|
||||||
|
darksalmon
|
||||||
|
darkseagreen
|
||||||
|
darkslateblue
|
||||||
|
darkslategray
|
||||||
|
darkslategrey
|
||||||
|
darkturquoise
|
||||||
|
darkviolet
|
||||||
|
deeppink
|
||||||
|
deepskyblue
|
||||||
|
dimgray
|
||||||
|
dimgrey
|
||||||
|
dodgerblue
|
||||||
|
firebrick
|
||||||
|
floralwhite
|
||||||
|
forestgreen
|
||||||
|
gainsboro
|
||||||
|
ghostwhite
|
||||||
|
greenyellow
|
||||||
|
hotpink
|
||||||
|
indian
|
||||||
|
indianred
|
||||||
|
lavenderblush
|
||||||
|
lawngreen
|
||||||
|
lemonchiffon
|
||||||
|
lightblue
|
||||||
|
lightcoral
|
||||||
|
lightcyan
|
||||||
|
lightgoldenrod
|
||||||
|
lightgoldenrodyellow
|
||||||
|
lightgray
|
||||||
|
lightgreen
|
||||||
|
lightgrey
|
||||||
|
lightpink
|
||||||
|
lightsalmon
|
||||||
|
lightseagreen
|
||||||
|
lightskyblue
|
||||||
|
lightslateblue
|
||||||
|
lightslategray
|
||||||
|
lightslategrey
|
||||||
|
lightsteelblue
|
||||||
|
lightyellow
|
||||||
|
limegreen
|
||||||
|
mediumaquamarine
|
||||||
|
mediumblue
|
||||||
|
mediumorchid
|
||||||
|
mediumpurple
|
||||||
|
mediumseagreen
|
||||||
|
mediumslateblue
|
||||||
|
mediumspringgreen
|
||||||
|
mediumturquoise
|
||||||
|
mediumvioletred
|
||||||
|
midnightblue
|
||||||
|
mintcream
|
||||||
|
mistyrose
|
||||||
|
navajo
|
||||||
|
navajowhite
|
||||||
|
navyblue
|
||||||
|
oldlace
|
||||||
|
olivedrab
|
||||||
|
orangered
|
||||||
|
palegoldenrod
|
||||||
|
palegreen
|
||||||
|
paleturquoise
|
||||||
|
palevioletred
|
||||||
|
papayawhip
|
||||||
|
peachpuff
|
||||||
|
peru
|
||||||
|
powderblue
|
||||||
|
rebecca
|
||||||
|
rebeccapurple
|
||||||
|
rosybrown
|
||||||
|
royalblue
|
||||||
|
saddlebrown
|
||||||
|
sandybrown
|
||||||
|
seagreen
|
||||||
|
sienna
|
||||||
|
skyblue
|
||||||
|
slateblue
|
||||||
|
slategray
|
||||||
|
slategrey
|
||||||
|
springgreen
|
||||||
|
steelblue
|
||||||
|
violetred
|
||||||
|
webgray
|
||||||
|
webgreen
|
||||||
|
webgrey
|
||||||
|
webmaroon
|
||||||
|
webpurple
|
||||||
|
whitesmoke
|
||||||
|
xaroon
|
||||||
|
xray
|
||||||
|
xreen
|
||||||
|
xrey
|
||||||
|
xurple
|
||||||
|
yellowgreen
|
|
@ -7,3 +7,4 @@ Iosevka
|
||||||
MDL
|
MDL
|
||||||
Monofur
|
Monofur
|
||||||
Segoe
|
Segoe
|
||||||
|
wght
|
11
.github/actions/spelling/allow/math.txt
vendored
Normal file
11
.github/actions/spelling/allow/math.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
atan
|
||||||
|
CPrime
|
||||||
|
HBar
|
||||||
|
HPrime
|
||||||
|
isnan
|
||||||
|
LPrime
|
||||||
|
LStep
|
||||||
|
powf
|
||||||
|
RSub
|
||||||
|
sqrtf
|
||||||
|
ULP
|
|
@ -1,15 +1,22 @@
|
||||||
ACLs
|
ACLs
|
||||||
ADMINS
|
ADMINS
|
||||||
|
advapi
|
||||||
altform
|
altform
|
||||||
altforms
|
altforms
|
||||||
appendwttlogging
|
appendwttlogging
|
||||||
|
appx
|
||||||
|
appxbundle
|
||||||
|
appxerror
|
||||||
|
appxmanifest
|
||||||
|
ATL
|
||||||
backplating
|
backplating
|
||||||
bitmaps
|
bitmaps
|
||||||
BOMs
|
BOMs
|
||||||
CPLs
|
CPLs
|
||||||
CPRs
|
|
||||||
cpptools
|
cpptools
|
||||||
cppvsdbg
|
cppvsdbg
|
||||||
|
CPRs
|
||||||
|
cryptbase
|
||||||
DACL
|
DACL
|
||||||
DACLs
|
DACLs
|
||||||
diffs
|
diffs
|
||||||
|
@ -19,14 +26,20 @@ DTDs
|
||||||
DWINRT
|
DWINRT
|
||||||
enablewttlogging
|
enablewttlogging
|
||||||
Intelli
|
Intelli
|
||||||
|
IVisual
|
||||||
LKG
|
LKG
|
||||||
|
LOCKFILE
|
||||||
|
Lxss
|
||||||
mfcribbon
|
mfcribbon
|
||||||
microsoft
|
microsoft
|
||||||
microsoftonline
|
microsoftonline
|
||||||
|
MSAA
|
||||||
msixbundle
|
msixbundle
|
||||||
|
MSVC
|
||||||
muxc
|
muxc
|
||||||
netcore
|
netcore
|
||||||
osgvsowi
|
osgvsowi
|
||||||
|
PFILETIME
|
||||||
pgc
|
pgc
|
||||||
pgo
|
pgo
|
||||||
pgosweep
|
pgosweep
|
||||||
|
@ -34,20 +47,29 @@ powerrename
|
||||||
powershell
|
powershell
|
||||||
propkey
|
propkey
|
||||||
pscustomobject
|
pscustomobject
|
||||||
|
QWORD
|
||||||
|
regedit
|
||||||
robocopy
|
robocopy
|
||||||
SACLs
|
SACLs
|
||||||
|
sdkddkver
|
||||||
Shobjidl
|
Shobjidl
|
||||||
Skype
|
Skype
|
||||||
|
SRW
|
||||||
|
sxs
|
||||||
|
Sysinternals
|
||||||
sysnative
|
sysnative
|
||||||
systemroot
|
systemroot
|
||||||
taskkill
|
taskkill
|
||||||
tasklist
|
tasklist
|
||||||
tdbuildteamid
|
tdbuildteamid
|
||||||
|
unvirtualized
|
||||||
VCRT
|
VCRT
|
||||||
vcruntime
|
vcruntime
|
||||||
|
Virtualization
|
||||||
visualstudio
|
visualstudio
|
||||||
vscode
|
vscode
|
||||||
VSTHRD
|
VSTHRD
|
||||||
|
winsdkver
|
||||||
wlk
|
wlk
|
||||||
wslpath
|
wslpath
|
||||||
wtl
|
wtl
|
|
@ -13,6 +13,7 @@ ethanschoonover
|
||||||
Firefox
|
Firefox
|
||||||
Gatta
|
Gatta
|
||||||
glsl
|
glsl
|
||||||
|
Gravell
|
||||||
Grie
|
Grie
|
||||||
Griese
|
Griese
|
||||||
Hernan
|
Hernan
|
||||||
|
@ -30,6 +31,7 @@ Kourosh
|
||||||
kowalczyk
|
kowalczyk
|
||||||
leonmsft
|
leonmsft
|
||||||
Lepilleur
|
Lepilleur
|
||||||
|
lhecker
|
||||||
lukesampson
|
lukesampson
|
||||||
Manandhar
|
Manandhar
|
||||||
mbadolato
|
mbadolato
|
||||||
|
@ -51,6 +53,7 @@ oldnewthing
|
||||||
opengl
|
opengl
|
||||||
osgwiki
|
osgwiki
|
||||||
pabhojwa
|
pabhojwa
|
||||||
|
panos
|
||||||
paulcam
|
paulcam
|
||||||
pauldotknopf
|
pauldotknopf
|
||||||
PGP
|
PGP
|
||||||
|
@ -65,12 +68,13 @@ sonpham
|
||||||
stakx
|
stakx
|
||||||
thereses
|
thereses
|
||||||
Walisch
|
Walisch
|
||||||
|
Wellons
|
||||||
Wirt
|
Wirt
|
||||||
Wojciech
|
Wojciech
|
||||||
zadjii
|
zadjii
|
||||||
Zamor
|
Zamor
|
||||||
zamora
|
|
||||||
Zamora
|
Zamora
|
||||||
|
zamora
|
||||||
Zoey
|
Zoey
|
||||||
zorio
|
zorio
|
||||||
Zverovich
|
Zverovich
|
782
.github/actions/spelling/dictionary/colors.txt
vendored
782
.github/actions/spelling/dictionary/colors.txt
vendored
|
@ -1,782 +0,0 @@
|
||||||
snow
|
|
||||||
ghost-white
|
|
||||||
ghostwhite
|
|
||||||
white-smoke
|
|
||||||
whitesmoke
|
|
||||||
gainsboro
|
|
||||||
floral-white
|
|
||||||
floralwhite
|
|
||||||
old-lace
|
|
||||||
oldlace
|
|
||||||
linen
|
|
||||||
antique-white
|
|
||||||
antiquewhite
|
|
||||||
papaya-whip
|
|
||||||
papayawhip
|
|
||||||
blanched-almond
|
|
||||||
blanchedalmond
|
|
||||||
bisque
|
|
||||||
peach-puff
|
|
||||||
peachpuff
|
|
||||||
navajo-white
|
|
||||||
navajowhite
|
|
||||||
moccasin
|
|
||||||
cornsilk
|
|
||||||
ivory
|
|
||||||
lemon-chiffon
|
|
||||||
lemonchiffon
|
|
||||||
seashell
|
|
||||||
honeydew
|
|
||||||
mint-cream
|
|
||||||
mintcream
|
|
||||||
azure
|
|
||||||
alice-blue
|
|
||||||
aliceblue
|
|
||||||
lavender
|
|
||||||
lavender-blush
|
|
||||||
lavenderblush
|
|
||||||
misty-rose
|
|
||||||
mistyrose
|
|
||||||
white
|
|
||||||
black
|
|
||||||
dark-slate-gray
|
|
||||||
darkslategray
|
|
||||||
dark-slate-grey
|
|
||||||
darkslategrey
|
|
||||||
dim-gray
|
|
||||||
dimgray
|
|
||||||
dim-grey
|
|
||||||
dimgrey
|
|
||||||
slate-gray
|
|
||||||
slategray
|
|
||||||
slate-grey
|
|
||||||
slategrey
|
|
||||||
light-slate-gray
|
|
||||||
lightslategray
|
|
||||||
light-slate-grey
|
|
||||||
lightslategrey
|
|
||||||
gray
|
|
||||||
grey
|
|
||||||
xray
|
|
||||||
x11gray
|
|
||||||
xrey
|
|
||||||
x11grey
|
|
||||||
web-gray
|
|
||||||
webgray
|
|
||||||
web-grey
|
|
||||||
webgrey
|
|
||||||
light-grey
|
|
||||||
lightgrey
|
|
||||||
light-gray
|
|
||||||
lightgray
|
|
||||||
midnight-blue
|
|
||||||
midnightblue
|
|
||||||
navy
|
|
||||||
navy-blue
|
|
||||||
navyblue
|
|
||||||
cornflower-blue
|
|
||||||
cornflowerblue
|
|
||||||
dark-slate-blue
|
|
||||||
darkslateblue
|
|
||||||
slate-blue
|
|
||||||
slateblue
|
|
||||||
medium-slate-blue
|
|
||||||
mediumslateblue
|
|
||||||
light-slate-blue
|
|
||||||
lightslateblue
|
|
||||||
medium-blue
|
|
||||||
mediumblue
|
|
||||||
royal-blue
|
|
||||||
royalblue
|
|
||||||
blue
|
|
||||||
dodger-blue
|
|
||||||
dodgerblue
|
|
||||||
deep-sky-blue
|
|
||||||
deepskyblue
|
|
||||||
sky-blue
|
|
||||||
skyblue
|
|
||||||
light-sky-blue
|
|
||||||
lightskyblue
|
|
||||||
steel-blue
|
|
||||||
steelblue
|
|
||||||
light-steel-blue
|
|
||||||
lightsteelblue
|
|
||||||
light-blue
|
|
||||||
lightblue
|
|
||||||
powder-blue
|
|
||||||
powderblue
|
|
||||||
pale-turquoise
|
|
||||||
paleturquoise
|
|
||||||
dark-turquoise
|
|
||||||
darkturquoise
|
|
||||||
medium-turquoise
|
|
||||||
mediumturquoise
|
|
||||||
turquoise
|
|
||||||
cyan
|
|
||||||
aqua
|
|
||||||
light-cyan
|
|
||||||
lightcyan
|
|
||||||
cadet-blue
|
|
||||||
cadetblue
|
|
||||||
medium-aquamarine
|
|
||||||
mediumaquamarine
|
|
||||||
aquamarine
|
|
||||||
dark-green
|
|
||||||
darkgreen
|
|
||||||
dark-olive-green
|
|
||||||
darkolivegreen
|
|
||||||
dark-sea-green
|
|
||||||
darkseagreen
|
|
||||||
sea-green
|
|
||||||
seagreen
|
|
||||||
medium-sea-green
|
|
||||||
mediumseagreen
|
|
||||||
light-sea-green
|
|
||||||
lightseagreen
|
|
||||||
pale-green
|
|
||||||
palegreen
|
|
||||||
spring-green
|
|
||||||
springgreen
|
|
||||||
lawn-green
|
|
||||||
lawngreen
|
|
||||||
green
|
|
||||||
lime
|
|
||||||
xreen
|
|
||||||
x11green
|
|
||||||
web-green
|
|
||||||
webgreen
|
|
||||||
chartreuse
|
|
||||||
medium-spring-green
|
|
||||||
mediumspringgreen
|
|
||||||
green-yellow
|
|
||||||
greenyellow
|
|
||||||
lime-green
|
|
||||||
limegreen
|
|
||||||
yellow-green
|
|
||||||
yellowgreen
|
|
||||||
forest-green
|
|
||||||
forestgreen
|
|
||||||
olive-drab
|
|
||||||
olivedrab
|
|
||||||
dark-khaki
|
|
||||||
darkkhaki
|
|
||||||
khaki
|
|
||||||
pale-goldenrod
|
|
||||||
palegoldenrod
|
|
||||||
light-goldenrod-yellow
|
|
||||||
lightgoldenrodyellow
|
|
||||||
light-yellow
|
|
||||||
lightyellow
|
|
||||||
yellow
|
|
||||||
gold
|
|
||||||
light-goldenrod
|
|
||||||
lightgoldenrod
|
|
||||||
goldenrod
|
|
||||||
dark-goldenrod
|
|
||||||
darkgoldenrod
|
|
||||||
rosy-brown
|
|
||||||
rosybrown
|
|
||||||
indian-red
|
|
||||||
indianred
|
|
||||||
saddle-brown
|
|
||||||
saddlebrown
|
|
||||||
sienna
|
|
||||||
peru
|
|
||||||
burlywood
|
|
||||||
beige
|
|
||||||
wheat
|
|
||||||
sandy-brown
|
|
||||||
sandybrown
|
|
||||||
tan
|
|
||||||
chocolate
|
|
||||||
firebrick
|
|
||||||
brown
|
|
||||||
dark-salmon
|
|
||||||
darksalmon
|
|
||||||
salmon
|
|
||||||
light-salmon
|
|
||||||
lightsalmon
|
|
||||||
orange
|
|
||||||
dark-orange
|
|
||||||
darkorange
|
|
||||||
coral
|
|
||||||
light-coral
|
|
||||||
lightcoral
|
|
||||||
tomato
|
|
||||||
orange-red
|
|
||||||
orangered
|
|
||||||
red
|
|
||||||
hot-pink
|
|
||||||
hotpink
|
|
||||||
deep-pink
|
|
||||||
deeppink
|
|
||||||
pink
|
|
||||||
light-pink
|
|
||||||
lightpink
|
|
||||||
pale-violet-red
|
|
||||||
palevioletred
|
|
||||||
maroon
|
|
||||||
xaroon
|
|
||||||
x11maroon
|
|
||||||
web-maroon
|
|
||||||
webmaroon
|
|
||||||
medium-violet-red
|
|
||||||
mediumvioletred
|
|
||||||
violet-red
|
|
||||||
violetred
|
|
||||||
magenta
|
|
||||||
fuchsia
|
|
||||||
violet
|
|
||||||
plum
|
|
||||||
orchid
|
|
||||||
medium-orchid
|
|
||||||
mediumorchid
|
|
||||||
dark-orchid
|
|
||||||
darkorchid
|
|
||||||
dark-violet
|
|
||||||
darkviolet
|
|
||||||
blue-violet
|
|
||||||
blueviolet
|
|
||||||
purple
|
|
||||||
xurple
|
|
||||||
x11purple
|
|
||||||
web-purple
|
|
||||||
webpurple
|
|
||||||
medium-purple
|
|
||||||
mediumpurple
|
|
||||||
thistle
|
|
||||||
snow1
|
|
||||||
snow2
|
|
||||||
snow3
|
|
||||||
snow4
|
|
||||||
seashell1
|
|
||||||
seashell2
|
|
||||||
seashell3
|
|
||||||
seashell4
|
|
||||||
antiquewhite1
|
|
||||||
antiquewhite2
|
|
||||||
antiquewhite3
|
|
||||||
antiquewhite4
|
|
||||||
bisque1
|
|
||||||
bisque2
|
|
||||||
bisque3
|
|
||||||
bisque4
|
|
||||||
peachpuff1
|
|
||||||
peachpuff2
|
|
||||||
peachpuff3
|
|
||||||
peachpuff4
|
|
||||||
navajowhite1
|
|
||||||
navajowhite2
|
|
||||||
navajowhite3
|
|
||||||
navajowhite4
|
|
||||||
lemonchiffon1
|
|
||||||
lemonchiffon2
|
|
||||||
lemonchiffon3
|
|
||||||
lemonchiffon4
|
|
||||||
cornsilk1
|
|
||||||
cornsilk2
|
|
||||||
cornsilk3
|
|
||||||
cornsilk4
|
|
||||||
ivory1
|
|
||||||
ivory2
|
|
||||||
ivory3
|
|
||||||
ivory4
|
|
||||||
honeydew1
|
|
||||||
honeydew2
|
|
||||||
honeydew3
|
|
||||||
honeydew4
|
|
||||||
lavenderblush1
|
|
||||||
lavenderblush2
|
|
||||||
lavenderblush3
|
|
||||||
lavenderblush4
|
|
||||||
mistyrose1
|
|
||||||
mistyrose2
|
|
||||||
mistyrose3
|
|
||||||
mistyrose4
|
|
||||||
azure1
|
|
||||||
azure2
|
|
||||||
azure3
|
|
||||||
azure4
|
|
||||||
slateblue1
|
|
||||||
slateblue2
|
|
||||||
slateblue3
|
|
||||||
slateblue4
|
|
||||||
royalblue1
|
|
||||||
royalblue2
|
|
||||||
royalblue3
|
|
||||||
royalblue4
|
|
||||||
blue1
|
|
||||||
blue2
|
|
||||||
blue3
|
|
||||||
blue4
|
|
||||||
dodgerblue1
|
|
||||||
dodgerblue2
|
|
||||||
dodgerblue3
|
|
||||||
dodgerblue4
|
|
||||||
steelblue1
|
|
||||||
steelblue2
|
|
||||||
steelblue3
|
|
||||||
steelblue4
|
|
||||||
deepskyblue1
|
|
||||||
deepskyblue2
|
|
||||||
deepskyblue3
|
|
||||||
deepskyblue4
|
|
||||||
skyblue1
|
|
||||||
skyblue2
|
|
||||||
skyblue3
|
|
||||||
skyblue4
|
|
||||||
lightskyblue1
|
|
||||||
lightskyblue2
|
|
||||||
lightskyblue3
|
|
||||||
lightskyblue4
|
|
||||||
slategray1
|
|
||||||
slategray2
|
|
||||||
slategray3
|
|
||||||
slategray4
|
|
||||||
lightsteelblue1
|
|
||||||
lightsteelblue2
|
|
||||||
lightsteelblue3
|
|
||||||
lightsteelblue4
|
|
||||||
lightblue1
|
|
||||||
lightblue2
|
|
||||||
lightblue3
|
|
||||||
lightblue4
|
|
||||||
lightcyan1
|
|
||||||
lightcyan2
|
|
||||||
lightcyan3
|
|
||||||
lightcyan4
|
|
||||||
paleturquoise1
|
|
||||||
paleturquoise2
|
|
||||||
paleturquoise3
|
|
||||||
paleturquoise4
|
|
||||||
cadetblue1
|
|
||||||
cadetblue2
|
|
||||||
cadetblue3
|
|
||||||
cadetblue4
|
|
||||||
turquoise1
|
|
||||||
turquoise2
|
|
||||||
turquoise3
|
|
||||||
turquoise4
|
|
||||||
cyan1
|
|
||||||
cyan2
|
|
||||||
cyan3
|
|
||||||
cyan4
|
|
||||||
darkslategray1
|
|
||||||
darkslategray2
|
|
||||||
darkslategray3
|
|
||||||
darkslategray4
|
|
||||||
aquamarine1
|
|
||||||
aquamarine2
|
|
||||||
aquamarine3
|
|
||||||
aquamarine4
|
|
||||||
darkseagreen1
|
|
||||||
darkseagreen2
|
|
||||||
darkseagreen3
|
|
||||||
darkseagreen4
|
|
||||||
seagreen1
|
|
||||||
seagreen2
|
|
||||||
seagreen3
|
|
||||||
seagreen4
|
|
||||||
palegreen1
|
|
||||||
palegreen2
|
|
||||||
palegreen3
|
|
||||||
palegreen4
|
|
||||||
springgreen1
|
|
||||||
springgreen2
|
|
||||||
springgreen3
|
|
||||||
springgreen4
|
|
||||||
green1
|
|
||||||
green2
|
|
||||||
green3
|
|
||||||
green4
|
|
||||||
chartreuse1
|
|
||||||
chartreuse2
|
|
||||||
chartreuse3
|
|
||||||
chartreuse4
|
|
||||||
olivedrab1
|
|
||||||
olivedrab2
|
|
||||||
olivedrab3
|
|
||||||
olivedrab4
|
|
||||||
darkolivegreen1
|
|
||||||
darkolivegreen2
|
|
||||||
darkolivegreen3
|
|
||||||
darkolivegreen4
|
|
||||||
khaki1
|
|
||||||
khaki2
|
|
||||||
khaki3
|
|
||||||
khaki4
|
|
||||||
lightgoldenrod1
|
|
||||||
lightgoldenrod2
|
|
||||||
lightgoldenrod3
|
|
||||||
lightgoldenrod4
|
|
||||||
lightyellow1
|
|
||||||
lightyellow2
|
|
||||||
lightyellow3
|
|
||||||
lightyellow4
|
|
||||||
yellow1
|
|
||||||
yellow2
|
|
||||||
yellow3
|
|
||||||
yellow4
|
|
||||||
gold1
|
|
||||||
gold2
|
|
||||||
gold3
|
|
||||||
gold4
|
|
||||||
goldenrod1
|
|
||||||
goldenrod2
|
|
||||||
goldenrod3
|
|
||||||
goldenrod4
|
|
||||||
darkgoldenrod1
|
|
||||||
darkgoldenrod2
|
|
||||||
darkgoldenrod3
|
|
||||||
darkgoldenrod4
|
|
||||||
rosybrown1
|
|
||||||
rosybrown2
|
|
||||||
rosybrown3
|
|
||||||
rosybrown4
|
|
||||||
indianred1
|
|
||||||
indianred2
|
|
||||||
indianred3
|
|
||||||
indianred4
|
|
||||||
sienna1
|
|
||||||
sienna2
|
|
||||||
sienna3
|
|
||||||
sienna4
|
|
||||||
burlywood1
|
|
||||||
burlywood2
|
|
||||||
burlywood3
|
|
||||||
burlywood4
|
|
||||||
wheat1
|
|
||||||
wheat2
|
|
||||||
wheat3
|
|
||||||
wheat4
|
|
||||||
tan1
|
|
||||||
tan2
|
|
||||||
tan3
|
|
||||||
tan4
|
|
||||||
chocolate1
|
|
||||||
chocolate2
|
|
||||||
chocolate3
|
|
||||||
chocolate4
|
|
||||||
firebrick1
|
|
||||||
firebrick2
|
|
||||||
firebrick3
|
|
||||||
firebrick4
|
|
||||||
brown1
|
|
||||||
brown2
|
|
||||||
brown3
|
|
||||||
brown4
|
|
||||||
salmon1
|
|
||||||
salmon2
|
|
||||||
salmon3
|
|
||||||
salmon4
|
|
||||||
lightsalmon1
|
|
||||||
lightsalmon2
|
|
||||||
lightsalmon3
|
|
||||||
lightsalmon4
|
|
||||||
orange1
|
|
||||||
orange2
|
|
||||||
orange3
|
|
||||||
orange4
|
|
||||||
darkorange1
|
|
||||||
darkorange2
|
|
||||||
darkorange3
|
|
||||||
darkorange4
|
|
||||||
coral1
|
|
||||||
coral2
|
|
||||||
coral3
|
|
||||||
coral4
|
|
||||||
tomato1
|
|
||||||
tomato2
|
|
||||||
tomato3
|
|
||||||
tomato4
|
|
||||||
orangered1
|
|
||||||
orangered2
|
|
||||||
orangered3
|
|
||||||
orangered4
|
|
||||||
red1
|
|
||||||
red2
|
|
||||||
red3
|
|
||||||
red4
|
|
||||||
deeppink1
|
|
||||||
deeppink2
|
|
||||||
deeppink3
|
|
||||||
deeppink4
|
|
||||||
hotpink1
|
|
||||||
hotpink2
|
|
||||||
hotpink3
|
|
||||||
hotpink4
|
|
||||||
pink1
|
|
||||||
pink2
|
|
||||||
pink3
|
|
||||||
pink4
|
|
||||||
lightpink1
|
|
||||||
lightpink2
|
|
||||||
lightpink3
|
|
||||||
lightpink4
|
|
||||||
palevioletred1
|
|
||||||
palevioletred2
|
|
||||||
palevioletred3
|
|
||||||
palevioletred4
|
|
||||||
maroon1
|
|
||||||
maroon2
|
|
||||||
maroon3
|
|
||||||
maroon4
|
|
||||||
violetred1
|
|
||||||
violetred2
|
|
||||||
violetred3
|
|
||||||
violetred4
|
|
||||||
magenta1
|
|
||||||
magenta2
|
|
||||||
magenta3
|
|
||||||
magenta4
|
|
||||||
orchid1
|
|
||||||
orchid2
|
|
||||||
orchid3
|
|
||||||
orchid4
|
|
||||||
plum1
|
|
||||||
plum2
|
|
||||||
plum3
|
|
||||||
plum4
|
|
||||||
mediumorchid1
|
|
||||||
mediumorchid2
|
|
||||||
mediumorchid3
|
|
||||||
mediumorchid4
|
|
||||||
darkorchid1
|
|
||||||
darkorchid2
|
|
||||||
darkorchid3
|
|
||||||
darkorchid4
|
|
||||||
purple1
|
|
||||||
purple2
|
|
||||||
purple3
|
|
||||||
purple4
|
|
||||||
mediumpurple1
|
|
||||||
mediumpurple2
|
|
||||||
mediumpurple3
|
|
||||||
mediumpurple4
|
|
||||||
thistle1
|
|
||||||
thistle2
|
|
||||||
thistle3
|
|
||||||
thistle4
|
|
||||||
gray0
|
|
||||||
grey0
|
|
||||||
gray1
|
|
||||||
grey1
|
|
||||||
gray2
|
|
||||||
grey2
|
|
||||||
gray3
|
|
||||||
grey3
|
|
||||||
gray4
|
|
||||||
grey4
|
|
||||||
gray5
|
|
||||||
grey5
|
|
||||||
gray6
|
|
||||||
grey6
|
|
||||||
gray7
|
|
||||||
grey7
|
|
||||||
gray8
|
|
||||||
grey8
|
|
||||||
gray9
|
|
||||||
grey9
|
|
||||||
gray10
|
|
||||||
grey10
|
|
||||||
gray11
|
|
||||||
grey11
|
|
||||||
gray12
|
|
||||||
grey12
|
|
||||||
gray13
|
|
||||||
grey13
|
|
||||||
gray14
|
|
||||||
grey14
|
|
||||||
gray15
|
|
||||||
grey15
|
|
||||||
gray16
|
|
||||||
grey16
|
|
||||||
gray17
|
|
||||||
grey17
|
|
||||||
gray18
|
|
||||||
grey18
|
|
||||||
gray19
|
|
||||||
grey19
|
|
||||||
gray20
|
|
||||||
grey20
|
|
||||||
gray21
|
|
||||||
grey21
|
|
||||||
gray22
|
|
||||||
grey22
|
|
||||||
gray23
|
|
||||||
grey23
|
|
||||||
gray24
|
|
||||||
grey24
|
|
||||||
gray25
|
|
||||||
grey25
|
|
||||||
gray26
|
|
||||||
grey26
|
|
||||||
gray27
|
|
||||||
grey27
|
|
||||||
gray28
|
|
||||||
grey28
|
|
||||||
gray29
|
|
||||||
grey29
|
|
||||||
gray30
|
|
||||||
grey30
|
|
||||||
gray31
|
|
||||||
grey31
|
|
||||||
gray32
|
|
||||||
grey32
|
|
||||||
gray33
|
|
||||||
grey33
|
|
||||||
gray34
|
|
||||||
grey34
|
|
||||||
gray35
|
|
||||||
grey35
|
|
||||||
gray36
|
|
||||||
grey36
|
|
||||||
gray37
|
|
||||||
grey37
|
|
||||||
gray38
|
|
||||||
grey38
|
|
||||||
gray39
|
|
||||||
grey39
|
|
||||||
gray40
|
|
||||||
grey40
|
|
||||||
gray41
|
|
||||||
grey41
|
|
||||||
gray42
|
|
||||||
grey42
|
|
||||||
gray43
|
|
||||||
grey43
|
|
||||||
gray44
|
|
||||||
grey44
|
|
||||||
gray45
|
|
||||||
grey45
|
|
||||||
gray46
|
|
||||||
grey46
|
|
||||||
gray47
|
|
||||||
grey47
|
|
||||||
gray48
|
|
||||||
grey48
|
|
||||||
gray49
|
|
||||||
grey49
|
|
||||||
gray50
|
|
||||||
grey50
|
|
||||||
gray51
|
|
||||||
grey51
|
|
||||||
gray52
|
|
||||||
grey52
|
|
||||||
gray53
|
|
||||||
grey53
|
|
||||||
gray54
|
|
||||||
grey54
|
|
||||||
gray55
|
|
||||||
grey55
|
|
||||||
gray56
|
|
||||||
grey56
|
|
||||||
gray57
|
|
||||||
grey57
|
|
||||||
gray58
|
|
||||||
grey58
|
|
||||||
gray59
|
|
||||||
grey59
|
|
||||||
gray60
|
|
||||||
grey60
|
|
||||||
gray61
|
|
||||||
grey61
|
|
||||||
gray62
|
|
||||||
grey62
|
|
||||||
gray63
|
|
||||||
grey63
|
|
||||||
gray64
|
|
||||||
grey64
|
|
||||||
gray65
|
|
||||||
grey65
|
|
||||||
gray66
|
|
||||||
grey66
|
|
||||||
gray67
|
|
||||||
grey67
|
|
||||||
gray68
|
|
||||||
grey68
|
|
||||||
gray69
|
|
||||||
grey69
|
|
||||||
gray70
|
|
||||||
grey70
|
|
||||||
gray71
|
|
||||||
grey71
|
|
||||||
gray72
|
|
||||||
grey72
|
|
||||||
gray73
|
|
||||||
grey73
|
|
||||||
gray74
|
|
||||||
grey74
|
|
||||||
gray75
|
|
||||||
grey75
|
|
||||||
gray76
|
|
||||||
grey76
|
|
||||||
gray77
|
|
||||||
grey77
|
|
||||||
gray78
|
|
||||||
grey78
|
|
||||||
gray79
|
|
||||||
grey79
|
|
||||||
gray80
|
|
||||||
grey80
|
|
||||||
gray81
|
|
||||||
grey81
|
|
||||||
gray82
|
|
||||||
grey82
|
|
||||||
gray83
|
|
||||||
grey83
|
|
||||||
gray84
|
|
||||||
grey84
|
|
||||||
gray85
|
|
||||||
grey85
|
|
||||||
gray86
|
|
||||||
grey86
|
|
||||||
gray87
|
|
||||||
grey87
|
|
||||||
gray88
|
|
||||||
grey88
|
|
||||||
gray89
|
|
||||||
grey89
|
|
||||||
gray90
|
|
||||||
grey90
|
|
||||||
gray91
|
|
||||||
grey91
|
|
||||||
gray92
|
|
||||||
grey92
|
|
||||||
gray93
|
|
||||||
grey93
|
|
||||||
gray94
|
|
||||||
grey94
|
|
||||||
gray95
|
|
||||||
grey95
|
|
||||||
gray96
|
|
||||||
grey96
|
|
||||||
gray97
|
|
||||||
grey97
|
|
||||||
gray98
|
|
||||||
grey98
|
|
||||||
gray99
|
|
||||||
grey99
|
|
||||||
gray100
|
|
||||||
grey100
|
|
||||||
dark-grey
|
|
||||||
darkgrey
|
|
||||||
dark-gray
|
|
||||||
darkgray
|
|
||||||
dark-blue
|
|
||||||
darkblue
|
|
||||||
dark-cyan
|
|
||||||
darkcyan
|
|
||||||
dark-magenta
|
|
||||||
darkmagenta
|
|
||||||
dark-red
|
|
||||||
darkred
|
|
||||||
light-green
|
|
||||||
lightgreen
|
|
||||||
crimson
|
|
||||||
indigo
|
|
||||||
olive
|
|
||||||
rebecca-purple
|
|
||||||
rebeccapurple
|
|
||||||
silver
|
|
||||||
teal
|
|
479851
.github/actions/spelling/dictionary/dictionary.txt
vendored
479851
.github/actions/spelling/dictionary/dictionary.txt
vendored
File diff suppressed because it is too large
Load diff
3
.github/actions/spelling/dictionary/math.txt
vendored
3
.github/actions/spelling/dictionary/math.txt
vendored
|
@ -1,3 +0,0 @@
|
||||||
powf
|
|
||||||
sqrtf
|
|
||||||
isnan
|
|
21
.github/actions/spelling/excludes.txt
vendored
21
.github/actions/spelling/excludes.txt
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
(?:(?i)\.png$)
|
||||||
(?:^|/)dirs$
|
(?:^|/)dirs$
|
||||||
(?:^|/)go\.mod$
|
(?:^|/)go\.mod$
|
||||||
(?:^|/)go\.sum$
|
(?:^|/)go\.sum$
|
||||||
|
@ -35,7 +36,6 @@ SUMS$
|
||||||
\.pbxproj$
|
\.pbxproj$
|
||||||
\.pdf$
|
\.pdf$
|
||||||
\.pem$
|
\.pem$
|
||||||
(?:(?i)\.png$)
|
|
||||||
\.psd$
|
\.psd$
|
||||||
\.runsettings$
|
\.runsettings$
|
||||||
\.sig$
|
\.sig$
|
||||||
|
@ -54,13 +54,26 @@ SUMS$
|
||||||
\.zip$
|
\.zip$
|
||||||
^consolegit2gitfilters\.json$
|
^consolegit2gitfilters\.json$
|
||||||
^dep/
|
^dep/
|
||||||
^oss/
|
^doc/reference/master-sequence-list.csv$
|
||||||
^doc/reference/UTF8-torture-test\.txt$
|
^doc/reference/UTF8-torture-test\.txt$
|
||||||
|
^oss/
|
||||||
|
^src/host/ft_uia/run\.bat$
|
||||||
|
^src/host/runft\.bat$
|
||||||
|
^src/host/runut\.bat$
|
||||||
^src/interactivity/onecore/BgfxEngine\.
|
^src/interactivity/onecore/BgfxEngine\.
|
||||||
^src/renderer/wddmcon/WddmConRenderer\.
|
^src/renderer/wddmcon/WddmConRenderer\.
|
||||||
|
^src/terminal/adapter/ut_adapter/run\.bat$
|
||||||
|
^src/terminal/parser/delfuzzpayload\.bat$
|
||||||
|
^src/terminal/parser/ft_fuzzer/run\.bat$
|
||||||
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
|
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
|
||||||
^src/types/ut_types/UtilsTests.cpp$
|
^src/terminal/parser/ft_fuzzwrapper/run\.bat$
|
||||||
|
^src/terminal/parser/ut_parser/run\.bat$
|
||||||
|
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
|
||||||
|
^src/tools/lnkd/lnkd\.bat$
|
||||||
|
^src/tools/pixels/pixels\.bat$
|
||||||
|
^src/tools/texttests/fira\.txt$
|
||||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||||
|
^src/types/ut_types/UtilsTests.cpp$
|
||||||
^\.github/actions/spelling/
|
^\.github/actions/spelling/
|
||||||
^\.gitignore$
|
^\.gitignore$
|
||||||
^doc/reference/master-sequence-list.csv$
|
^\XamlStyler.json$
|
||||||
|
|
17
.github/actions/spelling/expect/alphabet.txt
vendored
17
.github/actions/spelling/expect/alphabet.txt
vendored
|
@ -1,3 +1,9 @@
|
||||||
|
AAAa
|
||||||
|
AAAAA
|
||||||
|
AAAAAAAAAAAAA
|
||||||
|
AAAAAABBBBBBCCC
|
||||||
|
AAAAABBBBBBCCC
|
||||||
|
abcd
|
||||||
abcd
|
abcd
|
||||||
abcde
|
abcde
|
||||||
abcdef
|
abcdef
|
||||||
|
@ -5,12 +11,20 @@ ABCDEFG
|
||||||
ABCDEFGH
|
ABCDEFGH
|
||||||
ABCDEFGHIJ
|
ABCDEFGHIJ
|
||||||
abcdefghijk
|
abcdefghijk
|
||||||
|
ABCDEFGHIJKLMNO
|
||||||
abcdefghijklmnop
|
abcdefghijklmnop
|
||||||
ABCDEFGHIJKLMNOPQRST
|
ABCDEFGHIJKLMNOPQRST
|
||||||
abcdefghijklmnopqrstuvwxyz
|
abcdefghijklmnopqrstuvwxyz
|
||||||
|
ABCG
|
||||||
ABE
|
ABE
|
||||||
BBGGRR
|
abf
|
||||||
|
BBBBB
|
||||||
|
BBBBBBBB
|
||||||
BBBBBBBBBBBBBBDDDD
|
BBBBBBBBBBBBBBDDDD
|
||||||
|
BBBBBCCC
|
||||||
|
BBBBCCCCC
|
||||||
|
BBGGRR
|
||||||
|
CCE
|
||||||
EFG
|
EFG
|
||||||
EFGh
|
EFGh
|
||||||
QQQQQQQQQQABCDEFGHIJ
|
QQQQQQQQQQABCDEFGHIJ
|
||||||
|
@ -31,3 +45,4 @@ ZYXWVUT
|
||||||
ZZBBZ
|
ZZBBZ
|
||||||
ZZZBB
|
ZZZBB
|
||||||
ZZZBZ
|
ZZZBZ
|
||||||
|
ZZZZZ
|
||||||
|
|
250
.github/actions/spelling/expect/expect.txt
vendored
250
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load diff
7
.github/actions/spelling/expect/web.txt
vendored
7
.github/actions/spelling/expect/web.txt
vendored
|
@ -1,6 +1,7 @@
|
||||||
http
|
http
|
||||||
td
|
|
||||||
www
|
www
|
||||||
|
easyrgb
|
||||||
|
php
|
||||||
ecma
|
ecma
|
||||||
rapidtables
|
rapidtables
|
||||||
WCAG
|
WCAG
|
||||||
|
@ -10,9 +11,9 @@ robertelder
|
||||||
kovidgoyal
|
kovidgoyal
|
||||||
leonerd
|
leonerd
|
||||||
fixterms
|
fixterms
|
||||||
uk
|
|
||||||
winui
|
winui
|
||||||
appshellintegration
|
appshellintegration
|
||||||
|
mdtauk
|
||||||
cppreference
|
cppreference
|
||||||
gfycat
|
gfycat
|
||||||
what3words
|
Guake
|
||||||
|
|
|
@ -22,3 +22,6 @@ Base64::s_(?:En|De)code\(L"[^"]+"
|
||||||
VERIFY_ARE_EQUAL\(L"[^"]+"
|
VERIFY_ARE_EQUAL\(L"[^"]+"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
||||||
std::memory_order_[\w]+
|
std::memory_order_[\w]+
|
||||||
|
D2DERR_SHADER_COMPILE_FAILED
|
||||||
|
TIL_FEATURE_[0-9A-Z_]+
|
||||||
|
vcvars\w*
|
||||||
|
|
22
.github/actions/spelling/reject.txt
vendored
Normal file
22
.github/actions/spelling/reject.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
^attache$
|
||||||
|
^attacher$
|
||||||
|
^attachers$
|
||||||
|
^spae$
|
||||||
|
^spaebook$
|
||||||
|
^spaecraft$
|
||||||
|
^spaed$
|
||||||
|
^spaedom$
|
||||||
|
^spaeing$
|
||||||
|
^spaeings$
|
||||||
|
^spae-man$
|
||||||
|
^spaeman$
|
||||||
|
^spaer$
|
||||||
|
^Spaerobee$
|
||||||
|
^spaes$
|
||||||
|
^spaewife$
|
||||||
|
^spaewoman$
|
||||||
|
^spaework$
|
||||||
|
^spaewright$
|
||||||
|
^wether$
|
||||||
|
^wethers$
|
||||||
|
^wetherteg$
|
15
.github/workflows/spelling.yml
vendored
15
.github/workflows/spelling.yml
vendored
|
@ -1,15 +0,0 @@
|
||||||
name: Spell checking
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
push:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Spell checking
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2.0.0
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
fetch-depth: 5
|
|
||||||
- uses: check-spelling/check-spelling@0.0.17-alpha
|
|
20
.github/workflows/spelling2.yml
vendored
Normal file
20
.github/workflows/spelling2.yml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
|
||||||
|
name: Spell checking
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
spelling:
|
||||||
|
name: Spell checking
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout-merge
|
||||||
|
if: "contains(github.event_name, 'pull_request')"
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
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
|
|
@ -4,36 +4,6 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "AttrRow.hpp"
|
#include "AttrRow.hpp"
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - constructor
|
|
||||||
// Arguments:
|
|
||||||
// - cchRowWidth - the length of the default text attribute
|
|
||||||
// - attr - the default text attribute
|
|
||||||
// Return Value:
|
|
||||||
// - constructed object
|
|
||||||
ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr) noexcept
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_list.emplace_back(TextAttributeRun(cchRowWidth, attr));
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
FAIL_FAST_CAUGHT_EXCEPTION();
|
|
||||||
}
|
|
||||||
_cchRowWidth = cchRowWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Sets all properties of the ATTR_ROW to default values
|
|
||||||
// Arguments:
|
|
||||||
// - attr - The default text attributes to use on text in this row.
|
|
||||||
void ATTR_ROW::Reset(const TextAttribute attr)
|
|
||||||
{
|
|
||||||
_list.clear();
|
|
||||||
_list.emplace_back(TextAttributeRun(_cchRowWidth, attr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Takes an existing row of attributes, and changes the length so that it fills the NewWidth.
|
// - Takes an existing row of attributes, and changes the length so that it fills the NewWidth.
|
||||||
// If the new size is bigger, then the last attr is extended to fill the NewWidth.
|
// If the new size is bigger, then the last attr is extended to fill the NewWidth.
|
||||||
|
@ -45,46 +15,12 @@ void ATTR_ROW::Reset(const TextAttribute attr)
|
||||||
// - <none>, throws exceptions on failures.
|
// - <none>, throws exceptions on failures.
|
||||||
void ATTR_ROW::Resize(const size_t newWidth)
|
void ATTR_ROW::Resize(const size_t newWidth)
|
||||||
{
|
{
|
||||||
THROW_HR_IF(E_INVALIDARG, 0 == newWidth);
|
mybase::resize(gsl::narrow<UINT>(newWidth));
|
||||||
|
}
|
||||||
|
|
||||||
// Easy case. If the new row is longer, increase the length of the last run by how much new space there is.
|
void ATTR_ROW::Reset(const TextAttribute attr)
|
||||||
if (newWidth > _cchRowWidth)
|
{
|
||||||
{
|
mybase::fill(attr);
|
||||||
// Get the attribute that covers the final column of old width.
|
|
||||||
const auto runPos = FindAttrIndex(_cchRowWidth - 1, nullptr);
|
|
||||||
auto& run = _list.at(runPos);
|
|
||||||
|
|
||||||
// Extend its length by the additional columns we're adding.
|
|
||||||
run.SetLength(run.GetLength() + newWidth - _cchRowWidth);
|
|
||||||
|
|
||||||
// Store that the new total width we represent is the new width.
|
|
||||||
_cchRowWidth = newWidth;
|
|
||||||
}
|
|
||||||
// harder case: new row is shorter.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get the attribute that covers the final column of the new width
|
|
||||||
size_t CountOfAttr = 0;
|
|
||||||
const auto runPos = FindAttrIndex(newWidth - 1, &CountOfAttr);
|
|
||||||
auto& run = _list.at(runPos);
|
|
||||||
|
|
||||||
// CountOfAttr was given to us as "how many columns left from this point forward are covered by the returned run"
|
|
||||||
// So if the original run was B5 covering a 5 size OldWidth and we have a NewWidth of 3
|
|
||||||
// then when we called FindAttrIndex, it returned the B5 as the pIndexedRun and a 2 for how many more segments it covers
|
|
||||||
// after and including the 3rd column.
|
|
||||||
// B5-2 = B3, which is what we desire to cover the new 3 size buffer.
|
|
||||||
run.SetLength(run.GetLength() - CountOfAttr + 1);
|
|
||||||
|
|
||||||
// Store that the new total width we represent is the new width.
|
|
||||||
_cchRowWidth = newWidth;
|
|
||||||
|
|
||||||
// Erase segments after the one we just updated.
|
|
||||||
_list.erase(_list.cbegin() + runPos + 1, _list.cend());
|
|
||||||
|
|
||||||
// NOTE: Under some circumstances here, we have leftover run segments in memory or blank run segments
|
|
||||||
// in memory. We're not going to waste time redimensioning the array in the heap. We're just noting that the useful
|
|
||||||
// portions of it have changed.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -97,7 +33,7 @@ void ATTR_ROW::Resize(const size_t newWidth)
|
||||||
// - will throw on error
|
// - will throw on error
|
||||||
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column) const
|
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column) const
|
||||||
{
|
{
|
||||||
return GetAttrByColumn(column, nullptr);
|
return mybase::at(gsl::narrow<UINT>(column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -112,73 +48,10 @@ TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column) const
|
||||||
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column,
|
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column,
|
||||||
size_t* const pApplies) const
|
size_t* const pApplies) const
|
||||||
{
|
{
|
||||||
THROW_HR_IF(E_INVALIDARG, column >= _cchRowWidth);
|
UINT applies = 0;
|
||||||
const auto runPos = FindAttrIndex(column, pApplies);
|
const auto attr = mybase::at(gsl::narrow<UINT>(column), applies);
|
||||||
return _list.at(runPos).GetAttributes();
|
*pApplies = applies;
|
||||||
}
|
return attr;
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - reports how many runs we have stored (to be used for some optimizations
|
|
||||||
// Return Value:
|
|
||||||
// - Count of runs. 1 means we have 1 color to represent the entire row.
|
|
||||||
size_t ATTR_ROW::GetNumberOfRuns() const noexcept
|
|
||||||
{
|
|
||||||
return _list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - This routine finds the nth attribute in this ATTR_ROW.
|
|
||||||
// Arguments:
|
|
||||||
// - index - which attribute to find
|
|
||||||
// - applies - on output, contains corrected length of indexed attr.
|
|
||||||
// for example, if the attribute string was { 5, BLUE } and the requested
|
|
||||||
// index was 3, CountOfAttr would be 2.
|
|
||||||
// Return Value:
|
|
||||||
// - const reference to attribute run object
|
|
||||||
size_t ATTR_ROW::FindAttrIndex(const size_t index, size_t* const pApplies) const
|
|
||||||
{
|
|
||||||
FAIL_FAST_IF(!(index < _cchRowWidth)); // The requested index cannot be longer than the total length described by this set of Attrs.
|
|
||||||
|
|
||||||
size_t cTotalLength = 0;
|
|
||||||
|
|
||||||
FAIL_FAST_IF(!(_list.size() > 0)); // There should be a non-zero and positive number of items in the array.
|
|
||||||
|
|
||||||
// Scan through the internal array from position 0 adding up the lengths that each attribute applies to
|
|
||||||
auto runPos = _list.cbegin();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
cTotalLength += runPos->GetLength();
|
|
||||||
|
|
||||||
if (cTotalLength > index)
|
|
||||||
{
|
|
||||||
// If we've just passed up the requested index with the length we added, break early
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
runPos++;
|
|
||||||
} while (runPos < _list.cend());
|
|
||||||
|
|
||||||
// we should have broken before falling out the while case.
|
|
||||||
// if we didn't break, then this ATTR_ROW wasn't filled with enough attributes for the entire row of characters
|
|
||||||
FAIL_FAST_IF(runPos >= _list.cend());
|
|
||||||
|
|
||||||
// The remaining iterator position is the position of the attribute that is applicable at the position requested (index)
|
|
||||||
// Calculate its remaining applicability if requested
|
|
||||||
|
|
||||||
// The length on which the found attribute applies is the total length seen so far minus the index we were searching for.
|
|
||||||
FAIL_FAST_IF(!(cTotalLength > index)); // The length of all attributes we counted up so far should be longer than the index requested or we'll underflow.
|
|
||||||
|
|
||||||
if (nullptr != pApplies)
|
|
||||||
{
|
|
||||||
const auto attrApplies = cTotalLength - index;
|
|
||||||
FAIL_FAST_IF(!(attrApplies > 0)); // An attribute applies for >0 characters
|
|
||||||
// MSFT: 17130145 - will restore this and add a better assert to catch the real issue.
|
|
||||||
//FAIL_FAST_IF(!(attrApplies <= _cchRowWidth)); // An attribute applies for a maximum of the total length available to us
|
|
||||||
|
|
||||||
*pApplies = attrApplies;
|
|
||||||
}
|
|
||||||
|
|
||||||
return runPos - _list.cbegin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -188,11 +61,11 @@ size_t ATTR_ROW::FindAttrIndex(const size_t index, size_t* const pApplies) const
|
||||||
std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
|
std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
|
||||||
{
|
{
|
||||||
std::vector<uint16_t> ids;
|
std::vector<uint16_t> ids;
|
||||||
for (const auto& run : _list)
|
for (const auto& run : *this)
|
||||||
{
|
{
|
||||||
if (run.GetAttributes().IsHyperlink())
|
if (run.IsHyperlink())
|
||||||
{
|
{
|
||||||
ids.emplace_back(run.GetAttributes().GetHyperlinkId());
|
ids.emplace_back(run.GetHyperlinkId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
|
@ -207,10 +80,8 @@ std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
|
||||||
// - <none>
|
// - <none>
|
||||||
bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
|
bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
|
||||||
{
|
{
|
||||||
size_t const length = _cchRowWidth - iStart;
|
mybase::fill(attr, iStart);
|
||||||
|
return true;
|
||||||
const TextAttributeRun run(length, attr);
|
|
||||||
return SUCCEEDED(InsertAttrRuns({ &run, 1 }, iStart, _cchRowWidth - 1, _cchRowWidth));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -223,13 +94,7 @@ bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
|
||||||
// - <none>
|
// - <none>
|
||||||
void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept
|
void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept
|
||||||
{
|
{
|
||||||
for (auto& run : _list)
|
mybase::replace(toBeReplacedAttr, replaceWith);
|
||||||
{
|
|
||||||
if (run.GetAttributes() == toBeReplacedAttr)
|
|
||||||
{
|
|
||||||
run.SetAttributes(replaceWith);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -248,392 +113,12 @@ void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAtt
|
||||||
// otherwise STATUS_SUCCESS if we were successful.
|
// otherwise STATUS_SUCCESS if we were successful.
|
||||||
[[nodiscard]] HRESULT ATTR_ROW::InsertAttrRuns(const gsl::span<const TextAttributeRun> newAttrs,
|
[[nodiscard]] HRESULT ATTR_ROW::InsertAttrRuns(const gsl::span<const TextAttributeRun> newAttrs,
|
||||||
const size_t iStart,
|
const size_t iStart,
|
||||||
const size_t iEnd,
|
const size_t /*iEnd*/,
|
||||||
const size_t cBufferWidth)
|
const size_t /*cBufferWidth*/)
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// Definitions:
|
mybase::replace(iStart, mybase::npos, newAttrs.begin(), newAttrs.end());
|
||||||
// Existing Run = The run length encoded color array we're already storing in memory before this was called.
|
|
||||||
// Insert Run = The run length encoded color array that someone is asking us to inject into our stored memory run.
|
|
||||||
// New Run = The run length encoded color array that we have to allocate and rebuild to store internally
|
|
||||||
// which will replace Existing Run at the end of this function.
|
|
||||||
// Example:
|
|
||||||
// cBufferWidth = 10.
|
|
||||||
// Existing Run: R3 -> G5 -> B2
|
|
||||||
// Insert Run: Y1 -> N1 at iStart = 5 and iEnd = 6
|
|
||||||
// (rgInsertAttrs is a 2 length array with Y1->N1 in it and cInsertAttrs = 2)
|
|
||||||
// Final Run: R3 -> G2 -> Y1 -> N1 -> G1 -> B2
|
|
||||||
|
|
||||||
// We'll need to know what the last valid column is for some calculations versus iEnd
|
|
||||||
// because iEnd is specified to us as an inclusive index value.
|
|
||||||
// Do the -1 math here now so we don't have to have -1s scattered all over this function.
|
|
||||||
const size_t iLastBufferCol = cBufferWidth - 1;
|
|
||||||
|
|
||||||
// If the insertion size is 1, do some pre-processing to
|
|
||||||
// see if we can get this done quickly.
|
|
||||||
if (newAttrs.size() == 1)
|
|
||||||
{
|
|
||||||
// Get the new color attribute we're trying to apply
|
|
||||||
const TextAttribute NewAttr = til::at(newAttrs, 0).GetAttributes();
|
|
||||||
|
|
||||||
// If the existing run was only 1 element...
|
|
||||||
// ...and the new color is the same as the old, we don't have to do anything and can exit quick.
|
|
||||||
if (_list.size() == 1 && _list.at(0).GetAttributes() == NewAttr)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
// .. otherwise if we internally have a list of 2 or more and we're about to insert a single color
|
|
||||||
// it's possible that we just walk left-to-right through the row and find a quick exit.
|
|
||||||
else if (iStart >= 0 && iStart == iEnd)
|
|
||||||
{
|
|
||||||
// First we try to find the run where the insertion happens, using lowerBound and upperBound to track
|
|
||||||
// where we are currently at.
|
|
||||||
const auto begin = _list.begin();
|
|
||||||
size_t lowerBound = 0;
|
|
||||||
size_t upperBound = 0;
|
|
||||||
for (size_t i = 0; i < _list.size(); i++)
|
|
||||||
{
|
|
||||||
const auto curr = begin + i;
|
|
||||||
upperBound += curr->GetLength();
|
|
||||||
|
|
||||||
if (iStart >= lowerBound && iStart < upperBound)
|
|
||||||
{
|
|
||||||
// The run that we try to insert into has the same color as the new one.
|
|
||||||
// e.g.
|
|
||||||
// AAAAABBBBBBBCCC
|
|
||||||
// ^
|
|
||||||
// AAAAABBBBBBBCCC
|
|
||||||
//
|
|
||||||
// 'B' is the new color and '^' represents where iStart is. We don't have to
|
|
||||||
// do anything.
|
|
||||||
if (curr->GetAttributes() == NewAttr)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current run has length of exactly one, we can simply change the attribute
|
|
||||||
// of the current run.
|
|
||||||
// e.g.
|
|
||||||
// AAAAABCCCCCCCCC
|
|
||||||
// ^
|
|
||||||
// AAAAADCCCCCCCCC
|
|
||||||
//
|
|
||||||
// Here 'D' is the new color.
|
|
||||||
if (curr->GetLength() == 1)
|
|
||||||
{
|
|
||||||
curr->SetAttributes(NewAttr);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the insertion happens at current run's lower boundary...
|
|
||||||
if (iStart == lowerBound && i > 0)
|
|
||||||
{
|
|
||||||
const auto prev = std::prev(curr, 1);
|
|
||||||
// ... and the previous run has the same color as the new one, we can
|
|
||||||
// just adjust the counts in the existing two elements in our internal list.
|
|
||||||
// e.g.
|
|
||||||
// AAAAABBBBBBBCCC
|
|
||||||
// ^
|
|
||||||
// AAAAAABBBBBBCCC
|
|
||||||
//
|
|
||||||
// Here 'A' is the new color.
|
|
||||||
if (NewAttr == prev->GetAttributes())
|
|
||||||
{
|
|
||||||
prev->IncrementLength();
|
|
||||||
curr->DecrementLength();
|
|
||||||
|
|
||||||
// If we just reduced the right half to zero, just erase it out of the list.
|
|
||||||
if (curr->GetLength() == 0)
|
|
||||||
{
|
|
||||||
_list.erase(curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the insertion happens at current run's upper boundary...
|
|
||||||
if (iStart == upperBound - 1 && i + 1 < _list.size())
|
|
||||||
{
|
|
||||||
// ...then let's try our luck with the next run if possible. This is basically the opposite
|
|
||||||
// of what we did with the previous run.
|
|
||||||
// e.g.
|
|
||||||
// AAAAAABBBBBBCCC
|
|
||||||
// ^
|
|
||||||
// AAAAABBBBBBBCCC
|
|
||||||
//
|
|
||||||
// Here 'B' is the new color.
|
|
||||||
const auto next = std::next(curr, 1);
|
|
||||||
if (NewAttr == next->GetAttributes())
|
|
||||||
{
|
|
||||||
curr->DecrementLength();
|
|
||||||
next->IncrementLength();
|
|
||||||
|
|
||||||
if (curr->GetLength() == 0)
|
|
||||||
{
|
|
||||||
_list.erase(curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance one run in the _list.
|
|
||||||
lowerBound = upperBound;
|
|
||||||
|
|
||||||
// The lowerBound is larger than iStart, which means we fail to find an early exit at the run
|
|
||||||
// where the insertion happens. We can just break out.
|
|
||||||
if (lowerBound > iStart)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're about to cover the entire existing run with a new one, we can also make an optimization.
|
|
||||||
if (iStart == 0 && iEnd == iLastBufferCol)
|
|
||||||
{
|
|
||||||
// Just dump what we're given over what we have and call it a day.
|
|
||||||
_list.assign(newAttrs.begin(), newAttrs.end());
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the worst case scenario, we will need a new run that is the length of
|
|
||||||
// The existing run in memory + The new run in memory + 1.
|
|
||||||
// This worst case occurs when we inject a new item in the middle of an existing run like so
|
|
||||||
// Existing R3->B5->G2, Insertion Y2 starting at 5 (in the middle of the B5)
|
|
||||||
// becomes R3->B2->Y2->B1->G2.
|
|
||||||
// The original run was 3 long. The insertion run was 1 long. We need 1 more for the
|
|
||||||
// fact that an existing piece of the run was split in half (to hold the latter half).
|
|
||||||
const size_t cNewRun = _list.size() + newAttrs.size() + 1;
|
|
||||||
decltype(_list) newRun;
|
|
||||||
newRun.reserve(cNewRun);
|
|
||||||
|
|
||||||
// We will start analyzing from the beginning of our existing run.
|
|
||||||
// Use some pointers to keep track of where we are in walking through our runs.
|
|
||||||
|
|
||||||
// Get the existing run that we'll be updating/manipulating.
|
|
||||||
const auto existingRun = _list.begin();
|
|
||||||
auto pExistingRunPos = existingRun;
|
|
||||||
const auto pExistingRunEnd = _list.end();
|
|
||||||
auto pInsertRunPos = newAttrs.begin();
|
|
||||||
size_t cInsertRunRemaining = newAttrs.size();
|
|
||||||
size_t iExistingRunCoverage = 0;
|
|
||||||
|
|
||||||
// Copy the existing run into the new buffer up to the "start index" where the new run will be injected.
|
|
||||||
// If the new run starts at 0, we have nothing to copy from the beginning.
|
|
||||||
if (iStart != 0)
|
|
||||||
{
|
|
||||||
// While we're less than the desired insertion position...
|
|
||||||
while (iExistingRunCoverage < iStart)
|
|
||||||
{
|
|
||||||
// Add up how much length we can cover by copying an item from the existing run.
|
|
||||||
iExistingRunCoverage += pExistingRunPos->GetLength();
|
|
||||||
|
|
||||||
// Copy it to the new run buffer and advance both pointers.
|
|
||||||
newRun.push_back(*pExistingRunPos++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When we get to this point, we've copied full segments from the original existing run
|
|
||||||
// into our new run buffer. We will have 1 or more full segments of color attributes and
|
|
||||||
// we MIGHT have to cut the last copied segment's length back depending on where the inserted
|
|
||||||
// attributes will fall in the final/new run.
|
|
||||||
// Some examples:
|
|
||||||
// - Starting with the original string R3 -> G5 -> B2
|
|
||||||
// - 1. If the insertion is Y5 at start index 3
|
|
||||||
// We are trying to get a result/final/new run of R3 -> Y5 -> B2.
|
|
||||||
// We just copied R3 to the new destination buffer and we cang skip down and start inserting the new attrs.
|
|
||||||
// - 2. If the insertion is Y3 at start index 5
|
|
||||||
// We are trying to get a result/final/new run of R3 -> G2 -> Y3 -> B2.
|
|
||||||
// We just copied R3 -> G5 to the new destination buffer with the code above.
|
|
||||||
// But the insertion is going to cut out some of the length of the G5.
|
|
||||||
// We need to fix this up below so it says G2 instead to leave room for the Y3 to fit in
|
|
||||||
// the new/final run.
|
|
||||||
|
|
||||||
// Fetch out the length so we can fix it up based on the below conditions.
|
|
||||||
size_t length = newRun.back().GetLength();
|
|
||||||
|
|
||||||
// If we've covered more cells already than the start of the attributes to be inserted...
|
|
||||||
if (iExistingRunCoverage > iStart)
|
|
||||||
{
|
|
||||||
// ..then subtract some of the length of the final cell we copied.
|
|
||||||
// We want to take remove the difference in distance between the cells we've covered in the new
|
|
||||||
// run and the insertion point.
|
|
||||||
// (This turns G5 into G2 from Example 2 just above)
|
|
||||||
length -= (iExistingRunCoverage - iStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we're still on that "last cell copied" into the new run.
|
|
||||||
// If the color of that existing copied cell matches the color of the first segment
|
|
||||||
// of the run we're about to insert, we can just increment the length to extend the coverage.
|
|
||||||
if (newRun.back().GetAttributes() == pInsertRunPos->GetAttributes())
|
|
||||||
{
|
|
||||||
length += pInsertRunPos->GetLength();
|
|
||||||
|
|
||||||
// Since the color matched, we have already "used up" part of the insert run
|
|
||||||
// and can skip it in our big "memcopy" step below that will copy the bulk of the insert run.
|
|
||||||
cInsertRunRemaining--;
|
|
||||||
pInsertRunPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're done manipulating the length. Store it back.
|
|
||||||
newRun.back().SetLength(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bulk copy the majority (or all, depending on circumstance) of the insert run into the final run buffer.
|
|
||||||
std::copy_n(pInsertRunPos, cInsertRunRemaining, std::back_inserter(newRun));
|
|
||||||
|
|
||||||
// We're technically done with the insert run now and have 0 remaining, but won't bother updating its pointers
|
|
||||||
// and counts any further because we won't use them.
|
|
||||||
|
|
||||||
// Now we need to move our pointer for the original existing run forward and update our counts
|
|
||||||
// on how many cells we could have copied from the source before finishing off the new run.
|
|
||||||
while (iExistingRunCoverage <= iEnd)
|
|
||||||
{
|
|
||||||
FAIL_FAST_IF(!(pExistingRunPos != pExistingRunEnd));
|
|
||||||
iExistingRunCoverage += pExistingRunPos->GetLength();
|
|
||||||
pExistingRunPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we still have original existing run cells remaining, copy them into the final new run.
|
|
||||||
if (pExistingRunPos != pExistingRunEnd || iExistingRunCoverage != (iEnd + 1))
|
|
||||||
{
|
|
||||||
// We advanced the existing run pointer and its count to on or past the end of what the insertion run filled in.
|
|
||||||
// If this ended up being past the end of what the insertion run covers, we have to account for the cells after
|
|
||||||
// the insertion run but before the next piece of the original existing run.
|
|
||||||
// The example in this case is if we had...
|
|
||||||
// Existing Run = R3 -> G5 -> B2 -> X5
|
|
||||||
// Insert Run = Y2 @ iStart = 7 and iEnd = 8
|
|
||||||
// ... then at this point in time, our states would look like...
|
|
||||||
// New Run so far = R3 -> G4 -> Y2
|
|
||||||
// Existing Run Pointer is at X5
|
|
||||||
// Existing run coverage count at 3 + 5 + 2 = 10.
|
|
||||||
// However, in order to get the final desired New Run
|
|
||||||
// (which is R3 -> G4 -> Y2 -> B1 -> X5)
|
|
||||||
// we would need to grab a piece of that B2 we already skipped past.
|
|
||||||
// iExistingRunCoverage = 10. iEnd = 8. iEnd+1 = 9. 10 > 9. So we skipped something.
|
|
||||||
if (iExistingRunCoverage > (iEnd + 1))
|
|
||||||
{
|
|
||||||
// Back up the existing run pointer so we can grab the piece we skipped.
|
|
||||||
pExistingRunPos--;
|
|
||||||
|
|
||||||
// If the color matches what's already in our run, just increment the count value.
|
|
||||||
// This case is slightly off from the example above. This case is for if the B2 above was actually Y2.
|
|
||||||
// That Y2 from the existing run is the same color as the Y2 we just filled a few columns left in the final run
|
|
||||||
// so we can just adjust the final run's column count instead of adding another segment here.
|
|
||||||
if (newRun.back().GetAttributes() == pExistingRunPos->GetAttributes())
|
|
||||||
{
|
|
||||||
size_t length = newRun.back().GetLength();
|
|
||||||
length += (iExistingRunCoverage - (iEnd + 1));
|
|
||||||
newRun.back().SetLength(length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the color didn't match, then we just need to copy the piece we skipped and adjust
|
|
||||||
// its length for the discrepancy in columns not yet covered by the final/new run.
|
|
||||||
|
|
||||||
// Move forward to a blank spot in the new run
|
|
||||||
newRun.emplace_back();
|
|
||||||
|
|
||||||
// Copy the existing run's color information to the new run
|
|
||||||
newRun.back().SetAttributes(pExistingRunPos->GetAttributes());
|
|
||||||
|
|
||||||
// Adjust the length of that copied color to cover only the reduced number of columns needed
|
|
||||||
// now that some have been replaced by the insert run.
|
|
||||||
newRun.back().SetLength(iExistingRunCoverage - (iEnd + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we're done recovering a piece of the existing run we skipped, move the pointer forward again.
|
|
||||||
pExistingRunPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OK. In this case, we didn't skip anything. The end of the insert run fell right at a boundary
|
|
||||||
// in columns that was in the original existing run.
|
|
||||||
// However, the next piece of the original existing run might happen to have the same color attribute
|
|
||||||
// as the final piece of what we just copied.
|
|
||||||
// As an example...
|
|
||||||
// Existing Run = R3 -> G5 -> B2.
|
|
||||||
// Insert Run = B5 @ iStart = 3 and iEnd = 7
|
|
||||||
// New Run so far = R3 -> B5
|
|
||||||
// New Run desired when done = R3 -> B7
|
|
||||||
// Existing run pointer is on B2.
|
|
||||||
// We want to merge the 2 from the B2 into the B5 so we get B7.
|
|
||||||
else if (newRun.back().GetAttributes() == pExistingRunPos->GetAttributes())
|
|
||||||
{
|
|
||||||
// Add the value from the existing run into the current new run position.
|
|
||||||
size_t length = newRun.back().GetLength();
|
|
||||||
length += pExistingRunPos->GetLength();
|
|
||||||
newRun.back().SetLength(length);
|
|
||||||
|
|
||||||
// Advance the existing run position since we consumed its value and merged it in.
|
|
||||||
pExistingRunPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now bulk copy any segments left in the original existing run
|
|
||||||
if (pExistingRunPos < pExistingRunEnd)
|
|
||||||
{
|
|
||||||
std::copy_n(pExistingRunPos, (pExistingRunEnd - pExistingRunPos), std::back_inserter(newRun));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OK, phew. We're done. Now we just need to free the existing run and store the new run in its place.
|
|
||||||
_list.swap(newRun);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
CATCH_RETURN()
|
||||||
// Routine Description:
|
|
||||||
// - packs a vector of TextAttribute into a vector of TextAttributeRun
|
|
||||||
// Arguments:
|
|
||||||
// - attrs - text attributes to pack
|
|
||||||
// Return Value:
|
|
||||||
// - packed text attribute run
|
|
||||||
std::vector<TextAttributeRun> ATTR_ROW::PackAttrs(const std::vector<TextAttribute>& attrs)
|
|
||||||
{
|
|
||||||
std::vector<TextAttributeRun> runs;
|
|
||||||
if (attrs.empty())
|
|
||||||
{
|
|
||||||
return runs;
|
|
||||||
}
|
|
||||||
for (auto attr : attrs)
|
|
||||||
{
|
|
||||||
if (runs.empty() || runs.back().GetAttributes() != attr)
|
|
||||||
{
|
|
||||||
runs.emplace_back(TextAttributeRun(1, attr));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
runs.back().SetLength(runs.back().GetLength() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return runs;
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTR_ROW::const_iterator ATTR_ROW::begin() const noexcept
|
|
||||||
{
|
|
||||||
return AttrRowIterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTR_ROW::const_iterator ATTR_ROW::end() const noexcept
|
|
||||||
{
|
|
||||||
return AttrRowIterator::CreateEndIterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTR_ROW::const_iterator ATTR_ROW::cbegin() const noexcept
|
|
||||||
{
|
|
||||||
return AttrRowIterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTR_ROW::const_iterator ATTR_ROW::cend() const noexcept
|
|
||||||
{
|
|
||||||
return AttrRowIterator::CreateEndIterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept
|
|
||||||
{
|
|
||||||
return (a._list.size() == b._list.size() &&
|
|
||||||
a._list.data() == b._list.data() &&
|
|
||||||
a._cchRowWidth == b._cchRowWidth);
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,37 +20,27 @@ Revision History:
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "TextAttributeRun.hpp"
|
#include "til/rle.h"
|
||||||
#include "AttrRowIterator.hpp"
|
|
||||||
|
|
||||||
class ATTR_ROW final
|
#include "TextAttributeRun.hpp"
|
||||||
|
|
||||||
|
class ATTR_ROW final : public til::rle<TextAttribute, unsigned int>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using const_iterator = typename AttrRowIterator;
|
using mybase = til::rle<TextAttribute, unsigned int>;
|
||||||
|
|
||||||
ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr)
|
using const_iterator = mybase::const_iterator;
|
||||||
noexcept;
|
using const_reverse_iterator = mybase::const_reverse_iterator;
|
||||||
|
|
||||||
~ATTR_ROW() = default;
|
using mybase::mybase; // use base constructor
|
||||||
|
|
||||||
ATTR_ROW(const ATTR_ROW&) = default;
|
|
||||||
ATTR_ROW& operator=(const ATTR_ROW&) = default;
|
|
||||||
ATTR_ROW(ATTR_ROW&&)
|
|
||||||
noexcept = default;
|
|
||||||
ATTR_ROW& operator=(ATTR_ROW&&) noexcept = default;
|
|
||||||
|
|
||||||
TextAttribute GetAttrByColumn(const size_t column) const;
|
TextAttribute GetAttrByColumn(const size_t column) const;
|
||||||
TextAttribute GetAttrByColumn(const size_t column,
|
TextAttribute GetAttrByColumn(const size_t column,
|
||||||
size_t* const pApplies) const;
|
size_t* const pApplies) const;
|
||||||
|
|
||||||
size_t GetNumberOfRuns() const noexcept;
|
|
||||||
|
|
||||||
size_t FindAttrIndex(const size_t index,
|
|
||||||
size_t* const pApplies) const;
|
|
||||||
|
|
||||||
std::vector<uint16_t> GetHyperlinks();
|
std::vector<uint16_t> GetHyperlinks();
|
||||||
|
|
||||||
bool SetAttrToEnd(const UINT iStart, const TextAttribute attr);
|
bool SetAttrToEnd(const unsigned int iStart, const TextAttribute attr);
|
||||||
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept;
|
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept;
|
||||||
|
|
||||||
void Resize(const size_t newWidth);
|
void Resize(const size_t newWidth);
|
||||||
|
@ -60,26 +50,19 @@ public:
|
||||||
const size_t iEnd,
|
const size_t iEnd,
|
||||||
const size_t cBufferWidth);
|
const size_t cBufferWidth);
|
||||||
|
|
||||||
static std::vector<TextAttributeRun> PackAttrs(const std::vector<TextAttribute>& attrs);
|
using mybase::begin;
|
||||||
|
using mybase::cbegin;
|
||||||
|
using mybase::cend;
|
||||||
|
using mybase::end;
|
||||||
|
|
||||||
const_iterator begin() const noexcept;
|
using mybase::operator==;
|
||||||
const_iterator end() const noexcept;
|
|
||||||
|
|
||||||
const_iterator cbegin() const noexcept;
|
|
||||||
const_iterator cend() const noexcept;
|
|
||||||
|
|
||||||
friend bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept;
|
|
||||||
friend class AttrRowIterator;
|
|
||||||
friend class ROW;
|
friend class ROW;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Reset(const TextAttribute attr);
|
void Reset(const TextAttribute attr);
|
||||||
|
|
||||||
boost::container::small_vector<TextAttributeRun, 1> _list;
|
|
||||||
size_t _cchRowWidth;
|
|
||||||
|
|
||||||
#ifdef UNIT_TESTING
|
#ifdef UNIT_TESTING
|
||||||
friend class AttrRowTests;
|
|
||||||
friend class CommonState;
|
friend class CommonState;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,29 +22,23 @@ Revision History:
|
||||||
|
|
||||||
#include "TextAttribute.hpp"
|
#include "TextAttribute.hpp"
|
||||||
|
|
||||||
class TextAttributeRun final
|
class TextAttributeRun final : public std::pair<TextAttribute, unsigned int>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextAttributeRun() = default;
|
using mybase = std::pair<TextAttribute, unsigned int>;
|
||||||
TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept :
|
|
||||||
_cchLength(gsl::narrow<unsigned int>(cchLength))
|
using mybase::mybase;
|
||||||
|
|
||||||
|
TextAttributeRun(const size_t cchLength, const TextAttribute attr) :
|
||||||
|
mybase(attr, gsl::narrow<unsigned int>(cchLength))
|
||||||
{
|
{
|
||||||
SetAttributes(attr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLength() const noexcept { return _cchLength; }
|
size_t GetLength() const noexcept { return mybase::second; }
|
||||||
void SetLength(const size_t cchLength) noexcept { _cchLength = gsl::narrow<unsigned int>(cchLength); }
|
void SetLength(const size_t cchLength) noexcept { mybase::second = gsl::narrow<unsigned int>(cchLength); }
|
||||||
void IncrementLength() noexcept { _cchLength++; }
|
void IncrementLength() noexcept { mybase::second++; }
|
||||||
void DecrementLength() noexcept { _cchLength--; }
|
void DecrementLength() noexcept { mybase::second--; }
|
||||||
|
|
||||||
const TextAttribute& GetAttributes() const noexcept { return _attributes; }
|
const TextAttribute& GetAttributes() const noexcept { return mybase::first; }
|
||||||
void SetAttributes(const TextAttribute textAttribute) noexcept { _attributes = textAttribute; }
|
void SetAttributes(const TextAttribute textAttribute) noexcept { mybase::first = textAttribute; }
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int _cchLength{ 0 };
|
|
||||||
TextAttribute _attributes{ 0 };
|
|
||||||
|
|
||||||
#ifdef UNIT_TESTING
|
|
||||||
friend class AttrRowTests;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\AttrRow.cpp" />
|
<ClCompile Include="..\AttrRow.cpp" />
|
||||||
<ClCompile Include="..\AttrRowIterator.cpp" />
|
|
||||||
<ClCompile Include="..\cursor.cpp" />
|
<ClCompile Include="..\cursor.cpp" />
|
||||||
<ClCompile Include="..\OutputCell.cpp" />
|
<ClCompile Include="..\OutputCell.cpp" />
|
||||||
<ClCompile Include="..\OutputCellIterator.cpp" />
|
<ClCompile Include="..\OutputCellIterator.cpp" />
|
||||||
|
@ -34,7 +33,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\AttrRow.hpp" />
|
<ClInclude Include="..\AttrRow.hpp" />
|
||||||
<ClInclude Include="..\AttrRowIterator.hpp" />
|
|
||||||
<ClInclude Include="..\cursor.h" />
|
<ClInclude Include="..\cursor.h" />
|
||||||
<ClInclude Include="..\DbcsAttribute.hpp" />
|
<ClInclude Include="..\DbcsAttribute.hpp" />
|
||||||
<ClInclude Include="..\ICharRow.hpp" />
|
<ClInclude Include="..\ICharRow.hpp" />
|
||||||
|
|
|
@ -30,7 +30,6 @@ PRECOMPILED_INCLUDE = ..\precomp.h
|
||||||
|
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
..\AttrRow.cpp \
|
..\AttrRow.cpp \
|
||||||
..\AttrRowIterator.cpp \
|
|
||||||
..\cursor.cpp \
|
..\cursor.cpp \
|
||||||
..\OutputCell.cpp \
|
..\OutputCell.cpp \
|
||||||
..\OutputCellIterator.cpp \
|
..\OutputCellIterator.cpp \
|
||||||
|
|
|
@ -15,8 +15,8 @@ Author(s):
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AttrRowIterator.hpp"
|
|
||||||
#include "CharRow.hpp"
|
#include "CharRow.hpp"
|
||||||
|
#include "AttrRow.hpp"
|
||||||
#include "OutputCellView.hpp"
|
#include "OutputCellView.hpp"
|
||||||
#include "../../types/inc/viewport.hpp"
|
#include "../../types/inc/viewport.hpp"
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ protected:
|
||||||
OutputCellView _view;
|
OutputCellView _view;
|
||||||
|
|
||||||
const ROW* _pRow;
|
const ROW* _pRow;
|
||||||
AttrRowIterator _attrIter;
|
ATTR_ROW::const_iterator _attrIter;
|
||||||
const TextBuffer& _buffer;
|
const TextBuffer& _buffer;
|
||||||
const Microsoft::Console::Types::Viewport _bounds;
|
const Microsoft::Console::Types::Viewport _bounds;
|
||||||
bool _exceeded;
|
bool _exceeded;
|
||||||
|
|
|
@ -1,731 +0,0 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
#include "precomp.h"
|
|
||||||
#include "WexTestClass.h"
|
|
||||||
#include "../../../inc/consoletaeftemplates.hpp"
|
|
||||||
|
|
||||||
#include "../textBuffer.hpp"
|
|
||||||
|
|
||||||
using namespace WEX::Common;
|
|
||||||
using namespace WEX::Logging;
|
|
||||||
using namespace WEX::TestExecution;
|
|
||||||
|
|
||||||
namespace WEX
|
|
||||||
{
|
|
||||||
namespace TestExecution
|
|
||||||
{
|
|
||||||
template<>
|
|
||||||
class VerifyOutputTraits<TextAttributeRun>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static WEX::Common::NoThrowString ToString(const TextAttributeRun& tar)
|
|
||||||
{
|
|
||||||
return WEX::Common::NoThrowString().Format(
|
|
||||||
L"Length:%d, attr:%s",
|
|
||||||
tar.GetLength(),
|
|
||||||
VerifyOutputTraits<TextAttribute>::ToString(tar.GetAttributes()).GetBuffer());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class VerifyCompareTraits<TextAttributeRun, TextAttributeRun>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static bool AreEqual(const TextAttributeRun& expected, const TextAttributeRun& actual)
|
|
||||||
{
|
|
||||||
return expected.GetAttributes() == actual.GetAttributes() &&
|
|
||||||
expected.GetLength() == actual.GetLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool AreSame(const TextAttributeRun& expected, const TextAttributeRun& actual)
|
|
||||||
{
|
|
||||||
return &expected == &actual;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsLessThan(const TextAttributeRun&, const TextAttributeRun&) = delete;
|
|
||||||
|
|
||||||
static bool IsGreaterThan(const TextAttributeRun&, const TextAttributeRun&) = delete;
|
|
||||||
|
|
||||||
static bool IsNull(const TextAttributeRun& object)
|
|
||||||
{
|
|
||||||
return object.GetAttributes().IsLegacy() && object.GetAttributes().GetLegacyAttributes() == 0 &&
|
|
||||||
object.GetLength() == 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AttrRowTests
|
|
||||||
{
|
|
||||||
ATTR_ROW* pSingle;
|
|
||||||
ATTR_ROW* pChain;
|
|
||||||
|
|
||||||
short _sDefaultLength = 80;
|
|
||||||
short _sDefaultChainLength = 6;
|
|
||||||
|
|
||||||
short sChainSegLength;
|
|
||||||
short sChainLeftover;
|
|
||||||
short sChainSegmentsNeeded;
|
|
||||||
|
|
||||||
WORD __wDefaultAttr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
|
||||||
WORD __wDefaultChainAttr = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
|
|
||||||
TextAttribute _DefaultAttr = TextAttribute(__wDefaultAttr);
|
|
||||||
TextAttribute _DefaultChainAttr = TextAttribute(__wDefaultChainAttr);
|
|
||||||
|
|
||||||
TEST_CLASS(AttrRowTests);
|
|
||||||
|
|
||||||
TEST_METHOD_SETUP(MethodSetup)
|
|
||||||
{
|
|
||||||
pSingle = new ATTR_ROW(_sDefaultLength, _DefaultAttr);
|
|
||||||
|
|
||||||
// Segment length is the expected length divided by the row length
|
|
||||||
// E.g. row of 80, 4 segments, 20 segment length each
|
|
||||||
sChainSegLength = _sDefaultLength / _sDefaultChainLength;
|
|
||||||
|
|
||||||
// Leftover is spaces that don't fit evenly
|
|
||||||
// E.g. row of 81, 4 segments, 1 leftover length segment
|
|
||||||
sChainLeftover = _sDefaultLength % _sDefaultChainLength;
|
|
||||||
|
|
||||||
// Start with the number of segments we expect
|
|
||||||
sChainSegmentsNeeded = _sDefaultChainLength;
|
|
||||||
|
|
||||||
// If we had a remainder, add one more segment
|
|
||||||
if (sChainLeftover)
|
|
||||||
{
|
|
||||||
sChainSegmentsNeeded++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the chain
|
|
||||||
pChain = new ATTR_ROW(_sDefaultLength, _DefaultAttr);
|
|
||||||
pChain->_list.resize(sChainSegmentsNeeded);
|
|
||||||
|
|
||||||
// Attach all chain segments that are even multiples of the row length
|
|
||||||
for (short iChain = 0; iChain < _sDefaultChainLength; iChain++)
|
|
||||||
{
|
|
||||||
TextAttributeRun* pRun = &pChain->_list[iChain];
|
|
||||||
|
|
||||||
pRun->SetAttributes(TextAttribute{ gsl::narrow_cast<WORD>(iChain) }); // Just use the chain position as the value
|
|
||||||
pRun->SetLength(sChainSegLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sChainLeftover > 0)
|
|
||||||
{
|
|
||||||
// If we had a leftover, then this chain is one longer than we expected (the default length)
|
|
||||||
// So use it as the index (because indices start at 0)
|
|
||||||
TextAttributeRun* pRun = &pChain->_list[_sDefaultChainLength];
|
|
||||||
|
|
||||||
pRun->SetAttributes(_DefaultChainAttr);
|
|
||||||
pRun->SetLength(sChainLeftover);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD_CLEANUP(MethodCleanup)
|
|
||||||
{
|
|
||||||
delete pSingle;
|
|
||||||
|
|
||||||
delete pChain;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestInitialize)
|
|
||||||
{
|
|
||||||
// Properties needed for test
|
|
||||||
const WORD wAttr = FOREGROUND_RED | BACKGROUND_BLUE;
|
|
||||||
TextAttribute attr = TextAttribute(wAttr);
|
|
||||||
// Cases to test
|
|
||||||
ATTR_ROW* pTestItems[]{ pSingle, pChain };
|
|
||||||
|
|
||||||
// Loop cases
|
|
||||||
for (UINT iIndex = 0; iIndex < ARRAYSIZE(pTestItems); iIndex++)
|
|
||||||
{
|
|
||||||
ATTR_ROW* pUnderTest = pTestItems[iIndex];
|
|
||||||
|
|
||||||
pUnderTest->Reset(attr);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list.size(), 1u);
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list[0].GetAttributes(), attr);
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list[0].GetLength(), (unsigned int)_sDefaultLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Packs an array of words representing attributes into the more compact storage form used by the row.
|
|
||||||
// Arguments:
|
|
||||||
// - rgAttrs - Array of words representing the attribute associated with each character position in the row.
|
|
||||||
// - cRowLength - Length of preceding array.
|
|
||||||
// - outAttrRun - reference to unique_ptr that will contain packed attr run on success.
|
|
||||||
// Return Value:
|
|
||||||
// - Success if success. Buffer too small if row length is incorrect.
|
|
||||||
HRESULT PackAttrs(_In_reads_(cRowLength) const TextAttribute* const rgAttrs,
|
|
||||||
const size_t cRowLength,
|
|
||||||
_Inout_ std::unique_ptr<TextAttributeRun[]>& outAttrRun,
|
|
||||||
_Out_ size_t* const cOutAttrRun)
|
|
||||||
{
|
|
||||||
RETURN_HR_IF(E_NOT_SUFFICIENT_BUFFER, cRowLength == 0);
|
|
||||||
|
|
||||||
// first count up the deltas in the array
|
|
||||||
size_t cDeltas = 1;
|
|
||||||
|
|
||||||
const TextAttribute* pPrevAttr = &rgAttrs[0];
|
|
||||||
|
|
||||||
for (size_t i = 1; i < cRowLength; i++)
|
|
||||||
{
|
|
||||||
const TextAttribute* pCurAttr = &rgAttrs[i];
|
|
||||||
|
|
||||||
if (*pCurAttr != *pPrevAttr)
|
|
||||||
{
|
|
||||||
cDeltas++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPrevAttr = pCurAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This whole situation was too complicated with a one off holder for one row run
|
|
||||||
// new method:
|
|
||||||
// delete the old buffer
|
|
||||||
// make a new buffer, one run + one run for each change
|
|
||||||
// set the values for each run one run index at a time
|
|
||||||
|
|
||||||
std::unique_ptr<TextAttributeRun[]> attrRun = std::make_unique<TextAttributeRun[]>(cDeltas);
|
|
||||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, attrRun);
|
|
||||||
|
|
||||||
TextAttributeRun* pCurrentRun = attrRun.get();
|
|
||||||
pCurrentRun->SetAttributes(rgAttrs[0]);
|
|
||||||
pCurrentRun->SetLength(1);
|
|
||||||
for (size_t i = 1; i < cRowLength; i++)
|
|
||||||
{
|
|
||||||
if (pCurrentRun->GetAttributes() == rgAttrs[i])
|
|
||||||
{
|
|
||||||
pCurrentRun->SetLength(pCurrentRun->GetLength() + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pCurrentRun++;
|
|
||||||
pCurrentRun->SetAttributes(rgAttrs[i]);
|
|
||||||
pCurrentRun->SetLength(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attrRun.swap(outAttrRun);
|
|
||||||
*cOutAttrRun = cDeltas;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NoThrowString LogRunElement(_In_ TextAttributeRun& run)
|
|
||||||
{
|
|
||||||
return NoThrowString().Format(L"%wc%d", run.GetAttributes().GetLegacyAttributes(), run.GetLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogChain(_In_ PCWSTR pwszPrefix,
|
|
||||||
boost::container::small_vector_base<TextAttributeRun>& chain)
|
|
||||||
{
|
|
||||||
NoThrowString str(pwszPrefix);
|
|
||||||
|
|
||||||
if (chain.size() > 0)
|
|
||||||
{
|
|
||||||
str.Append(LogRunElement(chain[0]));
|
|
||||||
|
|
||||||
for (size_t i = 1; i < chain.size(); i++)
|
|
||||||
{
|
|
||||||
str.AppendFormat(L"->%s", (const wchar_t*)(LogRunElement(chain[i])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogChain(_In_ PCWSTR pwszPrefix,
|
|
||||||
std::vector<TextAttributeRun>& chain)
|
|
||||||
{
|
|
||||||
NoThrowString str(pwszPrefix);
|
|
||||||
|
|
||||||
if (chain.size() > 0)
|
|
||||||
{
|
|
||||||
str.Append(LogRunElement(chain[0]));
|
|
||||||
|
|
||||||
for (size_t i = 1; i < chain.size(); i++)
|
|
||||||
{
|
|
||||||
str.AppendFormat(L"->%s", (const wchar_t*)(LogRunElement(chain[i])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoTestInsertAttrRuns(UINT& uiStartPos, WORD& ch1, UINT& uiChar1Length, WORD& ch2, UINT& uiChar2Length)
|
|
||||||
{
|
|
||||||
Log::Comment(String().Format(L"StartPos: %d, Char1: %wc, Char1Length: %d, Char2: %wc, Char2Length: %d",
|
|
||||||
uiStartPos,
|
|
||||||
ch1,
|
|
||||||
uiChar1Length,
|
|
||||||
ch2,
|
|
||||||
uiChar2Length));
|
|
||||||
|
|
||||||
bool const fUseStr2 = (ch2 != L'0');
|
|
||||||
|
|
||||||
// Set up our "original row" that we are going to try to insert into.
|
|
||||||
// This will represent a 10 column run of R3->B5->G2 that we will use for all tests.
|
|
||||||
ATTR_ROW originalRow{ static_cast<UINT>(_sDefaultLength), _DefaultAttr };
|
|
||||||
originalRow._list.resize(3);
|
|
||||||
originalRow._cchRowWidth = 10;
|
|
||||||
originalRow._list[0].SetAttributes(TextAttribute{ 'R' });
|
|
||||||
originalRow._list[0].SetLength(3);
|
|
||||||
originalRow._list[1].SetAttributes(TextAttribute{ 'B' });
|
|
||||||
originalRow._list[1].SetLength(5);
|
|
||||||
originalRow._list[2].SetAttributes(TextAttribute{ 'G' });
|
|
||||||
originalRow._list[2].SetLength(2);
|
|
||||||
LogChain(L"Original: ", originalRow._list);
|
|
||||||
|
|
||||||
// Set up our "insertion run"
|
|
||||||
size_t cInsertRow = 1;
|
|
||||||
if (fUseStr2)
|
|
||||||
{
|
|
||||||
cInsertRow++;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TextAttributeRun> insertRow;
|
|
||||||
insertRow.resize(cInsertRow);
|
|
||||||
insertRow[0].SetAttributes(TextAttribute{ ch1 });
|
|
||||||
insertRow[0].SetLength(uiChar1Length);
|
|
||||||
if (fUseStr2)
|
|
||||||
{
|
|
||||||
insertRow[1].SetAttributes(TextAttribute{ ch2 });
|
|
||||||
insertRow[1].SetLength(uiChar2Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogChain(L"Insert: ", insertRow);
|
|
||||||
Log::Comment(NoThrowString().Format(L"At Index: %d", uiStartPos));
|
|
||||||
|
|
||||||
UINT uiTotalLength = uiChar1Length;
|
|
||||||
if (fUseStr2)
|
|
||||||
{
|
|
||||||
uiTotalLength += uiChar2Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERIFY_IS_TRUE((uiStartPos + uiTotalLength) >= 1); // assert we won't underflow.
|
|
||||||
UINT const uiEndPos = uiStartPos + uiTotalLength - 1;
|
|
||||||
|
|
||||||
// Calculate our expected final/result run by unpacking original, laying our insertion on it at the index
|
|
||||||
// then using our pack function to repack it.
|
|
||||||
// This method is easy to understand and very reliable, but its performance is bad.
|
|
||||||
// The InsertAttrRuns method we test against below is hard to understand but very high performance in production.
|
|
||||||
|
|
||||||
// - 1. Unpack
|
|
||||||
std::vector<TextAttribute> unpackedOriginal = { originalRow.begin(), originalRow.end() };
|
|
||||||
|
|
||||||
// - 2. Overlay insertion
|
|
||||||
UINT uiInsertedCount = 0;
|
|
||||||
UINT uiInsertIndex = 0;
|
|
||||||
|
|
||||||
// --- Walk through the unpacked run from start to end....
|
|
||||||
for (UINT uiUnpackedIndex = uiStartPos; uiUnpackedIndex <= uiEndPos; uiUnpackedIndex++)
|
|
||||||
{
|
|
||||||
// Pull the item from the insert run to analyze.
|
|
||||||
TextAttributeRun run = insertRow[uiInsertIndex];
|
|
||||||
|
|
||||||
// Copy the attribute from the run into the unpacked array
|
|
||||||
unpackedOriginal[uiUnpackedIndex] = run.GetAttributes();
|
|
||||||
|
|
||||||
// Increment how many times we've copied this particular portion of the run
|
|
||||||
uiInsertedCount++;
|
|
||||||
|
|
||||||
// If we've now inserted enough of them to match the length, advance the insert index and reset the counter.
|
|
||||||
if (uiInsertedCount >= run.GetLength())
|
|
||||||
{
|
|
||||||
uiInsertIndex++;
|
|
||||||
uiInsertedCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - 3. Pack.
|
|
||||||
std::unique_ptr<TextAttributeRun[]> packedRun;
|
|
||||||
size_t cPackedRun = 0;
|
|
||||||
VERIFY_SUCCEEDED(PackAttrs(unpackedOriginal.data(), originalRow._cchRowWidth, packedRun, &cPackedRun));
|
|
||||||
|
|
||||||
// Now send parameters into InsertAttrRuns and get its opinion on the subject.
|
|
||||||
VERIFY_SUCCEEDED(originalRow.InsertAttrRuns({ insertRow.data(), insertRow.size() }, uiStartPos, uiEndPos, (UINT)originalRow._cchRowWidth));
|
|
||||||
|
|
||||||
// Compare and ensure that the expected and actual match.
|
|
||||||
VERIFY_ARE_EQUAL(cPackedRun, originalRow._list.size(), L"Ensure that number of array elements required for RLE are the same.");
|
|
||||||
|
|
||||||
std::vector<TextAttributeRun> packedRunExpected;
|
|
||||||
std::copy_n(packedRun.get(), cPackedRun, std::back_inserter(packedRunExpected));
|
|
||||||
|
|
||||||
LogChain(L"Expected: ", packedRunExpected);
|
|
||||||
LogChain(L"Actual: ", originalRow._list);
|
|
||||||
|
|
||||||
for (size_t testIndex = 0; testIndex < cPackedRun; testIndex++)
|
|
||||||
{
|
|
||||||
VERIFY_ARE_EQUAL(packedRun[testIndex], originalRow._list[testIndex]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestInsertAttrRunsSingle)
|
|
||||||
{
|
|
||||||
UINT const uiTestRunLength = 10;
|
|
||||||
|
|
||||||
UINT uiStartPos = 0;
|
|
||||||
WORD ch1 = L'0';
|
|
||||||
UINT uiChar1Length = 0;
|
|
||||||
WORD ch2 = L'0';
|
|
||||||
UINT uiChar2Length = 0;
|
|
||||||
|
|
||||||
Log::Comment(L"Test inserting a single item of a variable length into the run.");
|
|
||||||
WORD rgch1Options[] = { L'X', L'R', L'G', L'B' };
|
|
||||||
for (size_t iCh1Option = 0; iCh1Option < ARRAYSIZE(rgch1Options); iCh1Option++)
|
|
||||||
{
|
|
||||||
ch1 = rgch1Options[iCh1Option];
|
|
||||||
for (UINT iCh1Length = 1; iCh1Length <= uiTestRunLength; iCh1Length++)
|
|
||||||
{
|
|
||||||
uiChar1Length = iCh1Length;
|
|
||||||
|
|
||||||
// We can't try to insert a run that's longer than would fit.
|
|
||||||
// If the run is of length 10 and we're trying to insert a length of 10,
|
|
||||||
// we can only insert at position 0.
|
|
||||||
// For the run length of 10 and an insert length of 9, we can try positions 0 and 1.
|
|
||||||
// And so on...
|
|
||||||
UINT const uiMaxPos = uiTestRunLength - uiChar1Length;
|
|
||||||
|
|
||||||
for (UINT iStartPos = 0; iStartPos < uiMaxPos; iStartPos++)
|
|
||||||
{
|
|
||||||
uiStartPos = iStartPos;
|
|
||||||
|
|
||||||
DoTestInsertAttrRuns(uiStartPos, ch1, uiChar1Length, ch2, uiChar2Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestInsertAttrRunsMultiple)
|
|
||||||
{
|
|
||||||
UINT const uiTestRunLength = 10;
|
|
||||||
|
|
||||||
UINT uiStartPos = 0;
|
|
||||||
WORD ch1 = L'0';
|
|
||||||
UINT uiChar1Length = 0;
|
|
||||||
WORD ch2 = L'0';
|
|
||||||
UINT uiChar2Length = 0;
|
|
||||||
|
|
||||||
Log::Comment(L"Test inserting a multiple item run with each piece having variable length into the existing run.");
|
|
||||||
WORD rgch1Options[] = { L'X', L'R', L'G', L'B' };
|
|
||||||
for (size_t iCh1Option = 0; iCh1Option < ARRAYSIZE(rgch1Options); iCh1Option++)
|
|
||||||
{
|
|
||||||
ch1 = rgch1Options[iCh1Option];
|
|
||||||
|
|
||||||
UINT const uiMaxCh1Length = uiTestRunLength - 1; // leave at least 1 space for the second piece of the insert run.
|
|
||||||
for (UINT iCh1Length = 1; iCh1Length <= uiMaxCh1Length; iCh1Length++)
|
|
||||||
{
|
|
||||||
uiChar1Length = iCh1Length;
|
|
||||||
|
|
||||||
WORD rgch2Options[] = { L'Y' };
|
|
||||||
for (size_t iCh2Option = 0; iCh2Option < ARRAYSIZE(rgch2Options); iCh2Option++)
|
|
||||||
{
|
|
||||||
ch2 = rgch2Options[iCh2Option];
|
|
||||||
|
|
||||||
// When choosing the length of the second item, it can't be bigger than the remaining space in the run
|
|
||||||
// when accounting for the length of the first piece chosen.
|
|
||||||
// For example if the total run length is 10 and the first piece chosen was 8 long,
|
|
||||||
// the second piece can only be 1 or 2 long.
|
|
||||||
UINT const uiMaxCh2Length = uiTestRunLength - uiMaxCh1Length;
|
|
||||||
for (UINT iCh2Length = 1; iCh2Length <= uiMaxCh2Length; iCh2Length++)
|
|
||||||
{
|
|
||||||
uiChar2Length = iCh2Length;
|
|
||||||
|
|
||||||
// We can't try to insert a run that's longer than would fit.
|
|
||||||
// If the run is of length 10 and we're trying to insert a total length of 10,
|
|
||||||
// we can only insert at position 0.
|
|
||||||
// For the run length of 10 and an insert length of 9, we can try positions 0 and 1.
|
|
||||||
// And so on...
|
|
||||||
UINT const uiMaxPos = uiTestRunLength - (uiChar1Length + uiChar2Length);
|
|
||||||
|
|
||||||
for (UINT iStartPos = 0; iStartPos <= uiMaxPos; iStartPos++)
|
|
||||||
{
|
|
||||||
uiStartPos = iStartPos;
|
|
||||||
|
|
||||||
DoTestInsertAttrRuns(uiStartPos, ch1, uiChar1Length, ch2, uiChar2Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestUnpackAttrs)
|
|
||||||
{
|
|
||||||
Log::Comment(L"Checking unpack of a single color for the entire length");
|
|
||||||
{
|
|
||||||
const std::vector<TextAttribute> attrs{ pSingle->begin(), pSingle->end() };
|
|
||||||
|
|
||||||
for (auto& attr : attrs)
|
|
||||||
{
|
|
||||||
VERIFY_ARE_EQUAL(attr, _DefaultAttr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(L"Checking unpack of the multiple color chain");
|
|
||||||
|
|
||||||
const std::vector<TextAttribute> attrs{ pChain->begin(), pChain->end() };
|
|
||||||
|
|
||||||
short cChainRun = 0; // how long we've been looking at the current piece of the chain
|
|
||||||
short iChainSegIndex = 0; // which piece of the chain we should be on right now
|
|
||||||
|
|
||||||
for (auto& attr : attrs)
|
|
||||||
{
|
|
||||||
// by default the chain was assembled above to have the chain segment index be the attribute
|
|
||||||
TextAttribute MatchingAttr = TextAttribute(iChainSegIndex);
|
|
||||||
|
|
||||||
// However, if the index is greater than the expected chain length, a remainder piece was made with a default attribute
|
|
||||||
if (iChainSegIndex >= _sDefaultChainLength)
|
|
||||||
{
|
|
||||||
MatchingAttr = _DefaultChainAttr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(attr, MatchingAttr);
|
|
||||||
|
|
||||||
// Add to the chain run
|
|
||||||
cChainRun++;
|
|
||||||
|
|
||||||
// If the chain run is greater than the length the segments were specified to be
|
|
||||||
if (cChainRun >= sChainSegLength)
|
|
||||||
{
|
|
||||||
// reset to 0
|
|
||||||
cChainRun = 0;
|
|
||||||
|
|
||||||
// move to the next chain segment down the line
|
|
||||||
iChainSegIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestReverseIteratorWalkFromMiddle)
|
|
||||||
{
|
|
||||||
// GH #3409, walking backwards through color range runs out of bounds
|
|
||||||
// We're going to create an attribute row with assorted colors and varying lengths
|
|
||||||
// just like the row of text on the Ubuntu prompt line that triggered this bug being found.
|
|
||||||
// Then we're going to walk backwards through the iterator like a selection-expand-to-left
|
|
||||||
// operation and ensure we don't run off the bounds.
|
|
||||||
|
|
||||||
// walk the chain, from index, stepSize at a time
|
|
||||||
// ensure we don't crash
|
|
||||||
auto testWalk = [](ATTR_ROW* chain, size_t index, int stepSize) {
|
|
||||||
// move to starting index
|
|
||||||
auto iter = chain->cbegin();
|
|
||||||
iter += index;
|
|
||||||
|
|
||||||
// Now walk backwards in a loop until 0.
|
|
||||||
while (iter)
|
|
||||||
{
|
|
||||||
iter -= stepSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(L"We made it through without crashing!");
|
|
||||||
};
|
|
||||||
|
|
||||||
// take one step of size stepSize on the chain
|
|
||||||
// index is where we start from
|
|
||||||
// expectedAttribute is what we expect to read here
|
|
||||||
auto verifyStep = [](ATTR_ROW* chain, size_t index, int stepSize, TextAttribute expectedAttribute) {
|
|
||||||
// move to starting index
|
|
||||||
auto iter = chain->cbegin();
|
|
||||||
iter += index;
|
|
||||||
|
|
||||||
// Now step backwards
|
|
||||||
iter -= stepSize;
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(expectedAttribute, *iter);
|
|
||||||
};
|
|
||||||
|
|
||||||
Log::Comment(L"Reverse iterate through ubuntu prompt");
|
|
||||||
{
|
|
||||||
// Create attr row representing a buffer that's 121 wide.
|
|
||||||
auto chain = std::make_unique<ATTR_ROW>(121, _DefaultAttr);
|
|
||||||
|
|
||||||
// The repro case had 4 chain segments.
|
|
||||||
chain->_list.resize(4);
|
|
||||||
|
|
||||||
// The color 10 went for the first 18.
|
|
||||||
chain->_list[0].SetAttributes(TextAttribute(0xA));
|
|
||||||
chain->_list[0].SetLength(18);
|
|
||||||
|
|
||||||
// Default color for the next 1
|
|
||||||
chain->_list[1].SetAttributes(TextAttribute());
|
|
||||||
chain->_list[1].SetLength(1);
|
|
||||||
|
|
||||||
// Color 12 for the next 29
|
|
||||||
chain->_list[2].SetAttributes(TextAttribute(0xC));
|
|
||||||
chain->_list[2].SetLength(29);
|
|
||||||
|
|
||||||
// Then default color to end the run
|
|
||||||
chain->_list[3].SetAttributes(TextAttribute());
|
|
||||||
chain->_list[3].SetLength(73);
|
|
||||||
|
|
||||||
// The sum of the lengths should be 121.
|
|
||||||
VERIFY_ARE_EQUAL(chain->_cchRowWidth, chain->_list[0]._cchLength + chain->_list[1]._cchLength + chain->_list[2]._cchLength + chain->_list[3]._cchLength);
|
|
||||||
|
|
||||||
auto index = chain->_list[0].GetLength();
|
|
||||||
auto stepSize = 1;
|
|
||||||
testWalk(chain.get(), index, stepSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(L"Reverse iterate across a text run in the chain");
|
|
||||||
{
|
|
||||||
// Create attr row representing a buffer that's 3 wide.
|
|
||||||
auto chain = std::make_unique<ATTR_ROW>(3, _DefaultAttr);
|
|
||||||
|
|
||||||
// The repro case had 3 chain segments.
|
|
||||||
chain->_list.resize(3);
|
|
||||||
|
|
||||||
// The color 10 went for the first 1.
|
|
||||||
chain->_list[0].SetAttributes(TextAttribute(0xA));
|
|
||||||
chain->_list[0].SetLength(1);
|
|
||||||
|
|
||||||
// The color 11 for the next 1
|
|
||||||
chain->_list[1].SetAttributes(TextAttribute(0xB));
|
|
||||||
chain->_list[1].SetLength(1);
|
|
||||||
|
|
||||||
// Color 12 for the next 1
|
|
||||||
chain->_list[2].SetAttributes(TextAttribute(0xC));
|
|
||||||
chain->_list[2].SetLength(1);
|
|
||||||
|
|
||||||
// The sum of the lengths should be 3.
|
|
||||||
VERIFY_ARE_EQUAL(chain->_cchRowWidth, chain->_list[0]._cchLength + chain->_list[1]._cchLength + chain->_list[2]._cchLength);
|
|
||||||
|
|
||||||
// on 'ABC', step from B to A
|
|
||||||
auto index = 1;
|
|
||||||
auto stepSize = 1;
|
|
||||||
verifyStep(chain.get(), index, stepSize, TextAttribute(0xA));
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::Comment(L"Reverse iterate across two text runs in the chain");
|
|
||||||
{
|
|
||||||
// Create attr row representing a buffer that's 3 wide.
|
|
||||||
auto chain = std::make_unique<ATTR_ROW>(3, _DefaultAttr);
|
|
||||||
|
|
||||||
// The repro case had 3 chain segments.
|
|
||||||
chain->_list.resize(3);
|
|
||||||
|
|
||||||
// The color 10 went for the first 1.
|
|
||||||
chain->_list[0].SetAttributes(TextAttribute(0xA));
|
|
||||||
chain->_list[0].SetLength(1);
|
|
||||||
|
|
||||||
// The color 11 for the next 1
|
|
||||||
chain->_list[1].SetAttributes(TextAttribute(0xB));
|
|
||||||
chain->_list[1].SetLength(1);
|
|
||||||
|
|
||||||
// Color 12 for the next 1
|
|
||||||
chain->_list[2].SetAttributes(TextAttribute(0xC));
|
|
||||||
chain->_list[2].SetLength(1);
|
|
||||||
|
|
||||||
// The sum of the lengths should be 3.
|
|
||||||
VERIFY_ARE_EQUAL(chain->_cchRowWidth, chain->_list[0]._cchLength + chain->_list[1]._cchLength + chain->_list[2]._cchLength);
|
|
||||||
|
|
||||||
// on 'ABC', step from C to A
|
|
||||||
auto index = 2;
|
|
||||||
auto stepSize = 2;
|
|
||||||
verifyStep(chain.get(), index, stepSize, TextAttribute(0xA));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestSetAttrToEnd)
|
|
||||||
{
|
|
||||||
const WORD wTestAttr = FOREGROUND_BLUE | BACKGROUND_GREEN;
|
|
||||||
TextAttribute TestAttr = TextAttribute(wTestAttr);
|
|
||||||
|
|
||||||
Log::Comment(L"FIRST: Set index to > 0 to test making/modifying chains");
|
|
||||||
const short iTestIndex = 50;
|
|
||||||
VERIFY_IS_TRUE(iTestIndex >= 0 && iTestIndex < _sDefaultLength);
|
|
||||||
|
|
||||||
Log::Comment(L"SetAttrToEnd for single color applied to whole string.");
|
|
||||||
pSingle->SetAttrToEnd(iTestIndex, TestAttr);
|
|
||||||
|
|
||||||
// Was 1 (single), should now have 2 segments
|
|
||||||
VERIFY_ARE_EQUAL(pSingle->_list.size(), 2u);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(pSingle->_list[0].GetAttributes(), _DefaultAttr);
|
|
||||||
VERIFY_ARE_EQUAL(pSingle->_list[0].GetLength(), (unsigned int)(_sDefaultLength - (_sDefaultLength - iTestIndex)));
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(pSingle->_list[1].GetAttributes(), TestAttr);
|
|
||||||
VERIFY_ARE_EQUAL(pSingle->_list[1].GetLength(), (unsigned int)(_sDefaultLength - iTestIndex));
|
|
||||||
|
|
||||||
Log::Comment(L"SetAttrToEnd for existing chain of multiple colors.");
|
|
||||||
pChain->SetAttrToEnd(iTestIndex, TestAttr);
|
|
||||||
|
|
||||||
// From 7 segments down to 5.
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list.size(), 5u);
|
|
||||||
|
|
||||||
// Verify chain colors and lengths
|
|
||||||
VERIFY_ARE_EQUAL(TextAttribute(0), pChain->_list[0].GetAttributes());
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list[0].GetLength(), (unsigned int)13);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(TextAttribute(1), pChain->_list[1].GetAttributes());
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list[1].GetLength(), (unsigned int)13);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(TextAttribute(2), pChain->_list[2].GetAttributes());
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list[2].GetLength(), (unsigned int)13);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(TextAttribute(3), pChain->_list[3].GetAttributes());
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list[3].GetLength(), (unsigned int)11);
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(TestAttr, pChain->_list[4].GetAttributes());
|
|
||||||
VERIFY_ARE_EQUAL(pChain->_list[4].GetLength(), (unsigned int)30);
|
|
||||||
|
|
||||||
Log::Comment(L"SECOND: Set index to 0 to test replacing anything with a single");
|
|
||||||
|
|
||||||
ATTR_ROW* pTestItems[]{ pSingle, pChain };
|
|
||||||
|
|
||||||
for (UINT iIndex = 0; iIndex < ARRAYSIZE(pTestItems); iIndex++)
|
|
||||||
{
|
|
||||||
ATTR_ROW* pUnderTest = pTestItems[iIndex];
|
|
||||||
|
|
||||||
pUnderTest->SetAttrToEnd(0, TestAttr);
|
|
||||||
|
|
||||||
// should be down to 1 attribute set from beginning to end of string
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list.size(), 1u);
|
|
||||||
|
|
||||||
// singular pair should contain the color
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list[0].GetAttributes(), TestAttr);
|
|
||||||
|
|
||||||
// and its length should be the length of the whole string
|
|
||||||
VERIFY_ARE_EQUAL(pUnderTest->_list[0].GetLength(), (unsigned int)_sDefaultLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestTotalLength)
|
|
||||||
{
|
|
||||||
ATTR_ROW* pTestItems[]{ pSingle, pChain };
|
|
||||||
|
|
||||||
for (UINT iIndex = 0; iIndex < ARRAYSIZE(pTestItems); iIndex++)
|
|
||||||
{
|
|
||||||
ATTR_ROW* pUnderTest = pTestItems[iIndex];
|
|
||||||
|
|
||||||
const size_t Result = pUnderTest->_cchRowWidth;
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL((short)Result, _sDefaultLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD(TestResize)
|
|
||||||
{
|
|
||||||
pSingle->Resize(240);
|
|
||||||
pChain->Resize(240);
|
|
||||||
|
|
||||||
pSingle->Resize(255);
|
|
||||||
pChain->Resize(255);
|
|
||||||
|
|
||||||
pSingle->Resize(255);
|
|
||||||
pChain->Resize(255);
|
|
||||||
|
|
||||||
pSingle->Resize(60);
|
|
||||||
pChain->Resize(60);
|
|
||||||
|
|
||||||
pSingle->Resize(60);
|
|
||||||
pChain->Resize(60);
|
|
||||||
|
|
||||||
VERIFY_THROWS_SPECIFIC(pSingle->Resize(0), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_INVALIDARG; });
|
|
||||||
VERIFY_THROWS_SPECIFIC(pChain->Resize(0), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_INVALIDARG; });
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -6,11 +6,10 @@
|
||||||
<RootNamespace>TextBufferUnitTests</RootNamespace>
|
<RootNamespace>TextBufferUnitTests</RootNamespace>
|
||||||
<ProjectName>TextBuffer.Unit.Tests</ProjectName>
|
<ProjectName>TextBuffer.Unit.Tests</ProjectName>
|
||||||
<TargetName>TextBuffer.Unit.Tests</TargetName>
|
<TargetName>TextBuffer.Unit.Tests</TargetName>
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AttrRowTests.cpp" />
|
|
||||||
<ClCompile Include="ReflowTests.cpp" />
|
<ClCompile Include="ReflowTests.cpp" />
|
||||||
<ClCompile Include="TextColorTests.cpp" />
|
<ClCompile Include="TextColorTests.cpp" />
|
||||||
<ClCompile Include="TextAttributeTests.cpp" />
|
<ClCompile Include="TextAttributeTests.cpp" />
|
||||||
|
|
|
@ -14,7 +14,6 @@ DLLDEF =
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$(SOURCES) \
|
$(SOURCES) \
|
||||||
AttrRowTests.cpp \
|
|
||||||
ReflowTests.cpp \
|
ReflowTests.cpp \
|
||||||
TextColorTests.cpp \
|
TextColorTests.cpp \
|
||||||
TextAttributeTests.cpp \
|
TextAttributeTests.cpp \
|
||||||
|
|
|
@ -106,4 +106,4 @@
|
||||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||||
<Import Project="$(SolutionDir)src\common.build.tests.props" />
|
<Import Project="$(SolutionDir)src\common.build.tests.props" />
|
||||||
</Project>
|
</Project>
|
|
@ -111,6 +111,9 @@
|
||||||
<ClCompile Include="ObjectTests.cpp">
|
<ClCompile Include="ObjectTests.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ConptyOutputTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="UnicodeLiteral.hpp">
|
<ClInclude Include="UnicodeLiteral.hpp">
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <numeric>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "til/point.h"
|
#include "til/point.h"
|
||||||
#include "til/operators.h"
|
#include "til/operators.h"
|
||||||
#include "til/rectangle.h"
|
#include "til/rectangle.h"
|
||||||
|
#include "til/rle.h"
|
||||||
#include "til/bitmap.h"
|
#include "til/bitmap.h"
|
||||||
#include "til/u8u16convert.h"
|
#include "til/u8u16convert.h"
|
||||||
#include "til/spsc.h"
|
#include "til/spsc.h"
|
||||||
|
|
1161
src/inc/til/rle.h
Normal file
1161
src/inc/til/rle.h
Normal file
File diff suppressed because it is too large
Load diff
744
src/til/ut_til/RunLengthEncodingTests.cpp
Normal file
744
src/til/ut_til/RunLengthEncodingTests.cpp
Normal file
|
@ -0,0 +1,744 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
#include "til/rle.h"
|
||||||
|
|
||||||
|
using namespace WEX::Common;
|
||||||
|
using namespace WEX::Logging;
|
||||||
|
using namespace WEX::TestExecution;
|
||||||
|
|
||||||
|
class RunLengthEncodingTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(RunLengthEncodingTests);
|
||||||
|
|
||||||
|
// NOTE: In some cases, these tests are also about ensuring that the various scenarios
|
||||||
|
// for template usage can compile correctly and will have minimal exercised functionality
|
||||||
|
// at unit test runtime.
|
||||||
|
|
||||||
|
TEST_METHOD(ConstructEmpty)
|
||||||
|
{
|
||||||
|
til::rle<unsigned int> rle;
|
||||||
|
VERIFY_ARE_EQUAL(0, rle.size());
|
||||||
|
VERIFY_ARE_EQUAL(rle.cbegin(), rle.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstructDefaultLength)
|
||||||
|
{
|
||||||
|
til::rle<unsigned int> rle(86, 9);
|
||||||
|
VERIFY_ARE_EQUAL(86, rle.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstructVerySmall)
|
||||||
|
{
|
||||||
|
const til::rle<unsigned short, unsigned char> rle(12, 37);
|
||||||
|
VERIFY_ARE_EQUAL(12, rle.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstructWithMinimumLoadSize)
|
||||||
|
{
|
||||||
|
const til::rle<unsigned short, unsigned short> def;
|
||||||
|
const til::rle<unsigned short, unsigned short, 3> bigger;
|
||||||
|
VERIFY_IS_GREATER_THAN(sizeof(bigger), sizeof(def));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Size)
|
||||||
|
{
|
||||||
|
const til::rle<unsigned short> rle(19, 12);
|
||||||
|
VERIFY_ARE_EQUAL(19, rle.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(AtPos)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(10, 10);
|
||||||
|
rle.insert(3, 0, 4);
|
||||||
|
rle.insert(7, 4, 2);
|
||||||
|
rle.insert(11, 6, 3);
|
||||||
|
rle.insert(4, 9, 1);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(1));
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(2));
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(3));
|
||||||
|
VERIFY_ARE_EQUAL(7, rle.at(4));
|
||||||
|
VERIFY_ARE_EQUAL(7, rle.at(5));
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(6));
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(7));
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(8));
|
||||||
|
VERIFY_ARE_EQUAL(4, rle.at(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(AtPosApplies)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(10, 10);
|
||||||
|
rle.insert(3, 0, 4);
|
||||||
|
rle.insert(7, 4, 2);
|
||||||
|
rle.insert(11, 6, 3);
|
||||||
|
rle.insert(4, 9, 1);
|
||||||
|
|
||||||
|
size_t appliesExpected = 4;
|
||||||
|
size_t applies = 0;
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(0, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(1, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(2, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(3, rle.at(3, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
appliesExpected = 2;
|
||||||
|
VERIFY_ARE_EQUAL(7, rle.at(4, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(7, rle.at(5, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
appliesExpected = 3;
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(6, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(7, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
--appliesExpected;
|
||||||
|
VERIFY_ARE_EQUAL(11, rle.at(8, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
appliesExpected = 1;
|
||||||
|
VERIFY_ARE_EQUAL(4, rle.at(9, applies));
|
||||||
|
VERIFY_ARE_EQUAL(appliesExpected, applies);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Substr)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(10, 10);
|
||||||
|
rle.insert(3, 0, 4);
|
||||||
|
rle.insert(7, 4, 2);
|
||||||
|
rle.insert(11, 6, 3);
|
||||||
|
rle.insert(4, 9, 1);
|
||||||
|
|
||||||
|
// 3 3 3 3 7 7 11 11 11 4
|
||||||
|
|
||||||
|
Log::Comment(L"1.) Nothing substring should match original.");
|
||||||
|
{
|
||||||
|
til::rle<int> expected(10, 10);
|
||||||
|
expected = rle;
|
||||||
|
// 3 3 3 3 7 7 11 11 11 4
|
||||||
|
|
||||||
|
const auto actual = rle.substr();
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::Comment(L"2.) Offset substring to implicit end.");
|
||||||
|
{
|
||||||
|
til::rle<int> expected(7, 10);
|
||||||
|
expected.insert(3, 0, 1);
|
||||||
|
expected.insert(7, 1, 2);
|
||||||
|
expected.insert(11, 3, 3);
|
||||||
|
expected.insert(4, 6, 1);
|
||||||
|
|
||||||
|
// 3 7 7 11 11 11 4
|
||||||
|
|
||||||
|
const auto actual = rle.substr(3);
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::Comment(L"3.) Substring cutting out middle bit.");
|
||||||
|
{
|
||||||
|
til::rle<int> expected(4, 4);
|
||||||
|
expected.insert(7, 0, 1);
|
||||||
|
expected.insert(11, 1, 3);
|
||||||
|
|
||||||
|
// 7 11 11 11
|
||||||
|
|
||||||
|
const auto actual = rle.substr(5, 4);
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Replace)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(20, 10);
|
||||||
|
actual.insert(3, 0, 4);
|
||||||
|
actual.insert(7, 4, 2);
|
||||||
|
actual.insert(11, 6, 3);
|
||||||
|
actual.insert(4, 9, 1);
|
||||||
|
actual.insert(7, 10, 5);
|
||||||
|
actual.insert(11, 15, 2);
|
||||||
|
actual.insert(9, 17, 3);
|
||||||
|
|
||||||
|
actual.replace(7, 49);
|
||||||
|
actual.replace(9, 81);
|
||||||
|
actual.replace(3, 9);
|
||||||
|
|
||||||
|
til::rle<int> expected(20, 10);
|
||||||
|
expected.insert(9, 0, 4);
|
||||||
|
expected.insert(49, 4, 2);
|
||||||
|
expected.insert(11, 6, 3);
|
||||||
|
expected.insert(4, 9, 1);
|
||||||
|
expected.insert(49, 10, 5);
|
||||||
|
expected.insert(11, 15, 2);
|
||||||
|
expected.insert(81, 17, 3);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ResizeShrink)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
actual.insert(3, 0, 4);
|
||||||
|
actual.insert(7, 4, 2);
|
||||||
|
actual.insert(11, 6, 3);
|
||||||
|
actual.insert(4, 9, 1);
|
||||||
|
|
||||||
|
// 3 3 3 3 7 7 11 11 11 4
|
||||||
|
// 3 for 4, 7 for 2, 11 for 3, 4 for 1.
|
||||||
|
|
||||||
|
til::rle<int> expected(7, 10);
|
||||||
|
expected.insert(3, 0, 4);
|
||||||
|
expected.insert(7, 4, 2);
|
||||||
|
expected.insert(11, 6, 1);
|
||||||
|
|
||||||
|
// 3 3 3 3 7 7 11
|
||||||
|
// 3 for 4, 7 for 2, 11 for 1
|
||||||
|
|
||||||
|
actual.resize(7);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ResizeGrow)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
actual.insert(3, 0, 4);
|
||||||
|
actual.insert(7, 4, 2);
|
||||||
|
actual.insert(11, 6, 3);
|
||||||
|
actual.insert(4, 9, 1);
|
||||||
|
|
||||||
|
// 3 3 3 3 7 7 11 11 11 4
|
||||||
|
// 3 for 4, 7 for 2, 11 for 3, 4 for 1.
|
||||||
|
|
||||||
|
til::rle<int> expected(13, 10);
|
||||||
|
expected.insert(3, 0, 4);
|
||||||
|
expected.insert(7, 4, 2);
|
||||||
|
expected.insert(11, 6, 3);
|
||||||
|
expected.insert(4, 9, 4);
|
||||||
|
|
||||||
|
// 3 3 3 3 7 7 11 11 11 4 4 4 4
|
||||||
|
// 3 for 4, 7 for 2, 11 for 3, 4 for 4.
|
||||||
|
|
||||||
|
actual.resize(13);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(FillAll)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
actual.insert(3, 0, 4);
|
||||||
|
actual.insert(7, 4, 2);
|
||||||
|
actual.insert(11, 6, 3);
|
||||||
|
actual.insert(4, 9, 1);
|
||||||
|
actual.fill(20);
|
||||||
|
|
||||||
|
til::rle<int> expected(10, 20);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(FillFrom)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
actual.insert(3, 0, 4);
|
||||||
|
actual.insert(7, 4, 2);
|
||||||
|
actual.insert(11, 6, 3);
|
||||||
|
actual.insert(4, 9, 1);
|
||||||
|
actual.fill(20, 2);
|
||||||
|
|
||||||
|
til::rle<int> expected(10, 20);
|
||||||
|
expected.insert(3, 0, 2);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Insert)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
actual.insert(4, 9); // insert single, implicit length
|
||||||
|
|
||||||
|
til::rle<int> expected(10, 4);
|
||||||
|
expected.insert(10, 0, 9); // insert multiple, say length
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Assign)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
|
||||||
|
// Prep initial buffer.
|
||||||
|
// 10 10 10 10 10 10 10 10 10 10
|
||||||
|
|
||||||
|
// Make something that can hold a span of pairs to assign in bulk.
|
||||||
|
std::vector<std::pair<int, size_t>> items;
|
||||||
|
items.push_back({ 400, 2 });
|
||||||
|
items.push_back({ 20, 3 });
|
||||||
|
|
||||||
|
// 400 400 20 20 20
|
||||||
|
|
||||||
|
// If we assign this to the front, we expect
|
||||||
|
// 400 400 20 20 20 10 10 10 10 10
|
||||||
|
til::rle<int> expected(10, 10);
|
||||||
|
expected.insert(400, 0, 2);
|
||||||
|
expected.insert(20, 2, 3);
|
||||||
|
|
||||||
|
actual.assign(items.cbegin(), items.cend());
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
|
||||||
|
// Now try assigning it again part way in.
|
||||||
|
// Our new expectation building on the last one if we assign at
|
||||||
|
// index 3 would be
|
||||||
|
// 400 400 20 400 400 20 20 20 10 10
|
||||||
|
expected.insert(400, 3, 2);
|
||||||
|
expected.insert(20, 5, 3);
|
||||||
|
|
||||||
|
actual.assign(items.cbegin(), items.cend(), 3);
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Equal)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 10);
|
||||||
|
til::rle<int> expected(10, 10);
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(NotEqualValue)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(10, 9);
|
||||||
|
til::rle<int> expected(10, 10);
|
||||||
|
|
||||||
|
VERIFY_ARE_NOT_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(NotEqualLength)
|
||||||
|
{
|
||||||
|
til::rle<int> actual(5, 10);
|
||||||
|
til::rle<int> expected(10, 10);
|
||||||
|
|
||||||
|
VERIFY_ARE_NOT_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(IteratorIncDecOnes)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(10, 1);
|
||||||
|
rle.insert(2, 0, 2);
|
||||||
|
rle.insert(3, 2, 3);
|
||||||
|
rle.insert(4, 5, 4);
|
||||||
|
|
||||||
|
// test array should be 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// or 2 for 2, 3 for 3, 4 for 4, 1 for 1.
|
||||||
|
|
||||||
|
Log::Comment(L"Increment by 1s.");
|
||||||
|
|
||||||
|
auto it = rle.begin();
|
||||||
|
for (auto i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(2, *it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(3, *it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(4, *it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 1; ++i)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(1, *it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(rle.end(), it);
|
||||||
|
|
||||||
|
Log::Comment(L"Decrement by 1s.");
|
||||||
|
|
||||||
|
for (auto i = 0; i < 1; ++i)
|
||||||
|
{
|
||||||
|
--it;
|
||||||
|
VERIFY_ARE_EQUAL(1, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
--it;
|
||||||
|
VERIFY_ARE_EQUAL(4, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
--it;
|
||||||
|
VERIFY_ARE_EQUAL(3, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
--it;
|
||||||
|
VERIFY_ARE_EQUAL(2, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(rle.begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestStruct
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
|
||||||
|
[[nodiscard]] bool operator==(const TestStruct& right) const noexcept
|
||||||
|
{
|
||||||
|
return a == right.a && b == right.b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorReference)
|
||||||
|
{
|
||||||
|
const TestStruct expected{ 3, 2 };
|
||||||
|
|
||||||
|
til::rle<TestStruct> rle(5, expected);
|
||||||
|
|
||||||
|
const TestStruct actual = *rle.cbegin();
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorPointer)
|
||||||
|
{
|
||||||
|
const TestStruct expected{ 3, 2 };
|
||||||
|
|
||||||
|
til::rle<TestStruct> rle(5, expected);
|
||||||
|
|
||||||
|
const auto it = rle.cbegin();
|
||||||
|
|
||||||
|
const TestStruct actual{ it->a, it->b };
|
||||||
|
VERIFY_ARE_EQUAL(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorIncPrefix)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 1, 1);
|
||||||
|
|
||||||
|
// 2 7 2 2 2
|
||||||
|
|
||||||
|
auto it = rle.cbegin();
|
||||||
|
++it;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorIncPostfix)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 1, 1);
|
||||||
|
|
||||||
|
// 2 7 2 2 2
|
||||||
|
|
||||||
|
auto it = rle.cbegin();
|
||||||
|
auto prevIt = it++;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
VERIFY_ARE_EQUAL(2, *prevIt);
|
||||||
|
VERIFY_ARE_NOT_EQUAL(it, prevIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorDecPrefix)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 4, 1);
|
||||||
|
|
||||||
|
// 2 2 2 2 7
|
||||||
|
|
||||||
|
auto it = rle.cend();
|
||||||
|
--it;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorDecPostfix)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 4, 1);
|
||||||
|
|
||||||
|
// 2 2 2 2 7
|
||||||
|
|
||||||
|
auto it = rle.cend();
|
||||||
|
auto prevIt = it--;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
VERIFY_ARE_EQUAL(rle.cend(), prevIt);
|
||||||
|
VERIFY_ARE_NOT_EQUAL(it, prevIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorPlusEquals)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 2, 1);
|
||||||
|
|
||||||
|
// 2 2 7 2 2
|
||||||
|
|
||||||
|
auto it = rle.cbegin();
|
||||||
|
it += 2;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorPlusOffset)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 2, 1);
|
||||||
|
|
||||||
|
// 2 2 7 2 2
|
||||||
|
|
||||||
|
auto it = rle.cbegin();
|
||||||
|
auto itAfter = it + 2;
|
||||||
|
VERIFY_ARE_EQUAL(7, *itAfter);
|
||||||
|
VERIFY_ARE_NOT_EQUAL(it, itAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorMinusEquals)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 3, 1);
|
||||||
|
|
||||||
|
// 2 2 2 7 2
|
||||||
|
|
||||||
|
auto it = rle.cend();
|
||||||
|
it -= 2;
|
||||||
|
VERIFY_ARE_EQUAL(7, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorMinusOffset)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 3, 1);
|
||||||
|
auto it = rle.cend();
|
||||||
|
auto itAfter = it - 2;
|
||||||
|
VERIFY_ARE_EQUAL(7, *itAfter);
|
||||||
|
VERIFY_ARE_NOT_EQUAL(it, itAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorDifference)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
const ptrdiff_t expected = 5;
|
||||||
|
VERIFY_ARE_EQUAL(expected, rle.cend() - rle.cbegin());
|
||||||
|
VERIFY_ARE_EQUAL(-expected, rle.cbegin() - rle.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorArrayOffset)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
rle.insert(7, 2, 1);
|
||||||
|
const auto it = rle.cbegin();
|
||||||
|
VERIFY_ARE_EQUAL(2, it[0]);
|
||||||
|
VERIFY_ARE_EQUAL(2, it[1]);
|
||||||
|
VERIFY_ARE_EQUAL(7, it[2]);
|
||||||
|
VERIFY_ARE_EQUAL(2, it[3]);
|
||||||
|
VERIFY_ARE_EQUAL(2, it[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorEquality)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
end -= 5;
|
||||||
|
VERIFY_IS_TRUE(begin == end);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorInequality)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
VERIFY_IS_TRUE(begin != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorLessThan)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
auto begin2 = end - 5;
|
||||||
|
VERIFY_IS_TRUE(begin < end);
|
||||||
|
VERIFY_IS_FALSE(end < begin);
|
||||||
|
VERIFY_IS_FALSE(begin < begin2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorGreaterThan)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
auto begin2 = end - 5;
|
||||||
|
VERIFY_IS_FALSE(begin > end);
|
||||||
|
VERIFY_IS_TRUE(end > begin);
|
||||||
|
VERIFY_IS_FALSE(begin > begin2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorLessThanEqual)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
auto begin2 = end - 5;
|
||||||
|
VERIFY_IS_TRUE(begin <= end);
|
||||||
|
VERIFY_IS_FALSE(end <= begin);
|
||||||
|
VERIFY_IS_TRUE(begin <= begin2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstIteratorGreaterThanEqual)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 2);
|
||||||
|
|
||||||
|
auto begin = rle.cbegin();
|
||||||
|
auto end = rle.cend();
|
||||||
|
auto begin2 = end - 5;
|
||||||
|
VERIFY_IS_FALSE(begin >= end);
|
||||||
|
VERIFY_IS_TRUE(end >= begin);
|
||||||
|
VERIFY_IS_TRUE(begin >= begin2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ConstReverseIterate)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(5, 5);
|
||||||
|
rle.insert(1, 0, 1);
|
||||||
|
rle.insert(2, 1, 1);
|
||||||
|
rle.insert(3, 2, 1);
|
||||||
|
rle.insert(4, 3, 1);
|
||||||
|
|
||||||
|
// 1 2 3 4 5
|
||||||
|
|
||||||
|
auto rit = rle.crbegin();
|
||||||
|
for (int i = 5; i > 0; i--)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(i, *rit);
|
||||||
|
rit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(rle.crend(), rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TEST_METHOD(NonConstIterators)
|
||||||
|
//{
|
||||||
|
// til::rle<int> rle(5, 5);
|
||||||
|
|
||||||
|
// auto iter = rle.begin();
|
||||||
|
// *iter++ = 1;
|
||||||
|
// *iter++ = 2;
|
||||||
|
// *iter++ = 3;
|
||||||
|
// *iter++ = 4;
|
||||||
|
|
||||||
|
// VERIFY_ARE_EQUAL(1, rle.at(0));
|
||||||
|
// VERIFY_ARE_EQUAL(2, rle.at(1));
|
||||||
|
// VERIFY_ARE_EQUAL(3, rle.at(2));
|
||||||
|
// VERIFY_ARE_EQUAL(4, rle.at(3));
|
||||||
|
// VERIFY_ARE_EQUAL(5, rle.at(4));
|
||||||
|
|
||||||
|
// VERIFY_ARE_EQUAL(rle.end(), iter);
|
||||||
|
|
||||||
|
// auto reverseIter = rle.crbegin();
|
||||||
|
// VERIFY_ARE_EQUAL(5, *reverseIter++);
|
||||||
|
// VERIFY_ARE_EQUAL(4, *reverseIter++);
|
||||||
|
// VERIFY_ARE_EQUAL(3, *reverseIter++);
|
||||||
|
// VERIFY_ARE_EQUAL(2, *reverseIter++);
|
||||||
|
// VERIFY_ARE_EQUAL(1, *reverseIter++);
|
||||||
|
|
||||||
|
// VERIFY_ARE_EQUAL(rle.crend(), reverseIter);
|
||||||
|
//}
|
||||||
|
|
||||||
|
TEST_METHOD(IteratorIncDecMultiple)
|
||||||
|
{
|
||||||
|
til::rle<int> rle(10, 1);
|
||||||
|
rle.insert(2, 0, 2);
|
||||||
|
rle.insert(3, 2, 3);
|
||||||
|
rle.insert(4, 5, 4);
|
||||||
|
|
||||||
|
// test array should be 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// or 2 for 2, 3 for 3, 4 for 4, 1 for 1.
|
||||||
|
|
||||||
|
auto it = rle.begin();
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(2, *it, L"Check we're sitting on the first of the first run.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^->
|
||||||
|
++it;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(2, *it, L"Move a spot into the run and ensure we're still on the same one.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^----->
|
||||||
|
it += 3;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(3, *it, L"Jump forward by 3 and we should still be on the second run of 3s.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^------->
|
||||||
|
it += 4;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(4, *it, L"Jump forward by 4 and we should still be on the third run of 4s.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^--->
|
||||||
|
it += 2;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(rle.end(), it, L"Jump past the last run of 1 for 1 to what should be the end.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// <-----^
|
||||||
|
it -= 3;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(4, *it, L"Jump back by 3 and we should be in the middle of the 4s run.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// <-------^
|
||||||
|
it -= 4;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(3, *it, L"Jump back by 4 and we should be in the middle of the 3s run.");
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// <-----^
|
||||||
|
it -= 3;
|
||||||
|
|
||||||
|
// 2 2 3 3 3 4 4 4 4 1
|
||||||
|
// ^
|
||||||
|
VERIFY_ARE_EQUAL(2, *it, L"Jump back by 3 and we should be at the beginning of the 2s run.");
|
||||||
|
VERIFY_ARE_EQUAL(rle.begin(), it, L"And it should equal 'begin'");
|
||||||
|
}
|
||||||
|
};
|
|
@ -21,6 +21,7 @@ SOURCES = \
|
||||||
PointTests.cpp \
|
PointTests.cpp \
|
||||||
MathTests.cpp \
|
MathTests.cpp \
|
||||||
RectangleTests.cpp \
|
RectangleTests.cpp \
|
||||||
|
RunLengthEncodingTests.cpp \
|
||||||
SizeTests.cpp \
|
SizeTests.cpp \
|
||||||
SomeTests.cpp \
|
SomeTests.cpp \
|
||||||
u8u16convertTests.cpp \
|
u8u16convertTests.cpp \
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<ClCompile Include="StaticMapTests.cpp" />
|
<ClCompile Include="StaticMapTests.cpp" />
|
||||||
<ClCompile Include="MathTests.cpp" />
|
<ClCompile Include="MathTests.cpp" />
|
||||||
<ClCompile Include="RectangleTests.cpp" />
|
<ClCompile Include="RectangleTests.cpp" />
|
||||||
|
<ClCompile Include="RunLengthEncodingTests.cpp" />
|
||||||
<ClCompile Include="SizeTests.cpp" />
|
<ClCompile Include="SizeTests.cpp" />
|
||||||
<ClCompile Include="ColorTests.cpp" />
|
<ClCompile Include="ColorTests.cpp" />
|
||||||
<ClCompile Include="CoalesceTests.cpp" />
|
<ClCompile Include="CoalesceTests.cpp" />
|
||||||
|
|
|
@ -97,4 +97,29 @@
|
||||||
<Type Name="til::color">
|
<Type Name="til::color">
|
||||||
<DisplayString>{{RGB: {(int)r,d}, {(int)g,d}, {(int)b,d}; α: {(int)a,d}}}</DisplayString>
|
<DisplayString>{{RGB: {(int)r,d}, {(int)g,d}, {(int)b,d}; α: {(int)a,d}}}</DisplayString>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="til::rle<*>">
|
||||||
|
<DisplayString>{{Size: {_size,d}}}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Name="[size]">_size</Item>
|
||||||
|
<ArrayItems>
|
||||||
|
<Size>_list.m_holder.m_size</Size>
|
||||||
|
<ValuePointer>_list.m_holder.m_start</ValuePointer>
|
||||||
|
</ArrayItems>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="til::details::rle_const_iterator<*>">
|
||||||
|
<DisplayString>{{ Run of {_it.m_ptr->first,d} for {_it.m_ptr->second,d} at {_usage,d}}}</DisplayString>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="boost::container::small_vector<*>">
|
||||||
|
<Expand>
|
||||||
|
<Item Name="[size]">m_holder.m_size</Item>
|
||||||
|
<ArrayItems>
|
||||||
|
<Size>m_holder.m_size</Size>
|
||||||
|
<ValuePointer>m_holder.m_start</ValuePointer>
|
||||||
|
</ArrayItems>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
||||||
|
|
Loading…
Reference in a new issue