mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-11 04:38:24 -06:00
Add support for more OSC color formats (#7578)
* Correct the behaviour of parsing `rgb:R/G/B`. It should be interpreted as `RR/GG/BB` instead of `0R/0G/0B` * Add support for `rgb:RRR/GGG/BBB` and `rgb:RRRR/GGGG/BBBB`. The behaviour of 12 bit variants is to repeat the first digit at the end, e.g. `rgb:123/456/789` becomes `rgb:1231/4564/7897`. * Add support for `#` formats. We are following the rules of [XParseColor] by interpreting `#RGB` as `R000G000B000`. * Add support for XOrg app color names, which are supported by xterm, VTE and many other terminal emulators. * Multi-parameter OSC 4 is now supported. * The chaining of OSC 10-12 is not yet supported. But the parameter validation is relaxed by parsing the parameters as multi-params but only use the first one, which means `\e]10;rgb:R/G/B;` and `\e]10:rgb:R/G/B;invalid` will execute `OSC 10` with the first color correctly. This fixes some of the issues mentioned in #942 but not all of them. [XParseColor]: https://linux.die.net/man/3/xparsecolor Closes #3715
This commit is contained in:
parent
f86045e041
commit
02b120236c
@ -18,3 +18,4 @@ it'll be accepted).
|
|||||||
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
||||||
| [Fonts](fonts.txt) | Font names |
|
| [Fonts](fonts.txt) | Font names |
|
||||||
| [Names](names.txt) | Names of people |
|
| [Names](names.txt) | Names of people |
|
||||||
|
| [Colors](colors.txt) | Names of color |
|
||||||
|
|||||||
@ -54,3 +54,4 @@ userenv
|
|||||||
wcstoui
|
wcstoui
|
||||||
XDocument
|
XDocument
|
||||||
XElement
|
XElement
|
||||||
|
XParse
|
||||||
|
|||||||
782
.github/actions/spell-check/dictionary/colors.txt
vendored
Normal file
782
.github/actions/spell-check/dictionary/colors.txt
vendored
Normal file
@ -0,0 +1,782 @@
|
|||||||
|
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
|
||||||
@ -961,6 +961,8 @@ hfile
|
|||||||
hfont
|
hfont
|
||||||
hglobal
|
hglobal
|
||||||
hh
|
hh
|
||||||
|
hhh
|
||||||
|
hhhh
|
||||||
hhook
|
hhook
|
||||||
hhx
|
hhx
|
||||||
HIBYTE
|
HIBYTE
|
||||||
@ -2793,6 +2795,9 @@ XCount
|
|||||||
xdy
|
xdy
|
||||||
xe
|
xe
|
||||||
XEncoding
|
XEncoding
|
||||||
|
xes
|
||||||
|
Xes
|
||||||
|
XES
|
||||||
xff
|
xff
|
||||||
XFile
|
XFile
|
||||||
xlang
|
xlang
|
||||||
@ -2802,6 +2807,8 @@ XMFLOAT
|
|||||||
xml
|
xml
|
||||||
xmlns
|
xmlns
|
||||||
xor
|
xor
|
||||||
|
xorg
|
||||||
|
XOrg
|
||||||
Xpath
|
Xpath
|
||||||
XPosition
|
XPosition
|
||||||
XResource
|
XResource
|
||||||
|
|||||||
@ -16,6 +16,7 @@ Scro\&ll
|
|||||||
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
|
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
|
||||||
(?:hostSm|mach)\.ProcessString\(L"[^"]+"
|
(?:hostSm|mach)\.ProcessString\(L"[^"]+"
|
||||||
\b([A-Za-z])\1{3,}\b
|
\b([A-Za-z])\1{3,}\b
|
||||||
|
0x[0-9A-Za-z]+
|
||||||
Base64::s_(?:En|De)code\(L"[^"]+"
|
Base64::s_(?:En|De)code\(L"[^"]+"
|
||||||
VERIFY_ARE_EQUAL\(L"[^"]+"
|
VERIFY_ARE_EQUAL\(L"[^"]+"
|
||||||
L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "../../inc/DefaultSettings.h"
|
#include "../../inc/DefaultSettings.h"
|
||||||
#include "../../inc/argb.h"
|
#include "../../inc/argb.h"
|
||||||
#include "../../types/inc/utils.hpp"
|
#include "../../types/inc/utils.hpp"
|
||||||
|
#include "../../types/inc/colorTable.hpp"
|
||||||
|
|
||||||
#include <winrt/Microsoft.Terminal.TerminalControl.h>
|
#include <winrt/Microsoft.Terminal.TerminalControl.h>
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "../TerminalSettingsModel/Profile.h"
|
#include "../TerminalSettingsModel/Profile.h"
|
||||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||||
#include "../LocalTests_SettingsModel/JsonTestClass.h"
|
#include "../LocalTests_SettingsModel/JsonTestClass.h"
|
||||||
|
#include "../types/inc/colorTable.hpp"
|
||||||
|
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
using namespace WEX::Logging;
|
using namespace WEX::Logging;
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
#include "..\interactivity\inc\ServiceLocator.hpp"
|
#include "..\interactivity\inc\ServiceLocator.hpp"
|
||||||
#include "../types/inc/utils.hpp"
|
#include "../types/inc/colorTable.hpp"
|
||||||
|
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
|
|
||||||
|
|||||||
@ -1566,13 +1566,13 @@ void ScreenBufferTests::VtSetColorTable()
|
|||||||
L"Process some valid sequences for setting the table"));
|
L"Process some valid sequences for setting the table"));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;0;rgb:1/1/1\x7");
|
stateMachine.ProcessString(L"\x1b]4;0;rgb:1/1/1\x7");
|
||||||
VERIFY_ARE_EQUAL(RGB(1, 1, 1), gci.GetColorTableEntry(::XtermToWindowsIndex(0)));
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(0)));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;1;rgb:1/23/1\x7");
|
stateMachine.ProcessString(L"\x1b]4;1;rgb:1/23/1\x7");
|
||||||
VERIFY_ARE_EQUAL(RGB(1, 0x23, 1), gci.GetColorTableEntry(::XtermToWindowsIndex(1)));
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x11), gci.GetColorTableEntry(::XtermToWindowsIndex(1)));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;2;rgb:1/23/12\x7");
|
stateMachine.ProcessString(L"\x1b]4;2;rgb:1/23/12\x7");
|
||||||
VERIFY_ARE_EQUAL(RGB(1, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(2)));
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(2)));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;3;rgb:12/23/12\x7");
|
stateMachine.ProcessString(L"\x1b]4;3;rgb:12/23/12\x7");
|
||||||
VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(3)));
|
VERIFY_ARE_EQUAL(RGB(0x12, 0x23, 0x12), gci.GetColorTableEntry(::XtermToWindowsIndex(3)));
|
||||||
@ -1587,7 +1587,7 @@ void ScreenBufferTests::VtSetColorTable()
|
|||||||
L"Try a bunch of invalid sequences."));
|
L"Try a bunch of invalid sequences."));
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"First start by setting an entry to a known value to compare to."));
|
L"First start by setting an entry to a known value to compare to."));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:9/9/9\x1b\\");
|
stateMachine.ProcessString(L"\x1b]4;5;rgb:09/09/09\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
|
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
@ -1595,11 +1595,6 @@ void ScreenBufferTests::VtSetColorTable()
|
|||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:/1/1\x1b\\");
|
stateMachine.ProcessString(L"\x1b]4;5;rgb:/1/1\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
|
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
|
||||||
L"invalid: too many characters in a component"));
|
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:111/1/1\x1b\\");
|
|
||||||
VERIFY_ARE_EQUAL(RGB(9, 9, 9), gci.GetColorTableEntry(::XtermToWindowsIndex(5)));
|
|
||||||
|
|
||||||
Log::Comment(NoThrowString().Format(
|
Log::Comment(NoThrowString().Format(
|
||||||
L"invalid: too many components"));
|
L"invalid: too many components"));
|
||||||
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/1/1/1\x1b\\");
|
stateMachine.ProcessString(L"\x1b]4;5;rgb:1/1/1/1\x1b\\");
|
||||||
@ -2845,17 +2840,8 @@ void ScreenBufferTests::SetDefaultForegroundColor()
|
|||||||
newColor = gci.GetDefaultForegroundColor();
|
newColor = gci.GetDefaultForegroundColor();
|
||||||
VERIFY_ARE_EQUAL(testColor, newColor);
|
VERIFY_ARE_EQUAL(testColor, newColor);
|
||||||
|
|
||||||
Log::Comment(L"Invalid Decimal Notation");
|
|
||||||
originalColor = newColor;
|
|
||||||
testColor = RGB(153, 102, 51);
|
|
||||||
stateMachine.ProcessString(L"\x1b]10;rgb:153/102/51\x1b\\");
|
|
||||||
|
|
||||||
newColor = gci.GetDefaultForegroundColor();
|
|
||||||
VERIFY_ARE_NOT_EQUAL(testColor, newColor);
|
|
||||||
// it will, in fact leave the color the way it was
|
|
||||||
VERIFY_ARE_EQUAL(originalColor, newColor);
|
|
||||||
|
|
||||||
Log::Comment(L"Invalid syntax");
|
Log::Comment(L"Invalid syntax");
|
||||||
|
originalColor = newColor;
|
||||||
testColor = RGB(153, 102, 51);
|
testColor = RGB(153, 102, 51);
|
||||||
stateMachine.ProcessString(L"\x1b]10;99/66/33\x1b\\");
|
stateMachine.ProcessString(L"\x1b]10;99/66/33\x1b\\");
|
||||||
|
|
||||||
@ -2899,17 +2885,8 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
|
|||||||
newColor = gci.GetDefaultBackgroundColor();
|
newColor = gci.GetDefaultBackgroundColor();
|
||||||
VERIFY_ARE_EQUAL(testColor, newColor);
|
VERIFY_ARE_EQUAL(testColor, newColor);
|
||||||
|
|
||||||
Log::Comment(L"Invalid Decimal Notation");
|
|
||||||
originalColor = newColor;
|
|
||||||
testColor = RGB(153, 102, 51);
|
|
||||||
stateMachine.ProcessString(L"\x1b]11;rgb:153/102/51\x1b\\");
|
|
||||||
|
|
||||||
newColor = gci.GetDefaultBackgroundColor();
|
|
||||||
VERIFY_ARE_NOT_EQUAL(testColor, newColor);
|
|
||||||
// it will, in fact leave the color the way it was
|
|
||||||
VERIFY_ARE_EQUAL(originalColor, newColor);
|
|
||||||
|
|
||||||
Log::Comment(L"Invalid Syntax");
|
Log::Comment(L"Invalid Syntax");
|
||||||
|
originalColor = newColor;
|
||||||
testColor = RGB(153, 102, 51);
|
testColor = RGB(153, 102, 51);
|
||||||
stateMachine.ProcessString(L"\x1b]11;99/66/33\x1b\\");
|
stateMachine.ProcessString(L"\x1b]11;99/66/33\x1b\\");
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@ namespace til
|
|||||||
{
|
{
|
||||||
#pragma warning(suppress : 26482) // Suppress bounds.2 check for indexing with constant expressions
|
#pragma warning(suppress : 26482) // Suppress bounds.2 check for indexing with constant expressions
|
||||||
#pragma warning(suppress : 26446) // Suppress bounds.4 check for subscript operator.
|
#pragma warning(suppress : 26446) // Suppress bounds.4 check for subscript operator.
|
||||||
|
#pragma warning(suppress : 26445) // Suppress lifetime check for a reference to gsl::span or std::string_view
|
||||||
return cont[i];
|
return cont[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
using const_iterator = typename std::array<std::pair<K, V>, N>::const_iterator;
|
using const_iterator = typename std::array<std::pair<K, V>, N>::const_iterator;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
constexpr explicit static_map(const Args&... args) :
|
constexpr explicit static_map(const Args&... args) noexcept :
|
||||||
_predicate{},
|
_predicate{},
|
||||||
_array{ { args... } }
|
_array{ { args... } }
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "base64.hpp"
|
#include "base64.hpp"
|
||||||
|
|
||||||
#include "ascii.hpp"
|
#include "ascii.hpp"
|
||||||
|
#include "../../types/inc/utils.hpp"
|
||||||
|
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
using namespace Microsoft::Console::VirtualTerminal;
|
using namespace Microsoft::Console::VirtualTerminal;
|
||||||
@ -734,8 +735,8 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
|||||||
std::wstring params;
|
std::wstring params;
|
||||||
std::wstring uri;
|
std::wstring uri;
|
||||||
bool queryClipboard = false;
|
bool queryClipboard = false;
|
||||||
size_t tableIndex = 0;
|
std::vector<size_t> tableIndexes;
|
||||||
DWORD color = 0;
|
std::vector<DWORD> colors;
|
||||||
|
|
||||||
switch (parameter)
|
switch (parameter)
|
||||||
{
|
{
|
||||||
@ -745,19 +746,17 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
|||||||
success = _GetOscTitle(string, title);
|
success = _GetOscTitle(string, title);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetColor:
|
case OscActionCodes::SetColor:
|
||||||
success = _GetOscSetColorTable(string, tableIndex, color);
|
success = _GetOscSetColorTable(string, tableIndexes, colors);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetForegroundColor:
|
case OscActionCodes::SetForegroundColor:
|
||||||
case OscActionCodes::SetBackgroundColor:
|
case OscActionCodes::SetBackgroundColor:
|
||||||
case OscActionCodes::SetCursorColor:
|
case OscActionCodes::SetCursorColor:
|
||||||
success = _GetOscSetColor(string, color);
|
success = _GetOscSetColor(string, colors);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetClipboard:
|
case OscActionCodes::SetClipboard:
|
||||||
success = _GetOscSetClipboard(string, setClipboardContent, queryClipboard);
|
success = _GetOscSetClipboard(string, setClipboardContent, queryClipboard);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::ResetCursorColor:
|
case OscActionCodes::ResetCursorColor:
|
||||||
// the console uses 0xffffffff as an "invalid color" value
|
|
||||||
color = 0xffffffff;
|
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::Hyperlink:
|
case OscActionCodes::Hyperlink:
|
||||||
@ -779,19 +778,33 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
|||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCWT);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCWT);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetColor:
|
case OscActionCodes::SetColor:
|
||||||
success = _dispatch->SetColorTableEntry(tableIndex, color);
|
for (size_t i = 0; i < tableIndexes.size(); i++)
|
||||||
|
{
|
||||||
|
const auto tableIndex = til::at(tableIndexes, i);
|
||||||
|
const auto rgb = til::at(colors, i);
|
||||||
|
success = _dispatch->SetColorTableEntry(tableIndex, rgb);
|
||||||
|
}
|
||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCCT);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCCT);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetForegroundColor:
|
case OscActionCodes::SetForegroundColor:
|
||||||
success = _dispatch->SetDefaultForeground(color);
|
if (colors.size() > 0)
|
||||||
|
{
|
||||||
|
success = _dispatch->SetDefaultForeground(til::at(colors, 0));
|
||||||
|
}
|
||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCFG);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCFG);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetBackgroundColor:
|
case OscActionCodes::SetBackgroundColor:
|
||||||
success = _dispatch->SetDefaultBackground(color);
|
if (colors.size() > 0)
|
||||||
|
{
|
||||||
|
success = _dispatch->SetDefaultBackground(til::at(colors, 0));
|
||||||
|
}
|
||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCBG);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCBG);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetCursorColor:
|
case OscActionCodes::SetCursorColor:
|
||||||
success = _dispatch->SetCursorColor(color);
|
if (colors.size() > 0)
|
||||||
|
{
|
||||||
|
success = _dispatch->SetCursorColor(til::at(colors, 0));
|
||||||
|
}
|
||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCC);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCC);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::SetClipboard:
|
case OscActionCodes::SetClipboard:
|
||||||
@ -802,7 +815,8 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
|||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCB);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCB);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::ResetCursorColor:
|
case OscActionCodes::ResetCursorColor:
|
||||||
success = _dispatch->SetCursorColor(color);
|
// the console uses 0xffffffff as an "invalid color" value
|
||||||
|
success = _dispatch->SetCursorColor(0xffffffff);
|
||||||
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCRCC);
|
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCRCC);
|
||||||
break;
|
break;
|
||||||
case OscActionCodes::Hyperlink:
|
case OscActionCodes::Hyperlink:
|
||||||
@ -1347,248 +1361,51 @@ bool OutputStateMachineEngine::DispatchIntermediatesFromEscape() const noexcept
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Converts a hex character to its equivalent integer value.
|
|
||||||
// Arguments:
|
|
||||||
// - wch - Character to convert.
|
|
||||||
// - value - receives the int value of the char
|
|
||||||
// Return Value:
|
|
||||||
// - true iff the character is a hex character.
|
|
||||||
bool OutputStateMachineEngine::s_HexToUint(const wchar_t wch,
|
|
||||||
unsigned int& value) noexcept
|
|
||||||
{
|
|
||||||
value = 0;
|
|
||||||
bool success = false;
|
|
||||||
if (wch >= L'0' && wch <= L'9')
|
|
||||||
{
|
|
||||||
value = wch - L'0';
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
else if (wch >= L'A' && wch <= L'F')
|
|
||||||
{
|
|
||||||
value = (wch - L'A') + 10;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
else if (wch >= L'a' && wch <= L'f')
|
|
||||||
{
|
|
||||||
value = (wch - L'a') + 10;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 26497) // We don't use any of these "constexprable" functions in that fashion
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Determines if a character is a valid number character, 0-9.
|
|
||||||
// Arguments:
|
|
||||||
// - wch - Character to check.
|
|
||||||
// Return Value:
|
|
||||||
// - True if it is. False if it isn't.
|
|
||||||
static constexpr bool _isNumber(const wchar_t wch) noexcept
|
|
||||||
{
|
|
||||||
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Determines if a character is a valid hex character, 0-9a-fA-F.
|
|
||||||
// Arguments:
|
|
||||||
// - wch - Character to check.
|
|
||||||
// Return Value:
|
|
||||||
// - True if it is. False if it isn't.
|
|
||||||
static constexpr bool _isHexNumber(const wchar_t wch) noexcept
|
|
||||||
{
|
|
||||||
return (wch >= L'0' && wch <= L'9') || // 0x30 - 0x39
|
|
||||||
(wch >= L'A' && wch <= L'F') ||
|
|
||||||
(wch >= L'a' && wch <= L'f');
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Given a color spec string, attempts to parse the color that's encoded.
|
|
||||||
// The only supported spec currently is the following:
|
|
||||||
// spec: a color in the following format:
|
|
||||||
// "rgb:<red>/<green>/<blue>"
|
|
||||||
// where <color> is one or two hex digits, upper or lower case.
|
|
||||||
// Arguments:
|
|
||||||
// - string - The string containing the color spec string to parse.
|
|
||||||
// - rgb - receives the color that we parsed
|
|
||||||
// Return Value:
|
|
||||||
// - True if a color was successfully parsed
|
|
||||||
bool OutputStateMachineEngine::s_ParseColorSpec(const std::wstring_view string,
|
|
||||||
DWORD& rgb) noexcept
|
|
||||||
{
|
|
||||||
bool foundRGB = false;
|
|
||||||
bool foundValidColorSpec = false;
|
|
||||||
std::array<unsigned int, 3> colorValues = { 0 };
|
|
||||||
bool success = false;
|
|
||||||
// We can have anywhere between [11,15] characters
|
|
||||||
// 9 "rgb:h/h/h"
|
|
||||||
// 12 "rgb:hh/hh/hh"
|
|
||||||
// Any fewer cannot be valid, and any more will be too many.
|
|
||||||
// Return early in this case.
|
|
||||||
// We'll still have to bounds check when parsing the hh/hh/hh values
|
|
||||||
if (string.size() < 9 || string.size() > 12)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we look for "rgb:"
|
|
||||||
// Other colorspaces are theoretically possible, but we don't support them.
|
|
||||||
|
|
||||||
auto curr = string.cbegin();
|
|
||||||
if ((*curr++ == L'r') &&
|
|
||||||
(*curr++ == L'g') &&
|
|
||||||
(*curr++ == L'b') &&
|
|
||||||
(*curr++ == L':'))
|
|
||||||
{
|
|
||||||
foundRGB = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundRGB)
|
|
||||||
{
|
|
||||||
// Colorspecs are up to hh/hh/hh, for 1-2 h's
|
|
||||||
for (size_t component = 0; component < 3; component++)
|
|
||||||
{
|
|
||||||
bool foundColor = false;
|
|
||||||
auto& value = til::at(colorValues, component);
|
|
||||||
for (size_t i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
const wchar_t wch = *curr++;
|
|
||||||
|
|
||||||
if (_isHexNumber(wch))
|
|
||||||
{
|
|
||||||
value *= 16;
|
|
||||||
unsigned int intVal = 0;
|
|
||||||
if (s_HexToUint(wch, intVal))
|
|
||||||
{
|
|
||||||
value += intVal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Encountered something weird oh no
|
|
||||||
foundColor = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// If we're on the blue component, we're not going to see a /.
|
|
||||||
// Break out once we hit the end.
|
|
||||||
if (component == 2 && curr >= string.cend())
|
|
||||||
{
|
|
||||||
foundValidColorSpec = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (wch == L'/')
|
|
||||||
{
|
|
||||||
// Break this component, and start the next one.
|
|
||||||
foundColor = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Encountered something weird oh no
|
|
||||||
foundColor = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!foundColor || curr >= string.cend())
|
|
||||||
{
|
|
||||||
// Indicates there was a some error parsing color
|
|
||||||
// or we're at the end of the string.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Only if we find a valid colorspec can we pass it out successfully.
|
|
||||||
if (foundValidColorSpec)
|
|
||||||
{
|
|
||||||
DWORD color = RGB(LOBYTE(colorValues.at(0)),
|
|
||||||
LOBYTE(colorValues.at(1)),
|
|
||||||
LOBYTE(colorValues.at(2)));
|
|
||||||
|
|
||||||
rgb = color;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - OSC 4 ; c ; spec ST
|
// - OSC 4 ; c ; spec ST
|
||||||
// c: the index of the ansi color table
|
// c: the index of the ansi color table
|
||||||
// spec: a color in the following format:
|
// spec: The colors are specified by name or RGB specification as per XParseColor
|
||||||
// "rgb:<red>/<green>/<blue>"
|
//
|
||||||
// where <color> is two hex digits
|
// It's possible to have multiple "c ; spec" pairs, which will set the index "c" of the color table
|
||||||
|
// with color parsed from "spec" for each pair respectively.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - string - the Osc String to parse
|
// - string - the Osc String to parse
|
||||||
// - tableIndex - receives the table index
|
// - tableIndexes - receives the table indexes
|
||||||
// - rgb - receives the color that we parsed in the format: 0x00BBGGRR
|
// - rgbs - receives the colors that we parsed in the format: 0x00BBGGRR
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - True if a table index and color was parsed successfully. False otherwise.
|
// - True if at least one table index and color was parsed successfully. False otherwise.
|
||||||
bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view string,
|
bool OutputStateMachineEngine::_GetOscSetColorTable(const std::wstring_view string,
|
||||||
size_t& tableIndex,
|
std::vector<size_t>& tableIndexes,
|
||||||
DWORD& rgb) const noexcept
|
std::vector<DWORD>& rgbs) const noexcept
|
||||||
|
try
|
||||||
{
|
{
|
||||||
tableIndex = 0;
|
const auto parts = Utils::SplitString(string, L';');
|
||||||
rgb = 0;
|
if (parts.size() < 2)
|
||||||
size_t _TableIndex = 0;
|
|
||||||
|
|
||||||
bool foundTableIndex = false;
|
|
||||||
bool success = false;
|
|
||||||
// We can have anywhere between [11,16] characters
|
|
||||||
// 11 "#;rgb:h/h/h"
|
|
||||||
// 16 "###;rgb:hh/hh/hh"
|
|
||||||
// Any fewer cannot be valid, and any more will be too many.
|
|
||||||
// Return early in this case.
|
|
||||||
// We'll still have to bounds check when parsing the hh/hh/hh values
|
|
||||||
if (string.size() < 11 || string.size() > 16)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First try to get the table index, a number between [0,256]
|
std::vector<size_t> newTableIndexes;
|
||||||
size_t current = 0;
|
std::vector<DWORD> newRgbs;
|
||||||
for (size_t i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
const wchar_t wch = string.at(current);
|
|
||||||
if (_isNumber(wch))
|
|
||||||
{
|
|
||||||
_TableIndex *= 10;
|
|
||||||
_TableIndex += wch - L'0';
|
|
||||||
|
|
||||||
++current;
|
for (size_t i = 0, j = 1; j < parts.size(); i += 2, j += 2)
|
||||||
}
|
|
||||||
else if (wch == L';' && i > 0)
|
|
||||||
{
|
|
||||||
// We need to explicitly pass in a number, we can't default to 0 if
|
|
||||||
// there's no param
|
|
||||||
++current;
|
|
||||||
foundTableIndex = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Found an unexpected character, fail.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Now we look for "rgb:"
|
|
||||||
// Other colorspaces are theoretically possible, but we don't support them.
|
|
||||||
if (foundTableIndex)
|
|
||||||
{
|
{
|
||||||
DWORD color = 0;
|
unsigned int tableIndex = 0;
|
||||||
success = s_ParseColorSpec(string.substr(current), color);
|
const bool indexSuccess = Utils::StringToUint(til::at(parts, i), tableIndex);
|
||||||
|
const auto colorOptional = Utils::ColorFromXTermColor(til::at(parts, j));
|
||||||
if (success)
|
if (indexSuccess && colorOptional.has_value())
|
||||||
{
|
{
|
||||||
tableIndex = _TableIndex;
|
newTableIndexes.push_back(tableIndex);
|
||||||
rgb = color;
|
newRgbs.push_back(colorOptional.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
tableIndexes.swap(newTableIndexes);
|
||||||
|
rgbs.swap(newRgbs);
|
||||||
|
|
||||||
|
return tableIndexes.size() > 0 && rgbs.size() > 0;
|
||||||
}
|
}
|
||||||
|
CATCH_LOG_RETURN_FALSE()
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Given a hyperlink string, attempts to parse the URI encoded. An 'id' parameter
|
// - Given a hyperlink string, attempts to parse the URI encoded. An 'id' parameter
|
||||||
@ -1630,31 +1447,51 @@ bool OutputStateMachineEngine::_ParseHyperlink(const std::wstring_view string,
|
|||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - OSC 10, 11, 12 ; spec ST
|
// - OSC 10, 11, 12 ; spec ST
|
||||||
// spec: a color in the following format:
|
// spec: The colors are specified by name or RGB specification as per XParseColor
|
||||||
// "rgb:<red>/<green>/<blue>"
|
//
|
||||||
// where <color> is two hex digits
|
// It's possible to have multiple "spec", which by design equals to a series of OSC command
|
||||||
|
// with accumulated Ps. For example "OSC 10;color1;color2" is effectively an "OSC 10;color1"
|
||||||
|
// and an "OSC 11;color2".
|
||||||
|
//
|
||||||
|
// However, we do not support the chaining of OSC 10-17 yet. Right now only the first parameter
|
||||||
|
// will take effect.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - string - the Osc String to parse
|
// - string - the Osc String to parse
|
||||||
// - rgb - receives the color that we parsed in the format: 0x00BBGGRR
|
// - rgbs - receives the colors that we parsed in the format: 0x00BBGGRR
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - True if a table index and color was parsed successfully. False otherwise.
|
// - True if the first table index and color was parsed successfully. False otherwise.
|
||||||
bool OutputStateMachineEngine::_GetOscSetColor(const std::wstring_view string,
|
bool OutputStateMachineEngine::_GetOscSetColor(const std::wstring_view string,
|
||||||
DWORD& rgb) const noexcept
|
std::vector<DWORD>& rgbs) const noexcept
|
||||||
|
try
|
||||||
{
|
{
|
||||||
rgb = 0;
|
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
DWORD color = 0;
|
const auto parts = Utils::SplitString(string, L';');
|
||||||
success = s_ParseColorSpec(string, color);
|
if (parts.size() < 1)
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
{
|
||||||
rgb = color;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<DWORD> newRgbs;
|
||||||
|
for (size_t i = 0; i < parts.size(); i++)
|
||||||
|
{
|
||||||
|
const auto colorOptional = Utils::ColorFromXTermColor(til::at(parts, i));
|
||||||
|
if (colorOptional.has_value())
|
||||||
|
{
|
||||||
|
newRgbs.push_back(colorOptional.value());
|
||||||
|
// Only mark the parsing as a success iff the first color is a success.
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rgbs.swap(newRgbs);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
CATCH_LOG_RETURN_FALSE()
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Retrieves the type of window manipulation operation from the parameter pool
|
// - Retrieves the type of window manipulation operation from the parameter pool
|
||||||
|
|||||||
@ -227,17 +227,12 @@ namespace Microsoft::Console::VirtualTerminal
|
|||||||
bool _GetWindowManipulationType(const gsl::span<const size_t> parameters,
|
bool _GetWindowManipulationType(const gsl::span<const size_t> parameters,
|
||||||
unsigned int& function) const noexcept;
|
unsigned int& function) const noexcept;
|
||||||
|
|
||||||
static bool s_HexToUint(const wchar_t wch,
|
|
||||||
unsigned int& value) noexcept;
|
|
||||||
bool _GetOscSetColorTable(const std::wstring_view string,
|
bool _GetOscSetColorTable(const std::wstring_view string,
|
||||||
size_t& tableIndex,
|
std::vector<size_t>& tableIndexes,
|
||||||
DWORD& rgb) const noexcept;
|
std::vector<DWORD>& rgbs) const noexcept;
|
||||||
|
|
||||||
static bool s_ParseColorSpec(const std::wstring_view string,
|
|
||||||
DWORD& rgb) noexcept;
|
|
||||||
|
|
||||||
bool _GetOscSetColor(const std::wstring_view string,
|
bool _GetOscSetColor(const std::wstring_view string,
|
||||||
DWORD& rgb) const noexcept;
|
std::vector<DWORD>& rgbs) const noexcept;
|
||||||
|
|
||||||
static constexpr DispatchTypes::CursorStyle DefaultCursorStyle = DispatchTypes::CursorStyle::UserDefault;
|
static constexpr DispatchTypes::CursorStyle DefaultCursorStyle = DispatchTypes::CursorStyle::UserDefault;
|
||||||
bool _GetCursorStyle(const gsl::span<const size_t> parameters,
|
bool _GetCursorStyle(const gsl::span<const size_t> parameters,
|
||||||
|
|||||||
@ -1008,8 +1008,14 @@ public:
|
|||||||
_isDECCOLMAllowed{ false },
|
_isDECCOLMAllowed{ false },
|
||||||
_windowWidth{ 80 },
|
_windowWidth{ 80 },
|
||||||
_win32InputMode{ false },
|
_win32InputMode{ false },
|
||||||
|
_setDefaultForeground(false),
|
||||||
|
_defaultForegroundColor{ RGB(0, 0, 0) },
|
||||||
|
_setDefaultBackground(false),
|
||||||
|
_defaultBackgroundColor{ RGB(0, 0, 0) },
|
||||||
_hyperlinkMode{ false },
|
_hyperlinkMode{ false },
|
||||||
_options{ s_cMaxOptions, static_cast<DispatchTypes::GraphicsOptions>(s_uiGraphicsCleared) } // fill with cleared option
|
_options{ s_cMaxOptions, static_cast<DispatchTypes::GraphicsOptions>(s_uiGraphicsCleared) }, // fill with cleared option
|
||||||
|
_colorTable{},
|
||||||
|
_setColorTableEntry{ false }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,6 +1361,27 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override
|
||||||
|
{
|
||||||
|
_setColorTableEntry = true;
|
||||||
|
_colorTable.at(tableIndex) = color;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetDefaultForeground(const DWORD color) noexcept override
|
||||||
|
{
|
||||||
|
_setDefaultForeground = true;
|
||||||
|
_defaultForegroundColor = color;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetDefaultBackground(const DWORD color) noexcept override
|
||||||
|
{
|
||||||
|
_setDefaultBackground = true;
|
||||||
|
_defaultBackgroundColor = color;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SetClipboard(std::wstring_view content) noexcept override
|
bool SetClipboard(std::wstring_view content) noexcept override
|
||||||
{
|
{
|
||||||
_copyContent = { content.begin(), content.end() };
|
_copyContent = { content.begin(), content.end() };
|
||||||
@ -1426,6 +1453,11 @@ public:
|
|||||||
bool _isDECCOLMAllowed;
|
bool _isDECCOLMAllowed;
|
||||||
size_t _windowWidth;
|
size_t _windowWidth;
|
||||||
bool _win32InputMode;
|
bool _win32InputMode;
|
||||||
|
bool _setDefaultForeground;
|
||||||
|
DWORD _defaultForegroundColor;
|
||||||
|
bool _setDefaultBackground;
|
||||||
|
DWORD _defaultBackgroundColor;
|
||||||
|
bool _setColorTableEntry;
|
||||||
bool _hyperlinkMode;
|
bool _hyperlinkMode;
|
||||||
std::wstring _copyContent;
|
std::wstring _copyContent;
|
||||||
std::wstring _uri;
|
std::wstring _uri;
|
||||||
@ -1433,7 +1465,9 @@ public:
|
|||||||
|
|
||||||
static const size_t s_cMaxOptions = 16;
|
static const size_t s_cMaxOptions = 16;
|
||||||
static const size_t s_uiGraphicsCleared = UINT_MAX;
|
static const size_t s_uiGraphicsCleared = UINT_MAX;
|
||||||
|
static const size_t XTERM_COLOR_TABLE_SIZE = 256;
|
||||||
std::vector<DispatchTypes::GraphicsOptions> _options;
|
std::vector<DispatchTypes::GraphicsOptions> _options;
|
||||||
|
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StateMachineExternalTest final
|
class StateMachineExternalTest final
|
||||||
@ -2608,6 +2642,324 @@ class StateMachineExternalTest final
|
|||||||
VERIFY_IS_TRUE(pDispatch->_vt52DeviceAttributes);
|
VERIFY_IS_TRUE(pDispatch->_vt52DeviceAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestOscSetDefaultForeground)
|
||||||
|
{
|
||||||
|
auto dispatch = std::make_unique<StatefulDispatch>();
|
||||||
|
auto pDispatch = dispatch.get();
|
||||||
|
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||||
|
StateMachine mach(std::move(engine));
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;rgb:12/34/56\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x12, 0x34, 0x56), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#123456\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x12, 0x34, 0x56), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;DarkOrange\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 140, 0), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Multiple params.
|
||||||
|
mach.ProcessString(L"\033]10;#111;rgb:2/2/2\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#111;DarkOrange\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Partially valid sequences. Only the first color works.
|
||||||
|
mach.ProcessString(L"\033]10;#111;\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#111;rgb:\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#111;#2\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultForeground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultForegroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid sequences.
|
||||||
|
mach.ProcessString(L"\033]10;rgb:1/1/\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultForeground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultForeground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid multi-param sequences.
|
||||||
|
mach.ProcessString(L"\033]10;;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultForeground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]10;#1;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultForeground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestOscSetDefaultBackground)
|
||||||
|
{
|
||||||
|
auto dispatch = std::make_unique<StatefulDispatch>();
|
||||||
|
auto pDispatch = dispatch.get();
|
||||||
|
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||||
|
StateMachine mach(std::move(engine));
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;rgb:12/34/56\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x12, 0x34, 0x56), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#123456\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x12, 0x34, 0x56), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;DarkOrange\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 140, 0), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Partially valid sequences. Only the first color works.
|
||||||
|
mach.ProcessString(L"\033]11;#111;\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#111;rgb:\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#111;#2\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setDefaultBackground);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_defaultBackgroundColor);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid sequences.
|
||||||
|
mach.ProcessString(L"\033]11;rgb:1/1/\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultBackground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultBackground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid multi-param sequences.
|
||||||
|
mach.ProcessString(L"\033]11;;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultBackground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]11;#1;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setDefaultBackground);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TestOscSetColorTableEntry)
|
||||||
|
{
|
||||||
|
auto dispatch = std::make_unique<StatefulDispatch>();
|
||||||
|
auto pDispatch = dispatch.get();
|
||||||
|
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||||
|
StateMachine mach(std::move(engine));
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;16;rgb:11/11/11\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(16));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;64;#111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(64));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;128;orange\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 165, 0), pDispatch->_colorTable.at(128));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid sequences.
|
||||||
|
mach.ProcessString(L"\033]4;\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;;\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;111\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;#111\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;1;111\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;1;rgb:\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Multiple params.
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1;16;rgb:2/2/2\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x22, 0x22, 0x22), pDispatch->_colorTable.at(16));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1;16;rgb:2/2/2;64;#111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x22, 0x22, 0x22), pDispatch->_colorTable.at(16));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(64));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1;16;rgb:2/2/2;64;#111;128;orange\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x22, 0x22, 0x22), pDispatch->_colorTable.at(16));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(64));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 165, 0), pDispatch->_colorTable.at(128));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Partially valid sequences. Valid colors should not be affected by invalid colors.
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:11;1;rgb:2/2/2;2;#111;3;orange;4;#111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x22, 0x22, 0x22), pDispatch->_colorTable.at(1));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(2));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 165, 0), pDispatch->_colorTable.at(3));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(4));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1;1;rgb:2/2/2;2;#111;3;orange;4;111\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x22, 0x22, 0x22), pDispatch->_colorTable.at(1));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(2));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 165, 0), pDispatch->_colorTable.at(3));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(4));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/1;1;rgb:2;2;#111;3;orange;4;#222\033\\");
|
||||||
|
VERIFY_IS_TRUE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x11, 0x11, 0x11), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(1));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x10, 0x10, 0x10), pDispatch->_colorTable.at(2));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(255, 165, 0), pDispatch->_colorTable.at(3));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0x20, 0x20, 0x20), pDispatch->_colorTable.at(4));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
// Invalid multi-param sequences
|
||||||
|
mach.ProcessString(L"\033]4;0;;1;;\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(1));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;;;;;1;;;;;\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(1));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
|
||||||
|
mach.ProcessString(L"\033]4;0;rgb:1/1/;16;rgb:2/2/;64;#11\033\\");
|
||||||
|
VERIFY_IS_FALSE(pDispatch->_setColorTableEntry);
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(16));
|
||||||
|
VERIFY_ARE_EQUAL(RGB(0, 0, 0), pDispatch->_colorTable.at(64));
|
||||||
|
|
||||||
|
pDispatch->ClearState();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_METHOD(TestSetClipboard)
|
TEST_METHOD(TestSetClipboard)
|
||||||
{
|
{
|
||||||
auto dispatch = std::make_unique<StatefulDispatch>();
|
auto dispatch = std::make_unique<StatefulDispatch>();
|
||||||
|
|||||||
1071
src/types/colorTable.cpp
Normal file
1071
src/types/colorTable.cpp
Normal file
File diff suppressed because it is too large
Load Diff
37
src/types/inc/colorTable.hpp
Normal file
37
src/types/inc/colorTable.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
- colorTable.hpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- Helper for color tables
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Microsoft::Console::Utils
|
||||||
|
{
|
||||||
|
void InitializeCampbellColorTable(const gsl::span<COLORREF> table);
|
||||||
|
void InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table);
|
||||||
|
void SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table);
|
||||||
|
void Initialize256ColorTable(const gsl::span<COLORREF> table);
|
||||||
|
|
||||||
|
std::optional<til::color> ColorFromXOrgAppColorName(const std::wstring_view wstr) noexcept;
|
||||||
|
|
||||||
|
// Function Description:
|
||||||
|
// - Fill the alpha byte of the colors in a given color table with the given value.
|
||||||
|
// Arguments:
|
||||||
|
// - table: a color table
|
||||||
|
// - newAlpha: the new value to use as the alpha for all the entries in that table.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
constexpr void SetColorTableAlpha(const gsl::span<COLORREF> table, const BYTE newAlpha) noexcept
|
||||||
|
{
|
||||||
|
const auto shiftedAlpha = newAlpha << 24;
|
||||||
|
for (auto& color : table)
|
||||||
|
{
|
||||||
|
WI_UpdateFlagsInMask(color, 0xff000000, shiftedAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,27 +45,12 @@ namespace Microsoft::Console::Utils
|
|||||||
|
|
||||||
std::string ColorToHexString(const til::color color);
|
std::string ColorToHexString(const til::color color);
|
||||||
til::color ColorFromHexString(const std::string_view wstr);
|
til::color ColorFromHexString(const std::string_view wstr);
|
||||||
|
std::optional<til::color> ColorFromXTermColor(const std::wstring_view wstr) noexcept;
|
||||||
|
std::optional<til::color> ColorFromXParseColorSpec(const std::wstring_view wstr) noexcept;
|
||||||
|
|
||||||
void InitializeCampbellColorTable(const gsl::span<COLORREF> table);
|
bool HexToUint(const wchar_t wch, unsigned int& value) noexcept;
|
||||||
void InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table);
|
bool StringToUint(const std::wstring_view wstr, unsigned int& value);
|
||||||
void SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table);
|
std::vector<std::wstring_view> SplitString(const std::wstring_view wstr, const wchar_t delimiter);
|
||||||
void Initialize256ColorTable(const gsl::span<COLORREF> table);
|
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - Fill the alpha byte of the colors in a given color table with the given value.
|
|
||||||
// Arguments:
|
|
||||||
// - table: a color table
|
|
||||||
// - newAlpha: the new value to use as the alpha for all the entries in that table.
|
|
||||||
// Return Value:
|
|
||||||
// - <none>
|
|
||||||
constexpr void SetColorTableAlpha(const gsl::span<COLORREF> table, const BYTE newAlpha) noexcept
|
|
||||||
{
|
|
||||||
const auto shiftedAlpha = newAlpha << 24;
|
|
||||||
for (auto& color : table)
|
|
||||||
{
|
|
||||||
WI_UpdateFlagsInMask(color, 0xff000000, shiftedAlpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint16_t EndianSwap(uint16_t value)
|
constexpr uint16_t EndianSwap(uint16_t value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\CodepointWidthDetector.cpp" />
|
<ClCompile Include="..\CodepointWidthDetector.cpp" />
|
||||||
<ClCompile Include="..\convert.cpp" />
|
<ClCompile Include="..\convert.cpp" />
|
||||||
|
<ClCompile Include="..\colorTable.cpp" />
|
||||||
<ClCompile Include="..\Environment.cpp" />
|
<ClCompile Include="..\Environment.cpp" />
|
||||||
<ClCompile Include="..\GlyphWidth.cpp" />
|
<ClCompile Include="..\GlyphWidth.cpp" />
|
||||||
<ClCompile Include="..\MouseEvent.cpp" />
|
<ClCompile Include="..\MouseEvent.cpp" />
|
||||||
@ -39,6 +40,7 @@
|
|||||||
<ClInclude Include="..\IControlAccessibilityInfo.h" />
|
<ClInclude Include="..\IControlAccessibilityInfo.h" />
|
||||||
<ClInclude Include="..\inc\CodepointWidthDetector.hpp" />
|
<ClInclude Include="..\inc\CodepointWidthDetector.hpp" />
|
||||||
<ClInclude Include="..\inc\convert.hpp" />
|
<ClInclude Include="..\inc\convert.hpp" />
|
||||||
|
<ClInclude Include="..\inc\colorTable.hpp" />
|
||||||
<ClInclude Include="..\inc\Environment.hpp" />
|
<ClInclude Include="..\inc\Environment.hpp" />
|
||||||
<ClInclude Include="..\inc\GlyphWidth.hpp" />
|
<ClInclude Include="..\inc\GlyphWidth.hpp" />
|
||||||
<ClInclude Include="..\inc\IInputEvent.hpp" />
|
<ClInclude Include="..\inc\IInputEvent.hpp" />
|
||||||
|
|||||||
@ -18,6 +18,9 @@
|
|||||||
<ClCompile Include="..\convert.cpp">
|
<ClCompile Include="..\convert.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\colorTable.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\MouseEvent.cpp">
|
<ClCompile Include="..\MouseEvent.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -89,6 +92,9 @@
|
|||||||
<ClInclude Include="..\inc\convert.hpp">
|
<ClInclude Include="..\inc\convert.hpp">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\colorTable.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\precomp.h">
|
<ClInclude Include="..\precomp.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@ -39,6 +39,7 @@ SOURCES= \
|
|||||||
..\Viewport.cpp \
|
..\Viewport.cpp \
|
||||||
..\WindowBufferSizeEvent.cpp \
|
..\WindowBufferSizeEvent.cpp \
|
||||||
..\convert.cpp \
|
..\convert.cpp \
|
||||||
|
..\colorTable.cpp \
|
||||||
..\Utf16Parser.cpp \
|
..\Utf16Parser.cpp \
|
||||||
..\utils.cpp \
|
..\utils.cpp \
|
||||||
..\ThemeUtils.cpp \
|
..\ThemeUtils.cpp \
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "..\..\inc\consoletaeftemplates.hpp"
|
#include "..\..\inc\consoletaeftemplates.hpp"
|
||||||
|
|
||||||
#include "..\inc\utils.hpp"
|
#include "..\inc\utils.hpp"
|
||||||
|
#include "..\inc\colorTable.hpp"
|
||||||
#include <conattrs.hpp>
|
#include <conattrs.hpp>
|
||||||
|
|
||||||
using namespace WEX::Common;
|
using namespace WEX::Common;
|
||||||
@ -21,6 +22,12 @@ class UtilsTests
|
|||||||
TEST_METHOD(TestClampToShortMax);
|
TEST_METHOD(TestClampToShortMax);
|
||||||
TEST_METHOD(TestSwapColorPalette);
|
TEST_METHOD(TestSwapColorPalette);
|
||||||
TEST_METHOD(TestGuidToString);
|
TEST_METHOD(TestGuidToString);
|
||||||
|
TEST_METHOD(TestSplitString);
|
||||||
|
TEST_METHOD(TestStringToUint);
|
||||||
|
TEST_METHOD(TestColorFromXTermColor);
|
||||||
|
|
||||||
|
void _VerifyXTermColorResult(const std::wstring_view wstr, DWORD colorValue);
|
||||||
|
void _VerifyXTermColorInvalid(const std::wstring_view wstr);
|
||||||
};
|
};
|
||||||
|
|
||||||
void UtilsTests::TestClampToShortMax()
|
void UtilsTests::TestClampToShortMax()
|
||||||
@ -89,3 +96,158 @@ void UtilsTests::TestGuidToString()
|
|||||||
VERIFY_ARE_EQUAL(constantGuidString.size(), generatedGuid.size());
|
VERIFY_ARE_EQUAL(constantGuidString.size(), generatedGuid.size());
|
||||||
VERIFY_ARE_EQUAL(constantGuidString, generatedGuid);
|
VERIFY_ARE_EQUAL(constantGuidString, generatedGuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UtilsTests::TestSplitString()
|
||||||
|
{
|
||||||
|
std::vector<std::wstring_view> result;
|
||||||
|
result = SplitString(L"", L';');
|
||||||
|
VERIFY_ARE_EQUAL(0u, result.size());
|
||||||
|
result = SplitString(L"1", L';');
|
||||||
|
VERIFY_ARE_EQUAL(1u, result.size());
|
||||||
|
result = SplitString(L"123", L';');
|
||||||
|
VERIFY_ARE_EQUAL(1u, result.size());
|
||||||
|
|
||||||
|
result = SplitString(L";123", L';');
|
||||||
|
VERIFY_ARE_EQUAL(2u, result.size());
|
||||||
|
VERIFY_ARE_EQUAL(L"", result.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(L"123", result.at(1));
|
||||||
|
|
||||||
|
result = SplitString(L"123;", L';');
|
||||||
|
VERIFY_ARE_EQUAL(2u, result.size());
|
||||||
|
VERIFY_ARE_EQUAL(L"123", result.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(L"", result.at(1));
|
||||||
|
|
||||||
|
result = SplitString(L"123;456", L';');
|
||||||
|
VERIFY_ARE_EQUAL(2u, result.size());
|
||||||
|
VERIFY_ARE_EQUAL(L"123", result.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(L"456", result.at(1));
|
||||||
|
|
||||||
|
result = SplitString(L"123;456;789", L';');
|
||||||
|
VERIFY_ARE_EQUAL(3u, result.size());
|
||||||
|
VERIFY_ARE_EQUAL(L"123", result.at(0));
|
||||||
|
VERIFY_ARE_EQUAL(L"456", result.at(1));
|
||||||
|
VERIFY_ARE_EQUAL(L"789", result.at(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UtilsTests::TestStringToUint()
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
unsigned int value = 0;
|
||||||
|
success = StringToUint(L"", value);
|
||||||
|
VERIFY_IS_FALSE(success);
|
||||||
|
success = StringToUint(L"xyz", value);
|
||||||
|
VERIFY_IS_FALSE(success);
|
||||||
|
success = StringToUint(L";", value);
|
||||||
|
VERIFY_IS_FALSE(success);
|
||||||
|
|
||||||
|
success = StringToUint(L"1", value);
|
||||||
|
VERIFY_IS_TRUE(success);
|
||||||
|
VERIFY_ARE_EQUAL(1u, value);
|
||||||
|
|
||||||
|
success = StringToUint(L"123", value);
|
||||||
|
VERIFY_IS_TRUE(success);
|
||||||
|
VERIFY_ARE_EQUAL(123u, value);
|
||||||
|
|
||||||
|
success = StringToUint(L"123456789", value);
|
||||||
|
VERIFY_IS_TRUE(success);
|
||||||
|
VERIFY_ARE_EQUAL(123456789u, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UtilsTests::TestColorFromXTermColor()
|
||||||
|
{
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/1/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rGb:1/1/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"RGB:1/1/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:111/1/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1111/1/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/11/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/111/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/1111/1", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/1/11", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/1/111", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/1/1111", RGB(0x11, 0x11, 0x11));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/23/4", RGB(0x11, 0x23, 0x44));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/23/45", RGB(0x11, 0x23, 0x45));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1/23/456", RGB(0x11, 0x23, 0x45));
|
||||||
|
_VerifyXTermColorResult(L"rgb:12/34/5", RGB(0x12, 0x34, 0x55));
|
||||||
|
_VerifyXTermColorResult(L"rgb:12/34/56", RGB(0x12, 0x34, 0x56));
|
||||||
|
_VerifyXTermColorResult(L"rgb:12/345/67", RGB(0x12, 0x34, 0x67));
|
||||||
|
_VerifyXTermColorResult(L"rgb:12/345/678", RGB(0x12, 0x34, 0x67));
|
||||||
|
_VerifyXTermColorResult(L"rgb:123/456/789", RGB(0x12, 0x45, 0x78));
|
||||||
|
_VerifyXTermColorResult(L"rgb:123/4564/789", RGB(0x12, 0x45, 0x78));
|
||||||
|
_VerifyXTermColorResult(L"rgb:123/4564/7897", RGB(0x12, 0x45, 0x78));
|
||||||
|
_VerifyXTermColorResult(L"rgb:1231/4564/7897", RGB(0x12, 0x45, 0x78));
|
||||||
|
|
||||||
|
_VerifyXTermColorResult(L"#111", RGB(0x10, 0x10, 0x10));
|
||||||
|
_VerifyXTermColorResult(L"#123456", RGB(0x12, 0x34, 0x56));
|
||||||
|
_VerifyXTermColorResult(L"#123456789", RGB(0x12, 0x45, 0x78));
|
||||||
|
_VerifyXTermColorResult(L"#123145647897", RGB(0x12, 0x45, 0x78));
|
||||||
|
|
||||||
|
_VerifyXTermColorResult(L"orange", RGB(255, 165, 0));
|
||||||
|
_VerifyXTermColorResult(L"dark green", RGB(0, 100, 0));
|
||||||
|
_VerifyXTermColorResult(L"medium sea green", RGB(60, 179, 113));
|
||||||
|
_VerifyXTermColorResult(L"LightYellow", RGB(255, 255, 224));
|
||||||
|
|
||||||
|
// Invalid sequences.
|
||||||
|
_VerifyXTermColorInvalid(L"");
|
||||||
|
_VerifyXTermColorInvalid(L"r:");
|
||||||
|
_VerifyXTermColorInvalid(L"rg:");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:/");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb://");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:///");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/1/");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/11/");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/1/1/");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:111111111");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:this/is/invalid");
|
||||||
|
_VerifyXTermColorInvalid(L"rgba:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgbi:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"cmyk:1/1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb#111");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:#111");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:rgb:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:rgb:#111");
|
||||||
|
_VerifyXTermColorInvalid(L"#");
|
||||||
|
_VerifyXTermColorInvalid(L"#1");
|
||||||
|
_VerifyXTermColorInvalid(L"#1111");
|
||||||
|
_VerifyXTermColorInvalid(L"#11111");
|
||||||
|
_VerifyXTermColorInvalid(L"#1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"#11/1/");
|
||||||
|
_VerifyXTermColorInvalid(L"#1111111");
|
||||||
|
_VerifyXTermColorInvalid(L"#/1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"#rgb:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"#111invalid");
|
||||||
|
_VerifyXTermColorInvalid(L"#invalid111");
|
||||||
|
_VerifyXTermColorInvalid(L"#1111111111111111");
|
||||||
|
_VerifyXTermColorInvalid(L"12/34/56");
|
||||||
|
_VerifyXTermColorInvalid(L"123456");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"中文rgb:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgb中文:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"这是一句中文");
|
||||||
|
_VerifyXTermColorInvalid(L"RGBİ1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgbİ1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgbİ:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgß:1/1/1");
|
||||||
|
_VerifyXTermColorInvalid(L"rgẞ:1/1/1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UtilsTests::_VerifyXTermColorResult(const std::wstring_view wstr, DWORD colorValue)
|
||||||
|
{
|
||||||
|
std::optional<til::color> color = ColorFromXTermColor(wstr);
|
||||||
|
VERIFY_IS_TRUE(color.has_value());
|
||||||
|
VERIFY_ARE_EQUAL(colorValue, (COLORREF)color.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UtilsTests::_VerifyXTermColorInvalid(const std::wstring_view wstr)
|
||||||
|
{
|
||||||
|
std::optional<til::color> color = ColorFromXTermColor(wstr);
|
||||||
|
VERIFY_IS_FALSE(color.has_value());
|
||||||
|
}
|
||||||
|
|||||||
@ -3,286 +3,20 @@
|
|||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "inc/utils.hpp"
|
#include "inc/utils.hpp"
|
||||||
|
#include "inc/colorTable.hpp"
|
||||||
|
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
|
|
||||||
static constexpr std::array<til::color, 16> campbellColorTable{
|
// Routine Description:
|
||||||
til::color{ 0x0C, 0x0C, 0x0C },
|
// - Determines if a character is a valid number character, 0-9.
|
||||||
til::color{ 0xC5, 0x0F, 0x1F },
|
// Arguments:
|
||||||
til::color{ 0x13, 0xA1, 0x0E },
|
// - wch - Character to check.
|
||||||
til::color{ 0xC1, 0x9C, 0x00 },
|
// Return Value:
|
||||||
til::color{ 0x00, 0x37, 0xDA },
|
// - True if it is. False if it isn't.
|
||||||
til::color{ 0x88, 0x17, 0x98 },
|
static constexpr bool _isNumber(const wchar_t wch) noexcept
|
||||||
til::color{ 0x3A, 0x96, 0xDD },
|
{
|
||||||
til::color{ 0xCC, 0xCC, 0xCC },
|
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
|
||||||
til::color{ 0x76, 0x76, 0x76 },
|
}
|
||||||
til::color{ 0xE7, 0x48, 0x56 },
|
|
||||||
til::color{ 0x16, 0xC6, 0x0C },
|
|
||||||
til::color{ 0xF9, 0xF1, 0xA5 },
|
|
||||||
til::color{ 0x3B, 0x78, 0xFF },
|
|
||||||
til::color{ 0xB4, 0x00, 0x9E },
|
|
||||||
til::color{ 0x61, 0xD6, 0xD6 },
|
|
||||||
til::color{ 0xF2, 0xF2, 0xF2 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr std::array<til::color, 256> standardXterm256ColorTable{
|
|
||||||
til::color{ 0x00, 0x00, 0x00 },
|
|
||||||
til::color{ 0x80, 0x00, 0x00 },
|
|
||||||
til::color{ 0x00, 0x80, 0x00 },
|
|
||||||
til::color{ 0x80, 0x80, 0x00 },
|
|
||||||
til::color{ 0x00, 0x00, 0x80 },
|
|
||||||
til::color{ 0x80, 0x00, 0x80 },
|
|
||||||
til::color{ 0x00, 0x80, 0x80 },
|
|
||||||
til::color{ 0xC0, 0xC0, 0xC0 },
|
|
||||||
til::color{ 0x80, 0x80, 0x80 },
|
|
||||||
til::color{ 0xFF, 0x00, 0x00 },
|
|
||||||
til::color{ 0x00, 0xFF, 0x00 },
|
|
||||||
til::color{ 0xFF, 0xFF, 0x00 },
|
|
||||||
til::color{ 0x00, 0x00, 0xFF },
|
|
||||||
til::color{ 0xFF, 0x00, 0xFF },
|
|
||||||
til::color{ 0x00, 0xFF, 0xFF },
|
|
||||||
til::color{ 0xFF, 0xFF, 0xFF },
|
|
||||||
til::color{ 0x00, 0x00, 0x00 },
|
|
||||||
til::color{ 0x00, 0x00, 0x5F },
|
|
||||||
til::color{ 0x00, 0x00, 0x87 },
|
|
||||||
til::color{ 0x00, 0x00, 0xAF },
|
|
||||||
til::color{ 0x00, 0x00, 0xD7 },
|
|
||||||
til::color{ 0x00, 0x00, 0xFF },
|
|
||||||
til::color{ 0x00, 0x5F, 0x00 },
|
|
||||||
til::color{ 0x00, 0x5F, 0x5F },
|
|
||||||
til::color{ 0x00, 0x5F, 0x87 },
|
|
||||||
til::color{ 0x00, 0x5F, 0xAF },
|
|
||||||
til::color{ 0x00, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0x00, 0x5F, 0xFF },
|
|
||||||
til::color{ 0x00, 0x87, 0x00 },
|
|
||||||
til::color{ 0x00, 0x87, 0x5F },
|
|
||||||
til::color{ 0x00, 0x87, 0x87 },
|
|
||||||
til::color{ 0x00, 0x87, 0xAF },
|
|
||||||
til::color{ 0x00, 0x87, 0xD7 },
|
|
||||||
til::color{ 0x00, 0x87, 0xFF },
|
|
||||||
til::color{ 0x00, 0xAF, 0x00 },
|
|
||||||
til::color{ 0x00, 0xAF, 0x5F },
|
|
||||||
til::color{ 0x00, 0xAF, 0x87 },
|
|
||||||
til::color{ 0x00, 0xAF, 0xAF },
|
|
||||||
til::color{ 0x00, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0x00, 0xAF, 0xFF },
|
|
||||||
til::color{ 0x00, 0xD7, 0x00 },
|
|
||||||
til::color{ 0x00, 0xD7, 0x5F },
|
|
||||||
til::color{ 0x00, 0xD7, 0x87 },
|
|
||||||
til::color{ 0x00, 0xD7, 0xAF },
|
|
||||||
til::color{ 0x00, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0x00, 0xD7, 0xFF },
|
|
||||||
til::color{ 0x00, 0xFF, 0x00 },
|
|
||||||
til::color{ 0x00, 0xFF, 0x5F },
|
|
||||||
til::color{ 0x00, 0xFF, 0x87 },
|
|
||||||
til::color{ 0x00, 0xFF, 0xAF },
|
|
||||||
til::color{ 0x00, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0x00, 0xFF, 0xFF },
|
|
||||||
til::color{ 0x5F, 0x00, 0x00 },
|
|
||||||
til::color{ 0x5F, 0x00, 0x5F },
|
|
||||||
til::color{ 0x5F, 0x00, 0x87 },
|
|
||||||
til::color{ 0x5F, 0x00, 0xAF },
|
|
||||||
til::color{ 0x5F, 0x00, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0x00, 0xFF },
|
|
||||||
til::color{ 0x5F, 0x5F, 0x00 },
|
|
||||||
til::color{ 0x5F, 0x5F, 0x5F },
|
|
||||||
til::color{ 0x5F, 0x5F, 0x87 },
|
|
||||||
til::color{ 0x5F, 0x5F, 0xAF },
|
|
||||||
til::color{ 0x5F, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0x5F, 0xFF },
|
|
||||||
til::color{ 0x5F, 0x87, 0x00 },
|
|
||||||
til::color{ 0x5F, 0x87, 0x5F },
|
|
||||||
til::color{ 0x5F, 0x87, 0x87 },
|
|
||||||
til::color{ 0x5F, 0x87, 0xAF },
|
|
||||||
til::color{ 0x5F, 0x87, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0x87, 0xFF },
|
|
||||||
til::color{ 0x5F, 0xAF, 0x00 },
|
|
||||||
til::color{ 0x5F, 0xAF, 0x5F },
|
|
||||||
til::color{ 0x5F, 0xAF, 0x87 },
|
|
||||||
til::color{ 0x5F, 0xAF, 0xAF },
|
|
||||||
til::color{ 0x5F, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0xAF, 0xFF },
|
|
||||||
til::color{ 0x5F, 0xD7, 0x00 },
|
|
||||||
til::color{ 0x5F, 0xD7, 0x5F },
|
|
||||||
til::color{ 0x5F, 0xD7, 0x87 },
|
|
||||||
til::color{ 0x5F, 0xD7, 0xAF },
|
|
||||||
til::color{ 0x5F, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0xD7, 0xFF },
|
|
||||||
til::color{ 0x5F, 0xFF, 0x00 },
|
|
||||||
til::color{ 0x5F, 0xFF, 0x5F },
|
|
||||||
til::color{ 0x5F, 0xFF, 0x87 },
|
|
||||||
til::color{ 0x5F, 0xFF, 0xAF },
|
|
||||||
til::color{ 0x5F, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0x5F, 0xFF, 0xFF },
|
|
||||||
til::color{ 0x87, 0x00, 0x00 },
|
|
||||||
til::color{ 0x87, 0x00, 0x5F },
|
|
||||||
til::color{ 0x87, 0x00, 0x87 },
|
|
||||||
til::color{ 0x87, 0x00, 0xAF },
|
|
||||||
til::color{ 0x87, 0x00, 0xD7 },
|
|
||||||
til::color{ 0x87, 0x00, 0xFF },
|
|
||||||
til::color{ 0x87, 0x5F, 0x00 },
|
|
||||||
til::color{ 0x87, 0x5F, 0x5F },
|
|
||||||
til::color{ 0x87, 0x5F, 0x87 },
|
|
||||||
til::color{ 0x87, 0x5F, 0xAF },
|
|
||||||
til::color{ 0x87, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0x87, 0x5F, 0xFF },
|
|
||||||
til::color{ 0x87, 0x87, 0x00 },
|
|
||||||
til::color{ 0x87, 0x87, 0x5F },
|
|
||||||
til::color{ 0x87, 0x87, 0x87 },
|
|
||||||
til::color{ 0x87, 0x87, 0xAF },
|
|
||||||
til::color{ 0x87, 0x87, 0xD7 },
|
|
||||||
til::color{ 0x87, 0x87, 0xFF },
|
|
||||||
til::color{ 0x87, 0xAF, 0x00 },
|
|
||||||
til::color{ 0x87, 0xAF, 0x5F },
|
|
||||||
til::color{ 0x87, 0xAF, 0x87 },
|
|
||||||
til::color{ 0x87, 0xAF, 0xAF },
|
|
||||||
til::color{ 0x87, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0x87, 0xAF, 0xFF },
|
|
||||||
til::color{ 0x87, 0xD7, 0x00 },
|
|
||||||
til::color{ 0x87, 0xD7, 0x5F },
|
|
||||||
til::color{ 0x87, 0xD7, 0x87 },
|
|
||||||
til::color{ 0x87, 0xD7, 0xAF },
|
|
||||||
til::color{ 0x87, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0x87, 0xD7, 0xFF },
|
|
||||||
til::color{ 0x87, 0xFF, 0x00 },
|
|
||||||
til::color{ 0x87, 0xFF, 0x5F },
|
|
||||||
til::color{ 0x87, 0xFF, 0x87 },
|
|
||||||
til::color{ 0x87, 0xFF, 0xAF },
|
|
||||||
til::color{ 0x87, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0x87, 0xFF, 0xFF },
|
|
||||||
til::color{ 0xAF, 0x00, 0x00 },
|
|
||||||
til::color{ 0xAF, 0x00, 0x5F },
|
|
||||||
til::color{ 0xAF, 0x00, 0x87 },
|
|
||||||
til::color{ 0xAF, 0x00, 0xAF },
|
|
||||||
til::color{ 0xAF, 0x00, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0x00, 0xFF },
|
|
||||||
til::color{ 0xAF, 0x5F, 0x00 },
|
|
||||||
til::color{ 0xAF, 0x5F, 0x5F },
|
|
||||||
til::color{ 0xAF, 0x5F, 0x87 },
|
|
||||||
til::color{ 0xAF, 0x5F, 0xAF },
|
|
||||||
til::color{ 0xAF, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0x5F, 0xFF },
|
|
||||||
til::color{ 0xAF, 0x87, 0x00 },
|
|
||||||
til::color{ 0xAF, 0x87, 0x5F },
|
|
||||||
til::color{ 0xAF, 0x87, 0x87 },
|
|
||||||
til::color{ 0xAF, 0x87, 0xAF },
|
|
||||||
til::color{ 0xAF, 0x87, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0x87, 0xFF },
|
|
||||||
til::color{ 0xAF, 0xAF, 0x00 },
|
|
||||||
til::color{ 0xAF, 0xAF, 0x5F },
|
|
||||||
til::color{ 0xAF, 0xAF, 0x87 },
|
|
||||||
til::color{ 0xAF, 0xAF, 0xAF },
|
|
||||||
til::color{ 0xAF, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0xAF, 0xFF },
|
|
||||||
til::color{ 0xAF, 0xD7, 0x00 },
|
|
||||||
til::color{ 0xAF, 0xD7, 0x5F },
|
|
||||||
til::color{ 0xAF, 0xD7, 0x87 },
|
|
||||||
til::color{ 0xAF, 0xD7, 0xAF },
|
|
||||||
til::color{ 0xAF, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0xD7, 0xFF },
|
|
||||||
til::color{ 0xAF, 0xFF, 0x00 },
|
|
||||||
til::color{ 0xAF, 0xFF, 0x5F },
|
|
||||||
til::color{ 0xAF, 0xFF, 0x87 },
|
|
||||||
til::color{ 0xAF, 0xFF, 0xAF },
|
|
||||||
til::color{ 0xAF, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0xAF, 0xFF, 0xFF },
|
|
||||||
til::color{ 0xD7, 0x00, 0x00 },
|
|
||||||
til::color{ 0xD7, 0x00, 0x5F },
|
|
||||||
til::color{ 0xD7, 0x00, 0x87 },
|
|
||||||
til::color{ 0xD7, 0x00, 0xAF },
|
|
||||||
til::color{ 0xD7, 0x00, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0x00, 0xFF },
|
|
||||||
til::color{ 0xD7, 0x5F, 0x00 },
|
|
||||||
til::color{ 0xD7, 0x5F, 0x5F },
|
|
||||||
til::color{ 0xD7, 0x5F, 0x87 },
|
|
||||||
til::color{ 0xD7, 0x5F, 0xAF },
|
|
||||||
til::color{ 0xD7, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0x5F, 0xFF },
|
|
||||||
til::color{ 0xD7, 0x87, 0x00 },
|
|
||||||
til::color{ 0xD7, 0x87, 0x5F },
|
|
||||||
til::color{ 0xD7, 0x87, 0x87 },
|
|
||||||
til::color{ 0xD7, 0x87, 0xAF },
|
|
||||||
til::color{ 0xD7, 0x87, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0x87, 0xFF },
|
|
||||||
til::color{ 0xD7, 0xAF, 0x00 },
|
|
||||||
til::color{ 0xD7, 0xAF, 0x5F },
|
|
||||||
til::color{ 0xD7, 0xAF, 0x87 },
|
|
||||||
til::color{ 0xD7, 0xAF, 0xAF },
|
|
||||||
til::color{ 0xD7, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0xAF, 0xFF },
|
|
||||||
til::color{ 0xD7, 0xD7, 0x00 },
|
|
||||||
til::color{ 0xD7, 0xD7, 0x5F },
|
|
||||||
til::color{ 0xD7, 0xD7, 0x87 },
|
|
||||||
til::color{ 0xD7, 0xD7, 0xAF },
|
|
||||||
til::color{ 0xD7, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0xD7, 0xFF },
|
|
||||||
til::color{ 0xD7, 0xFF, 0x00 },
|
|
||||||
til::color{ 0xD7, 0xFF, 0x5F },
|
|
||||||
til::color{ 0xD7, 0xFF, 0x87 },
|
|
||||||
til::color{ 0xD7, 0xFF, 0xAF },
|
|
||||||
til::color{ 0xD7, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0xD7, 0xFF, 0xFF },
|
|
||||||
til::color{ 0xFF, 0x00, 0x00 },
|
|
||||||
til::color{ 0xFF, 0x00, 0x5F },
|
|
||||||
til::color{ 0xFF, 0x00, 0x87 },
|
|
||||||
til::color{ 0xFF, 0x00, 0xAF },
|
|
||||||
til::color{ 0xFF, 0x00, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0x00, 0xFF },
|
|
||||||
til::color{ 0xFF, 0x5F, 0x00 },
|
|
||||||
til::color{ 0xFF, 0x5F, 0x5F },
|
|
||||||
til::color{ 0xFF, 0x5F, 0x87 },
|
|
||||||
til::color{ 0xFF, 0x5F, 0xAF },
|
|
||||||
til::color{ 0xFF, 0x5F, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0x5F, 0xFF },
|
|
||||||
til::color{ 0xFF, 0x87, 0x00 },
|
|
||||||
til::color{ 0xFF, 0x87, 0x5F },
|
|
||||||
til::color{ 0xFF, 0x87, 0x87 },
|
|
||||||
til::color{ 0xFF, 0x87, 0xAF },
|
|
||||||
til::color{ 0xFF, 0x87, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0x87, 0xFF },
|
|
||||||
til::color{ 0xFF, 0xAF, 0x00 },
|
|
||||||
til::color{ 0xFF, 0xAF, 0x5F },
|
|
||||||
til::color{ 0xFF, 0xAF, 0x87 },
|
|
||||||
til::color{ 0xFF, 0xAF, 0xAF },
|
|
||||||
til::color{ 0xFF, 0xAF, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0xAF, 0xFF },
|
|
||||||
til::color{ 0xFF, 0xD7, 0x00 },
|
|
||||||
til::color{ 0xFF, 0xD7, 0x5F },
|
|
||||||
til::color{ 0xFF, 0xD7, 0x87 },
|
|
||||||
til::color{ 0xFF, 0xD7, 0xAF },
|
|
||||||
til::color{ 0xFF, 0xD7, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0xD7, 0xFF },
|
|
||||||
til::color{ 0xFF, 0xFF, 0x00 },
|
|
||||||
til::color{ 0xFF, 0xFF, 0x5F },
|
|
||||||
til::color{ 0xFF, 0xFF, 0x87 },
|
|
||||||
til::color{ 0xFF, 0xFF, 0xAF },
|
|
||||||
til::color{ 0xFF, 0xFF, 0xD7 },
|
|
||||||
til::color{ 0xFF, 0xFF, 0xFF },
|
|
||||||
til::color{ 0x08, 0x08, 0x08 },
|
|
||||||
til::color{ 0x12, 0x12, 0x12 },
|
|
||||||
til::color{ 0x1C, 0x1C, 0x1C },
|
|
||||||
til::color{ 0x26, 0x26, 0x26 },
|
|
||||||
til::color{ 0x30, 0x30, 0x30 },
|
|
||||||
til::color{ 0x3A, 0x3A, 0x3A },
|
|
||||||
til::color{ 0x44, 0x44, 0x44 },
|
|
||||||
til::color{ 0x4E, 0x4E, 0x4E },
|
|
||||||
til::color{ 0x58, 0x58, 0x58 },
|
|
||||||
til::color{ 0x62, 0x62, 0x62 },
|
|
||||||
til::color{ 0x6C, 0x6C, 0x6C },
|
|
||||||
til::color{ 0x76, 0x76, 0x76 },
|
|
||||||
til::color{ 0x80, 0x80, 0x80 },
|
|
||||||
til::color{ 0x8A, 0x8A, 0x8A },
|
|
||||||
til::color{ 0x94, 0x94, 0x94 },
|
|
||||||
til::color{ 0x9E, 0x9E, 0x9E },
|
|
||||||
til::color{ 0xA8, 0xA8, 0xA8 },
|
|
||||||
til::color{ 0xB2, 0xB2, 0xB2 },
|
|
||||||
til::color{ 0xBC, 0xBC, 0xBC },
|
|
||||||
til::color{ 0xC6, 0xC6, 0xC6 },
|
|
||||||
til::color{ 0xD0, 0xD0, 0xD0 },
|
|
||||||
til::color{ 0xDA, 0xDA, 0xDA },
|
|
||||||
til::color{ 0xE4, 0xE4, 0xE4 },
|
|
||||||
til::color{ 0xEE, 0xEE, 0xEE },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - Creates a String representation of a guid, in the format
|
// - Creates a String representation of a guid, in the format
|
||||||
@ -377,6 +111,317 @@ til::color Utils::ColorFromHexString(const std::string_view str)
|
|||||||
return til::color{ r, g, b };
|
return til::color{ r, g, b };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Given a color string, attempts to parse the color.
|
||||||
|
// The color are specified by name or RGB specification as per XParseColor.
|
||||||
|
// Arguments:
|
||||||
|
// - string - The string containing the color spec string to parse.
|
||||||
|
// Return Value:
|
||||||
|
// - An optional color which contains value if a color was successfully parsed
|
||||||
|
std::optional<til::color> Utils::ColorFromXTermColor(const std::wstring_view string) noexcept
|
||||||
|
{
|
||||||
|
auto color = ColorFromXParseColorSpec(string);
|
||||||
|
if (!color.has_value())
|
||||||
|
{
|
||||||
|
// Try again, but use the app color name parser
|
||||||
|
color = ColorFromXOrgAppColorName(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Given a color spec string, attempts to parse the color that's encoded.
|
||||||
|
//
|
||||||
|
// Based on the XParseColor documentation, the supported specs currently are the following:
|
||||||
|
// spec1: a color in the following format:
|
||||||
|
// "rgb:<red>/<green>/<blue>"
|
||||||
|
// spec2: a color in the following format:
|
||||||
|
// "#<red><green><blue>"
|
||||||
|
//
|
||||||
|
// In both specs, <color> is a value contains up to 4 hex digits, upper or lower case.
|
||||||
|
// Arguments:
|
||||||
|
// - string - The string containing the color spec string to parse.
|
||||||
|
// Return Value:
|
||||||
|
// - An optional color which contains value if a color was successfully parsed
|
||||||
|
std::optional<til::color> Utils::ColorFromXParseColorSpec(const std::wstring_view string) noexcept
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool foundXParseColorSpec = false;
|
||||||
|
bool foundValidColorSpec = false;
|
||||||
|
|
||||||
|
bool isSharpSignFormat = false;
|
||||||
|
size_t rgbHexDigitCount = 0;
|
||||||
|
std::array<unsigned int, 3> colorValues = { 0 };
|
||||||
|
std::array<unsigned int, 3> parameterValues = { 0 };
|
||||||
|
const auto stringSize = string.size();
|
||||||
|
|
||||||
|
// First we look for "rgb:"
|
||||||
|
// Other colorspaces are theoretically possible, but we don't support them.
|
||||||
|
auto curr = string.cbegin();
|
||||||
|
if (stringSize > 4)
|
||||||
|
{
|
||||||
|
auto prefix = std::wstring(string.substr(0, 4));
|
||||||
|
|
||||||
|
// The "rgb:" indicator should be case insensitive. To prevent possible issues under
|
||||||
|
// different locales, transform only ASCII range latin characters.
|
||||||
|
std::transform(prefix.begin(), prefix.end(), prefix.begin(), [](const auto x) {
|
||||||
|
return x >= L'A' && x <= L'Z' ? static_cast<wchar_t>(std::towlower(x)) : x;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prefix.compare(L"rgb:") == 0)
|
||||||
|
{
|
||||||
|
// If all the components have the same digit count, we can have one of the following formats:
|
||||||
|
// 9 "rgb:h/h/h"
|
||||||
|
// 12 "rgb:hh/hh/hh"
|
||||||
|
// 15 "rgb:hhh/hhh/hhh"
|
||||||
|
// 18 "rgb:hhhh/hhhh/hhhh"
|
||||||
|
// Note that the component sizes aren't required to be the same.
|
||||||
|
// Anything in between is also valid, e.g. "rgb:h/hh/h" and "rgb:h/hh/hhh".
|
||||||
|
// Any fewer cannot be valid, and any more will be too many. Return early in this case.
|
||||||
|
if (stringSize < 9 || stringSize > 18)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
foundXParseColorSpec = true;
|
||||||
|
|
||||||
|
std::advance(curr, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try the sharp sign format.
|
||||||
|
if (!foundXParseColorSpec && stringSize > 1)
|
||||||
|
{
|
||||||
|
if (til::at(string, 0) == L'#')
|
||||||
|
{
|
||||||
|
// We can have one of the following formats:
|
||||||
|
// 4 "#hhh"
|
||||||
|
// 7 "#hhhhhh"
|
||||||
|
// 10 "#hhhhhhhhh"
|
||||||
|
// 13 "#hhhhhhhhhhhh"
|
||||||
|
// Any other cases will be invalid. Return early in this case.
|
||||||
|
if (!(stringSize == 4 || stringSize == 7 || stringSize == 10 || stringSize == 13))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSharpSignFormat = true;
|
||||||
|
foundXParseColorSpec = true;
|
||||||
|
rgbHexDigitCount = (stringSize - 1) / 3;
|
||||||
|
|
||||||
|
std::advance(curr, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No valid spec is found. Return early.
|
||||||
|
if (!foundXParseColorSpec)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse the actual color value of each component.
|
||||||
|
for (size_t component = 0; component < 3; component++)
|
||||||
|
{
|
||||||
|
bool foundColor = false;
|
||||||
|
auto& parameterValue = til::at(parameterValues, component);
|
||||||
|
// For "sharp sign" format, the rgbHexDigitCount is known.
|
||||||
|
// For "rgb:" format, colorspecs are up to hhhh/hhhh/hhhh, for 1-4 h's
|
||||||
|
const auto iteration = isSharpSignFormat ? rgbHexDigitCount : 4;
|
||||||
|
for (size_t i = 0; i < iteration && curr < string.cend(); i++)
|
||||||
|
{
|
||||||
|
const wchar_t wch = *curr++;
|
||||||
|
|
||||||
|
parameterValue *= 16;
|
||||||
|
unsigned int intVal = 0;
|
||||||
|
const auto ret = HexToUint(wch, intVal);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
// Encountered something weird oh no
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameterValue += intVal;
|
||||||
|
|
||||||
|
if (isSharpSignFormat)
|
||||||
|
{
|
||||||
|
// If we get this far, any number can be seen as a valid part
|
||||||
|
// of this component.
|
||||||
|
foundColor = true;
|
||||||
|
|
||||||
|
if (i >= rgbHexDigitCount)
|
||||||
|
{
|
||||||
|
// Successfully parsed this component. Start the next one.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Record the hex digit count of the current component.
|
||||||
|
rgbHexDigitCount = i + 1;
|
||||||
|
|
||||||
|
// If this is the first 2 component...
|
||||||
|
if (component < 2 && curr < string.cend() && *curr == L'/')
|
||||||
|
{
|
||||||
|
// ...and we have successfully parsed this component, we need
|
||||||
|
// to skip the delimiter before starting the next one.
|
||||||
|
curr++;
|
||||||
|
foundColor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Or we have reached the end of the string...
|
||||||
|
else if (curr >= string.cend())
|
||||||
|
{
|
||||||
|
// ...meaning that this is the last component. We're not going to
|
||||||
|
// see any delimiter. We can just break out.
|
||||||
|
foundColor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundColor)
|
||||||
|
{
|
||||||
|
// Indicates there was some error parsing color.
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the actual color value based on the hex digit count.
|
||||||
|
auto& colorValue = til::at(colorValues, component);
|
||||||
|
const auto scaleMultiplier = isSharpSignFormat ? 0x10 : 0x11;
|
||||||
|
const auto scaleDivisor = scaleMultiplier << 8 >> 4 * (4 - rgbHexDigitCount);
|
||||||
|
colorValue = parameterValue * scaleMultiplier / scaleDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr >= string.cend())
|
||||||
|
{
|
||||||
|
// We're at the end of the string and we have successfully parsed the color.
|
||||||
|
foundValidColorSpec = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only if we find a valid colorspec can we pass it out successfully.
|
||||||
|
if (foundValidColorSpec)
|
||||||
|
{
|
||||||
|
return til::color(LOBYTE(til::at(colorValues, 0)),
|
||||||
|
LOBYTE(til::at(colorValues, 1)),
|
||||||
|
LOBYTE(til::at(colorValues, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG_CAUGHT_EXCEPTION();
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Converts a hex character to its equivalent integer value.
|
||||||
|
// Arguments:
|
||||||
|
// - wch - Character to convert.
|
||||||
|
// - value - receives the int value of the char
|
||||||
|
// Return Value:
|
||||||
|
// - true iff the character is a hex character.
|
||||||
|
bool Utils::HexToUint(const wchar_t wch,
|
||||||
|
unsigned int& value) noexcept
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
bool success = false;
|
||||||
|
if (wch >= L'0' && wch <= L'9')
|
||||||
|
{
|
||||||
|
value = wch - L'0';
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
else if (wch >= L'A' && wch <= L'F')
|
||||||
|
{
|
||||||
|
value = (wch - L'A') + 10;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
else if (wch >= L'a' && wch <= L'f')
|
||||||
|
{
|
||||||
|
value = (wch - L'a') + 10;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Converts a number string to its equivalent unsigned integer value.
|
||||||
|
// Arguments:
|
||||||
|
// - wstr - String to convert.
|
||||||
|
// - value - receives the int value of the string
|
||||||
|
// Return Value:
|
||||||
|
// - true iff the string is a unsigned integer string.
|
||||||
|
bool Utils::StringToUint(const std::wstring_view wstr,
|
||||||
|
unsigned int& value)
|
||||||
|
{
|
||||||
|
if (wstr.size() < 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int result = 0;
|
||||||
|
size_t current = 0;
|
||||||
|
while (current < wstr.size())
|
||||||
|
{
|
||||||
|
const wchar_t wch = wstr.at(current);
|
||||||
|
if (_isNumber(wch))
|
||||||
|
{
|
||||||
|
result *= 10;
|
||||||
|
result += wch - L'0';
|
||||||
|
|
||||||
|
++current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = result;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Split a string into different parts using the delimiter provided.
|
||||||
|
// Arguments:
|
||||||
|
// - wstr - String to split.
|
||||||
|
// - delimiter - delimiter to use.
|
||||||
|
// Return Value:
|
||||||
|
// - a vector containing the result string parts.
|
||||||
|
std::vector<std::wstring_view> Utils::SplitString(const std::wstring_view wstr,
|
||||||
|
const wchar_t delimiter)
|
||||||
|
{
|
||||||
|
std::vector<std::wstring_view> result;
|
||||||
|
size_t current = 0;
|
||||||
|
while (current < wstr.size())
|
||||||
|
{
|
||||||
|
const auto nextDelimiter = wstr.find(delimiter, current);
|
||||||
|
if (nextDelimiter == std::wstring::npos)
|
||||||
|
{
|
||||||
|
result.push_back(wstr.substr(current));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto length = nextDelimiter - current;
|
||||||
|
result.push_back(wstr.substr(current, length));
|
||||||
|
// Skip this part and the delimiter. Start the next one
|
||||||
|
current += length + 1;
|
||||||
|
// The next index is larger than string size, which means the string
|
||||||
|
// is in the format of "part1;part2;" (assuming use ';' as delimiter).
|
||||||
|
// Add the last part which is an empty string.
|
||||||
|
if (current >= wstr.size())
|
||||||
|
{
|
||||||
|
result.push_back(L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Shorthand check if a handle value is null or invalid.
|
// - Shorthand check if a handle value is null or invalid.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
@ -388,63 +433,6 @@ bool Utils::IsValidHandle(const HANDLE handle) noexcept
|
|||||||
return handle != nullptr && handle != INVALID_HANDLE_VALUE;
|
return handle != nullptr && handle != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - Fill the first 16 entries of a given color table with the Campbell color
|
|
||||||
// scheme, in the ANSI/VT RGB order.
|
|
||||||
// Arguments:
|
|
||||||
// - table: a color table with at least 16 entries
|
|
||||||
// Return Value:
|
|
||||||
// - <none>, throws if the table has less that 16 entries
|
|
||||||
void Utils::InitializeCampbellColorTable(const gsl::span<COLORREF> table)
|
|
||||||
{
|
|
||||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
|
||||||
|
|
||||||
std::copy(campbellColorTable.begin(), campbellColorTable.end(), table.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - Fill the first 16 entries of a given color table with the Campbell color
|
|
||||||
// scheme, in the Windows BGR order.
|
|
||||||
// Arguments:
|
|
||||||
// - table: a color table with at least 16 entries
|
|
||||||
// Return Value:
|
|
||||||
// - <none>, throws if the table has less that 16 entries
|
|
||||||
void Utils::InitializeCampbellColorTableForConhost(const gsl::span<COLORREF> table)
|
|
||||||
{
|
|
||||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
|
||||||
InitializeCampbellColorTable(table);
|
|
||||||
SwapANSIColorOrderForConhost(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - modifies in-place the given color table from ANSI (RGB) order to Console order (BRG).
|
|
||||||
// Arguments:
|
|
||||||
// - table: a color table with at least 16 entries
|
|
||||||
// Return Value:
|
|
||||||
// - <none>, throws if the table has less that 16 entries
|
|
||||||
void Utils::SwapANSIColorOrderForConhost(const gsl::span<COLORREF> table)
|
|
||||||
{
|
|
||||||
THROW_HR_IF(E_INVALIDARG, table.size() < 16);
|
|
||||||
std::swap(til::at(table, 1), til::at(table, 4));
|
|
||||||
std::swap(til::at(table, 3), til::at(table, 6));
|
|
||||||
std::swap(til::at(table, 9), til::at(table, 12));
|
|
||||||
std::swap(til::at(table, 11), til::at(table, 14));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - Fill the first 255 entries of a given color table with the default values
|
|
||||||
// of a full 256-color table
|
|
||||||
// Arguments:
|
|
||||||
// - table: a color table with at least 256 entries
|
|
||||||
// Return Value:
|
|
||||||
// - <none>, throws if the table has less that 256 entries
|
|
||||||
void Utils::Initialize256ColorTable(const gsl::span<COLORREF> table)
|
|
||||||
{
|
|
||||||
THROW_HR_IF(E_INVALIDARG, table.size() < 256);
|
|
||||||
|
|
||||||
std::copy(standardXterm256ColorTable.begin(), standardXterm256ColorTable.end(), table.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - Generate a Version 5 UUID (specified in RFC4122 4.3)
|
// - Generate a Version 5 UUID (specified in RFC4122 4.3)
|
||||||
// v5 UUIDs are stable given the same namespace and "name".
|
// v5 UUIDs are stable given the same namespace and "name".
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user