Compare commits

..

40 commits

Author SHA1 Message Date
Carlos Zamora 1a2da08f15 add client secret 2021-11-23 16:13:41 -05:00
Carlos Zamora 158d242d85 fix env var references 2021-11-23 15:22:49 -05:00
Carlos Zamora e15f639b85 fix path to json 2021-11-23 14:59:52 -05:00
Carlos Zamora d8d0cc90d0 spellcheck 2021-11-23 14:51:53 -05:00
Carlos Zamora d5c7cebc7d set up notifications; ready for review 2021-11-23 14:44:44 -05:00
Carlos Zamora 83037289ef couldn't find fuzzer lib, add MT to help 2021-11-22 17:43:49 -05:00
Carlos Zamora ce5209880f fix build 2021-11-22 17:34:35 -05:00
Carlos Zamora c97787f020 copy over relevant missing steps from build-console-steps (broken since c91e07) 2021-11-22 13:03:48 -05:00
Carlos Zamora 4bd309522d change build pool & remove unused PGO steps 2021-11-22 10:34:02 -05:00
Carlos Zamora 541b25c68f fix indents 2021-11-18 13:27:09 -08:00
Carlos Zamora c32524ae1f spelling 2021-11-18 11:23:12 -08:00
Carlos Zamora a578d877c1 Merge branch 'dev/cazamor/onefuzz/setup' of https://github.com/microsoft/Terminal into dev/cazamor/onefuzz/setup 2021-11-18 11:06:53 -08:00
Carlos Zamora 1268cc1493 Merge branch 'main' into dev/cazamor/onefuzz/setup 2021-11-18 11:01:29 -08:00
Carlos Zamora 16d226a6f4 apply PR feedback; add notifications 2021-06-23 14:13:02 -07:00
Carlos Zamora c91e078df8 address PR feedback 2021-06-23 11:55:35 -07:00
Carlos Zamora 4e3a1ba8e9 Merge branch 'main' into dev/cazamor/onefuzz/setup 2021-06-23 09:49:41 -07:00
Dustin L. Howett a8c905d95f Migrate spelling-0.0.19 changes from main 2021-06-15 11:03:05 -07:00
Carlos Zamora 83ea5f3a68 fix fuzz.yml; add doc 2021-06-15 11:03:05 -07:00
Carlos Zamora 7719b1feeb add a variable for SHA1, just to get going 2021-06-14 13:08:34 -07:00
Carlos Zamora 1030c062cf fix up those slashes 2021-06-14 12:51:35 -07:00
Carlos Zamora 35c99673cf don't forget the _drop_ 2021-06-14 12:43:02 -07:00
Carlos Zamora facdf7745c added an extra slash 2021-06-14 12:36:26 -07:00
Carlos Zamora dc9fd554c4 actually download the artifacts 2021-06-14 11:59:10 -07:00
Carlos Zamora 153971af7d bring back stages; fiz path 2021-06-14 11:36:10 -07:00
Carlos Zamora db0fdd6ba9 pointed at the wrong thing 2021-06-11 17:14:31 -07:00
Carlos Zamora 745728a082 3rd time's the charm? 2021-06-11 17:12:48 -07:00
Carlos Zamora 7611c6cf02 apparently you NEED a stage 2021-06-11 17:06:12 -07:00
Carlos Zamora 74bcb1c6b8 stages don't preserve file system changes 2021-06-11 16:58:30 -07:00
Carlos Zamora aa644e94c9 fix onefuxx call (this one should work) 2021-06-11 16:40:57 -07:00
Carlos Zamora ce26d64ee7 escape the slasher 2021-06-11 15:49:29 -07:00
Carlos Zamora 02af781697 fix syntax error 2021-06-11 15:41:40 -07:00
Carlos Zamora bda579ddfb remove useless build step; try fix onefuzz cmd 2021-06-11 15:31:21 -07:00
Carlos Zamora e3f64b943c BUILD PLATFORM --> CONFIGURATION 2021-06-11 14:47:58 -07:00
Carlos Zamora d4ae5f9a28 or --> and (bad logic) 2021-06-11 14:03:00 -07:00
Carlos Zamora da864edf53 test: print variable to see if it's populated 2021-06-11 13:55:41 -07:00
Carlos Zamora e8266b13b9 add some conditions to the build template 2021-06-11 11:03:53 -07:00
Carlos Zamora f2f188fd70 fix configs --> fix build 2021-06-10 17:11:13 -07:00
Carlos Zamora 6e6a6edfa3 fix platform 2021-06-08 15:30:04 -07:00
Carlos Zamora 284a4a7e82 Fix pipeline syntax issues
[skip ci]
2021-06-08 18:18:34 -04:00
Carlos Zamora f39b092a5e Setup OneFuzz 2021-06-08 15:01:25 -07:00
81 changed files with 1166 additions and 846 deletions

View file

@ -3,6 +3,7 @@ apc
Apc
bsd
calt
CMMI
ccmp
changelog
clickable
@ -35,6 +36,7 @@ img
inlined
It'd
kje
libfuzzer
liga
lje
Llast
@ -46,11 +48,13 @@ maxed
mkmk
mnt
mru
noreply
nje
noreply
ogonek
ok'd
overlined
pipeline
postmodern
ptys
qof

View file

@ -30,6 +30,7 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
endfor
enumset
environstrings
EXPCMDFLAGS
@ -115,6 +116,7 @@ oaidl
ocidl
ODR
offsetof
onefuzz
osver
OSVERSIONINFOEXW
otms
@ -169,7 +171,6 @@ toupper
TTask
TVal
UChar
UFIELD
ULARGE
UPDATEINIFILE
userenv

View file

@ -39,6 +39,7 @@ MSVC
muxc
netcore
osgvsowi
Onefuzz
PFILETIME
pgc
pgo

View file

@ -8,6 +8,7 @@ dhowett
Diviness
dsafa
duhowett
DXP
ekg
eryksun
ethanschoonover
@ -69,6 +70,7 @@ sonpham
stakx
thereses
Walisch
WDX
Wellons
Wirt
Wojciech

View file

@ -17,3 +17,4 @@ mdtauk
cppreference
gfycat
Guake
azurewebsites

View file

@ -4,7 +4,7 @@ https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]*
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)

View file

@ -25,6 +25,7 @@
"Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"Microsoft.VisualStudio.Component.VC.Tools.ARM64",
"Microsoft.VisualStudio.Component.VC.ASAN",
"Microsoft.VisualStudio.Component.VC.v142.x86.x64",
"Microsoft.VisualStudio.Component.VC.v142.ARM64",
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",

View file

@ -99,29 +99,15 @@ If you don't have any additional info/context to add but would like to indicate
## Contributing fixes / features
If you're able & willing to help fix issues and/or implement features, we'd love your contribution!
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.
* ["Tasks"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Task%22+) are usually new pieces of functionality that aren't yet implemented for the Terminal/Console. These are usually smaller features, which we believe
- could be a single, atomic PR
- Don't require much design consideration, or we've already written the spec for the larger feature they belong to.
* ["Features"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Feature%22+) are larger pieces of new functionality. These are usually things we believe would require larger discussion of how they should be implemented, or they'll require some complicated new settings. They might just be features that are composed of many individual tasks. Often times, with features, we like to have a spec written before development work is started, to make sure we're all on the same page (see below).
Bugs and tasks are obviously the easiest to get started with, but don't feel afraid of features either! We've had some community members contribute some amazing "feature"-level work to the Terminal (albeit, with lots of discussion 😄).
Often, we like to assign issues that generally belong to somebody's area of expertise to the team member that owns that area. This doesn't mean the community can't jump in -- they should reach out and have a chat with the assignee to see if it'd okay to take. If an issue's been assigned more than a month ago, there's a good chance it's fair game to try yourself.
For those able & willing to help fix issues and/or implement features ...
### To Spec or not to Spec
Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below.
Small issues that do not require a spec will be labelled `Issue-Bug` or `Issue-Task`.
Small issues that do not require a spec will be labelled Issue-Bug or Issue-Task.
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled `Issue-Feature`. More often than not, we'll add such features to the ["Specification Tracker" project](https://github.com/microsoft/terminal/projects/1).
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled Issue-Feature.
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.

View file

@ -1198,11 +1198,11 @@ Global
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x86.Build.0 = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x64.ActiveCfg = Debug|x64
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x86.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|Any CPU.ActiveCfg = Release|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|ARM.ActiveCfg = Release|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|ARM64.ActiveCfg = Release|ARM64
@ -1269,7 +1269,6 @@ Global
{919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x64.Build.0 = Fuzzing|x64
{919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{919544AC-D39B-463F-8414-3C3C67CF727C}.Release|Any CPU.ActiveCfg = Release|Win32
{919544AC-D39B-463F-8414-3C3C67CF727C}.Release|ARM.ActiveCfg = Release|Win32
@ -3246,13 +3245,10 @@ Global
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x64.Build.0 = Fuzzing|x64
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|Any CPU.ActiveCfg = Release|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|ARM.ActiveCfg = Release|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|ARM64.ActiveCfg = Release|ARM64
@ -3326,7 +3322,6 @@ Global
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.Build.0 = Fuzzing|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|Any CPU.ActiveCfg = Release|Win32

View file

@ -0,0 +1,34 @@
{
"config": {
"base_url": "https://dev.azure.com/microsoft/os",
"auth_token": "INSERT_PAT_HERE",
"project": "OpenConsole",
"type": "Bug",
"unique_fields": [
"Microsoft.VSTS.Common.CustomString03"
],
"comment": "<a href='{{ input_url }}'>This input</a> caused the <a href='{{ target_url }}'>fuzz target</a> {{ report.executable }} to crash. The faulting input SHA256 hash is {{ report.input_sha256 }} <br>",
"ado_fields": {
"System.AssignedTo": "INSERT_ASSIGNED_HERE",
"System.Tags": "OneFuzz",
"System.AreaPath": "OS\\WDX\\DXP\\WinDev\\Terminal",
"OSG.Watson.Telemetry14DaysInMarketHits": "1",
"System.IterationPath": "OS\\Future",
"Microsoft.VSTS.Common.CustomString01": "{{ job.project }}",
"Microsoft.VSTS.Common.CustomString02": "{{ job.name }}",
"Microsoft.VSTS.Common.CustomString03": "{{ report.minimized_stack_function_lines_sha256}}",
"System.Title": "[Fuzzing] - {{ report.crash_site }}",
"Microsoft.VSTS.CMMI.HowFound": "Security: Fuzzing",
"OSG.SecurityImpact": "Security Triage Requested",
"OSG.SDLSeverity": "Moderate",
"Microsoft.VSTS.TCM.ReproSteps": "The fuzzing target ({{ job.project }} {{ job.name }} {{ job.build }}) reported a crash. <br> {%if report.asan_log %} AddressSanitizer reported the following details: <br> <pre> {{ report.asan_log }} </pre> {% else %} Faulting call stack: <ul> {% for item in report.call_stack %} <li> {{ item }} </li> {% endfor %} </ul> <br> {% endif %} You can reproduce the issue remotely in OneFuzz by running the following command: <pre> {{ repro_cmd }} </pre>"
},
"on_duplicate": {
"set_state": {"Resolved": "Active", "Closed": "Active"},
"ado_fields": {
"System.IterationPath": "OS\\Future"
},
"increment": ["OSG.Watson.Telemetry14DaysInMarketHits"]
}
}
}

61
build/pipelines/fuzz.yml Normal file
View file

@ -0,0 +1,61 @@
trigger:
batch: true
branches:
include:
- main
paths:
exclude:
- docs/*
- samples/*
- tools/*
pr: none
# 0.0.yyMM.dd##
# 0.0.1904.0900
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
stages:
- stage: Build_Fuzz_Config
displayName: Build Fuzzers
dependsOn: []
condition: succeeded()
jobs:
- template: ./templates/build-console-fuzzing.yml
parameters:
platform: x64
- stage: OneFuzz
displayName: Submit OneFuzz Job
dependsOn: ['Build_Fuzz_Config']
condition: succeeded()
pool:
vmImage: 'ubuntu-latest'
variables:
artifactName: drop
jobs:
- job:
steps:
- task: DownloadBuildArtifacts@0
inputs:
artifactName: $(artifactName)
downloadPath: $(Build.ArtifactStagingDirectory)
- task: UsePythonVersion@0
inputs:
versionSpec: '3.x'
addToPath: true
architecture: 'x64'
- bash: |
set -ex
pip -q install onefuzz
onefuzz config --endpoint $(endpoint) --client_id $(client_id) --authority $(authority) --tenant_domain $(tenant_domain) --client_secret $(client_secret)
sed -i s/INSERT_PAT_HERE/${ado_pat}/ build/Fuzz/notifications-ado.json
sed -i s/INSERT_ASSIGNED_HERE/${ado_assigned_to}/ build/Fuzz/notifications-ado.json
displayName: Configure OneFuzz
# replace the bash command below with this to run this with notifications
# onefuzz template libfuzzer basic --colocate_all_tasks --vm_count 1 --target_exe $target_exe_path --notification_config build/Fuzz/notifications-ado.json OpenConsole $test_name $(Build.SourceVersion) windows
- bash: |
onefuzz template libfuzzer basic --colocate_all_tasks --vm_count 1 --target_exe $target_exe_path OpenConsole $test_name $(Build.SourceVersion) windows
displayName: Submit OneFuzz Job
env:
target_exe_path: $(Build.ArtifactStagingDirectory)/$(artifactName)/Fuzzing/x64/test/OpenConsoleFuzzer.exe
test_name: WriteCharsLegacy

View file

@ -0,0 +1,132 @@
parameters:
configuration: 'Fuzzing'
platform: ''
additionalBuildArguments: ''
jobs:
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
steps:
- checkout: self
submodules: true
clean: true
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 5.2.0
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for solution
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: OpenConsole.sln
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
- script: |
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
del %TEMP%\vsinstalldir.txt
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
echo VCToolsInstallDir = %VCToolsInstallDir%
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- task: CmdLine@1
displayName: 'Display build machine environment variables'
inputs:
filename: 'set'
- task: VSBuild@1
displayName: 'Build solution **\OpenConsole.sln'
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArgs: "${{ parameters.additionalBuildArguments }}"
clean: true
maximumCpuCount: true
- task: PowerShell@2
displayName: 'Rationalize build platform'
inputs:
targetType: inline
script: |
$Arch = "$(BuildPlatform)"
If ($Arch -Eq "x86") { $Arch = "Win32" }
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: CopyFiles@2
displayName: 'Copy result logs to Artifacts'
inputs:
Contents: |
**/*.wtl
**/*onBuildMachineResults.xml
${{ parameters.testLogPath }}
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
OverWrite: true
flattenFolders: true
- task: CopyFiles@2
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
inputs:
Contents: |
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
condition: succeeded()
- task: CopyFiles@2
displayName: 'Copy outputs needed for test runs to Artifacts'
inputs:
Contents: |
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
**/Microsoft.VCLibs.*.appx
**/TestHostApp/*.exe
**/TestHostApp/*.dll
**/TestHostApp/*.xml
!**/*.pdb
!**/*.ipdb
!**/*.obj
!**/*.pch
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
OverWrite: true
flattenFolders: true
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: 'Publish All Build Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'

View file

@ -113,7 +113,7 @@ steps:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
condition: and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument'), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
- task: PowerShell@2
displayName: 'Run Feature Tests (x64 only)'
@ -121,7 +121,7 @@ steps:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
condition: and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument'), eq(variables['BuildPlatform'], 'x64'))
- task: PowerShell@2
displayName: 'Convert Test Logs from WTL to xUnit format'
@ -129,7 +129,7 @@ steps:
targetType: filePath
filePath: build\Helix\ConvertWttLogToXUnit.ps1
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
condition: and(ne(variables['PGOBuildMode'], 'Instrument'), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
- task: PublishTestResults@2
displayName: 'Upload converted test logs'
@ -193,7 +193,7 @@ steps:
displayName: 'Publish All Build Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
ArtifactName: 'drop'
- task: CopyFiles@2
displayName: 'Copy PGO databases needed for PGO instrumentation run'

View file

@ -63,14 +63,8 @@
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
DependsOnTargets="_GenerateBranchAndBrandingCache">
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
<!-- This commandline is escaped like:
powershell -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)'' -Branding $(_WTBrandingName)"
which was the only way I could find to get it to obey spaces in the SolutionDir
-->
<Exec
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;&amp;&apos;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&apos; -Path &apos;%(FeatureFlagFile.FullPath)&apos; -Branding $(_WTBrandingName)&quot;"
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
ConsoleToMsBuild="true"
StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />

62
doc/fuzzing.md Normal file
View file

@ -0,0 +1,62 @@
# Fuzzing
## Setting up a fuzzer locally
As of v1.8, OpenConsole can now be built with a `Fuzzing` configuration.
To set up a fuzzer, you'll need an `LLVMFuzzerTestOneInput` function. This serves as a way for the fuzzer to attach itself and inject tests into your fuzz target.
To build the fuzzer locally, build the OpenConsole solution in the `Fuzzing` configuration. This should output an executable that runs the fuzzer on the provided test case. In the case of PR \#9604, the desired executable is located at `bin\x64\Fuzzing\OpenConsoleFuzzer.exe`.
### Resources
- [LibFuzzer Docs](https://www.llvm.org/docs/LibFuzzer.html)
- [#9604](https://github.com/microsoft/terminal/pull/9604)
## Setting up OneFuzz
OneFuzz allows us to run our fuzzers in CI and be alerted of new bugs found in this endeavor.
### Installing OneFuzz
You can download the latest OneFuzz CLI on their [releases page](https://github.com/microsoft/onefuzz/releases).
### Configuring OneFuzz
To run OneFuzz locally, you'll need to configure its endpoint, client ID, and client secret. Windows has a preset configuration available; this can be found at [this tutorial](https://www.osgwiki.com/wiki/Fuzzing_Service_-_Azure_Edge_and_Platform#Configure_OneFuzz_CLI) on osgwiki.
`onefuzz config --endpoint $(endpoint) --client_id $(client_id) --authority $(authority) --tenant_domain $(tenant_domain)`
**NOTE**: Our pipeline is already set up with these variables, so you don't need to worry about this when running this on Azure DevOps.
### Running a job on OneFuzz
You should now be able to run a job using the following command:
`onefuzz template libfuzzer basic <project> <name> <build> <pool> --target_exe <exe_path>`
- `project`: the name of the project
- `name`: the name of the test
- `build`: the identifier for the build (i.e. commit SHA1)
- `pool`: the VM pool to run this on
- `exe_path`: the fuzzer executable output from building your project
This should also output more information (i.e. job ID) about the newly created job in a JSON format.
### Enabling notifications
**NOTE**: Our pipeline is already set up with this functionality. However, here is a quick guide on how to get it set up and modify it to our liking.
OneFuzz supports multiple notification systems at once including MS Teams and Azure DevOps. See the resources below to learn more about setting these up.
Our pipeline has been set up to create Azure DevOps work items.
### Resources
- [OneFuzz GitHub](https://github.com/microsoft/onefuzz)
- [Getting started using OneFuzz](https://github.com/microsoft/onefuzz/blob/main/docs/getting-started.md)
- [Releases Page](https://github.com/microsoft/onefuzz/releases)
- [Notifications](https://github.com/microsoft/onefuzz/blob/main/docs/notifications.md)
- [MS Teams](https://github.com/microsoft/onefuzz/blob/main/docs/notifications/teams.md)
- [Azure DevOps](https://github.com/microsoft/onefuzz/blob/main/docs/notifications/ado.md)
- [OSG Wiki - OneFuzz](https://www.osgwiki.com/wiki/Fuzzing_Service_-_Azure_Edge_and_Platform)

View file

@ -118,23 +118,6 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

@ -128,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
// - Calculates rgb colors based off of current color table and active modification attributes.
// Arguments:
// - colorTable: the current color table rgb values.
// - defaultFgIndex: the color table index of the default foreground color.
// - defaultBgIndex: the color table index of the default background color.
// - defaultFgColor: the default foreground color rgb value.
// - defaultBgColor: the default background color rgb value.
// - reverseScreenMode: true if the screen mode is reversed.
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
// Return Value:
// - the foreground and background colors that should be displayed.
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
const bool reverseScreenMode,
const bool blinkingIsFaint,
const bool boldIsBright) const noexcept
{
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgIndex);
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgColor);
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
{
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.

View file

@ -64,9 +64,9 @@ public:
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
WORD GetLegacyAttributes() const noexcept;
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
const bool reverseScreenMode = false,
const bool blinkingIsFaint = false,
const bool boldIsBright = true) const noexcept;

View file

@ -139,16 +139,14 @@ void TextColor::SetDefault() noexcept
// Arguments:
// - colorTable: The table of colors we should use to look up the value of
// an indexed attribute from.
// - defaultIndex: The color table index to use if we're a default attribute.
// - defaultColor: The color value to use if we're a default attribute.
// - brighten: if true, we'll brighten a dark color table index.
// Return Value:
// - a COLORREF containing the real value of this TextColor.
COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
{
if (IsDefault())
{
const auto defaultColor = til::at(colorTable, defaultIndex);
if (brighten)
{
// See MSFT:20266024 for context on this fix.

View file

@ -65,11 +65,6 @@ public:
static constexpr BYTE BRIGHT_CYAN = 14;
static constexpr BYTE BRIGHT_WHITE = 15;
static constexpr size_t DEFAULT_FOREGROUND = 256;
static constexpr size_t DEFAULT_BACKGROUND = 257;
static constexpr size_t CURSOR_COLOR = 258;
static constexpr size_t TABLE_SIZE = 259;
constexpr TextColor() noexcept :
_meta{ ColorType::IsDefault },
_red{ 0 },
@ -108,7 +103,7 @@ public:
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
void SetDefault() noexcept;
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept;
COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
constexpr BYTE GetIndex() const noexcept

View file

@ -27,7 +27,9 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false),
_ulSize(ulSize),
_cursorType(CursorType::Legacy)
_cursorType(CursorType::Legacy),
_fUseColor(false),
_color(s_InvertCursorColor)
{
}
@ -141,9 +143,10 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
_RedrawCursor();
}
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
{
_ulSize = ulSize;
_color = color;
_cursorType = type;
_RedrawCursor();
@ -282,6 +285,7 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
// Size will be handled separately in the resize operation.
//_ulSize = OtherCursor._ulSize;
_cursorType = OtherCursor._cursorType;
_color = OtherCursor._color;
}
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
@ -331,6 +335,21 @@ const CursorType Cursor::GetType() const noexcept
return _cursorType;
}
const bool Cursor::IsUsingColor() const noexcept
{
return GetColor() != INVALID_COLOR;
}
const COLORREF Cursor::GetColor() const noexcept
{
return _color;
}
void Cursor::SetColor(const unsigned int color) noexcept
{
_color = gsl::narrow_cast<COLORREF>(color);
}
void Cursor::SetType(const CursorType type) noexcept
{
_cursorType = type;

View file

@ -24,6 +24,7 @@ class TextBuffer;
class Cursor final
{
public:
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
// the following values are used to create the textmode cursor.
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
@ -50,6 +51,8 @@ public:
COORD GetPosition() const noexcept;
const CursorType GetType() const noexcept;
const bool IsUsingColor() const noexcept;
const COLORREF GetColor() const noexcept;
void StartDeferDrawing() noexcept;
bool IsDeferDrawing() noexcept;
@ -64,7 +67,7 @@ public:
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
void SetDelay(const bool fDelay) noexcept;
void SetSize(const ULONG ulSize) noexcept;
void SetStyle(const ULONG ulSize, const CursorType type) noexcept;
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
void SetPosition(const COORD cPosition) noexcept;
void SetXPosition(const int NewX) noexcept;
@ -81,6 +84,7 @@ public:
COORD GetDelayedAtPosition() const noexcept;
bool IsDelayedEOLWrap() const noexcept;
void SetColor(const unsigned int color) noexcept;
void SetType(const CursorType type) noexcept;
private:
@ -113,4 +117,6 @@ private:
void _RedrawCursorAlways() noexcept;
CursorType _cursorType;
bool _fUseColor;
COLORREF _color;
};

View file

@ -24,11 +24,9 @@ class TextAttributeTests
TEST_METHOD(TestRoundtripDefaultColors);
TEST_METHOD(TestBoldAsBright);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
};
bool TextAttributeTests::ClassSetup()
@ -49,8 +47,6 @@ bool TextAttributeTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true;
}
@ -136,17 +132,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// reset the reverse video
attr.SetReverseVideo(false);
@ -155,17 +151,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// while the background and getters stay the same
attr.SetFaint(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be
// switched, and the background fainter, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// reset the reverse video and faint attributes
attr.SetReverseVideo(false);
@ -175,17 +171,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// background, while getters stay the same
attr.SetInvisible(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, the calculated background value should match
// the foreground, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
}
void TextAttributeTests::TestReverseDefaultColors()
@ -198,34 +194,34 @@ void TextAttributeTests::TestReverseDefaultColors()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
attr.SetForeground(red);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
attr.Invert();
VERIFY_IS_FALSE(attr.IsReverseVideo());
attr.SetDefaultForeground();
attr.SetBackground(green);
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
}
void TextAttributeTests::TestRoundtripDefaultColors()
@ -281,43 +277,43 @@ void TextAttributeTests::TestBoldAsBright()
// values when not bold
VERIFY_IS_FALSE(attr.IsBold());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
// with bold set, calculated foreground/background values shouldn't change for the default colors.
attr.SetBold(true);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedForeground(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedBackground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"background should be unaffected by 'bold is bright'");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetBold(false);
VERIFY_IS_FALSE(attr.IsBold());
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
attr.SetBold(true);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
}

View file

@ -23,11 +23,9 @@ class TextColorTests
TEST_METHOD(TestRgbColor);
TEST_METHOD(TestChangeColor);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
};
bool TextColorTests::ClassSetup()
@ -48,8 +46,6 @@ bool TextColorTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true;
}
@ -61,16 +57,16 @@ void TextColorTests::TestDefaultColor()
VERIFY_IS_FALSE(defaultColor.IsLegacy());
VERIFY_IS_FALSE(defaultColor.IsRgb());
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
}
@ -82,16 +78,16 @@ void TextColorTests::TestDarkIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -103,16 +99,16 @@ void TextColorTests::TestBrightIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -125,16 +121,16 @@ void TextColorTests::TestRgbColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color);
}
@ -147,55 +143,55 @@ void TextColorTests::TestChangeColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color);
rgbColor.SetDefault();
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
rgbColor.SetIndex(7, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
rgbColor.SetIndex(15, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}

View file

@ -61,26 +61,13 @@
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\wt\wt.vcxproj">
<Project>{506fd703-baa7-4f6e-9361-64f550ec8fca}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\exe\Host.EXE.vcxproj">
<Project>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\proxy\Host.Proxy.vcxproj">
<Project>{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
<ProjectReference Include="..\wt\wt.vcxproj" />
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">

View file

@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
_terminal->SetBackgroundCallback([](auto) {});
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
_terminal->SetDefaultBackground(RGB(12, 12, 12));
_terminal->SetDefaultForeground(RGB(204, 204, 204));
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
localPointerToThread->EnablePainting();
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
{
auto lock = publicTerminal->_terminal->LockForWriting();
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
// Set the font colors

View file

@ -318,29 +318,7 @@
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj">
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
manually include the winmds as References below -->
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See

View file

@ -3,38 +3,38 @@
#include "pch.h"
#include "TerminalPage.h"
#include "TerminalPage.g.cpp"
#include "RenameWindowRequestedArgs.g.cpp"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include <filesystem>
#include <inc/WindowingBehavior.h>
#include <LibraryResources.h>
#include <TerminalCore/ControlKeyStates.hpp>
#include <til/latch.h>
#include "../../types/inc/utils.hpp"
#include "TerminalPage.g.cpp"
#include <winrt/Windows.Storage.h>
#include "TabRowControl.h"
#include "ColorHelper.h"
#include "DebugTapConnection.h"
#include "SettingsTab.h"
#include "TabRowControl.h"
#include "RenameWindowRequestedArgs.g.cpp"
#include "../inc/WindowingBehavior.h"
#include <til/latch.h>
using namespace winrt;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::TerminalApp;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
using namespace std::chrono_literals;
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
@ -1038,153 +1038,29 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
// - Called when the users pressed keyBindings while CommandPalette is open.
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
// Called when the users pressed keyBindings while CommandPalette is open.
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
const auto keyStatus = e.KeyStatus();
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
const auto modifiers = _GetPressedModifierKeys();
const auto key = e.OriginalKey();
const auto scanCode = e.KeyStatus().ScanCode;
const auto coreWindow = CoreWindow::GetForCurrentThread();
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
// GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab.
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
// either have a valid vkey/scanCode. This is important, because this prevents
// accidential insertion of invalid KeyChords into classes like ActionMap.
if (!vkey && !scanCode)
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
{
return;
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
// details
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
{
return;
}
// GH#2235: Terminal::Settings hasn't been modified to differentiate
// between AltGr and Ctrl+Alt yet.
// -> Don't check for key bindings if this is an AltGr key combination.
if (modifiers.IsAltGrPressed())
{
return;
}
const auto actionMap = _settings.ActionMap();
if (!actionMap)
{
return;
}
const auto cmd = actionMap.GetActionByKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
modifiers.IsWinPressed(),
vkey,
scanCode,
});
if (!cmd)
{
return;
}
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
{
return;
}
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
p.Visibility(Visibility::Collapsed);
}
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
_ClearKeyboardState(vkey, scanCode);
e.Handled(true);
}
// Method Description:
// - Get the modifier keys that are currently pressed. This can be used to
// find out which modifiers (ctrl, alt, shift) are pressed in events that
// don't necessarily include that state.
// - This is a copy of TermControl::_GetPressedModifierKeys.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
// != CoreVirtualKeyStates::None
// OR
// == CoreVirtualKeyStates::Down
// Sometimes with the key down, the state is Down | Locked.
// Sometimes with the key up, the state is Locked.
// IsFlagSet(Down) is the only correct solution.
struct KeyModifier
{
VirtualKey vkey;
ControlKeyStates flags;
};
constexpr std::array<KeyModifier, 7> modifiers{ {
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
} };
ControlKeyStates flags;
for (const auto& mod : modifiers)
{
const auto state = window.GetKeyState(mod.vkey);
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
if (isDown)
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
flags |= mod.flags;
CommandPalette().Visibility(Visibility::Collapsed);
}
}
return flags;
}
// Method Description:
// - Discards currently pressed dead keys.
// - This is a copy of TermControl::_ClearKeyboardState.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
{
return;
}
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
std::array<wchar_t, 16> buffer;
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
{
_actionDispatch->DoAction(cmd.ActionAndArgs());
e.Handled(true);
}
}

View file

@ -14,17 +14,12 @@
static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
// fwdecl unittest classes
namespace TerminalAppLocalTests
{
class TabTests;
class SettingsTests;
}
namespace Microsoft::Terminal::Core
{
class ControlKeyStates;
}
};
namespace winrt::TerminalApp::implementation
{
@ -230,8 +225,6 @@ namespace winrt::TerminalApp::implementation
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
void _RegisterActionCallbacks();

View file

@ -68,22 +68,5 @@
</Link>
</ItemDefinitionGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
</Project>

View file

@ -97,39 +97,4 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<!--
BODGY:
We depend on `cpprest142*.dll`, which comes from our vcpkg dependency. As a
part of the vcpkg dependency restore, msbuild will call the `deployBinary()`
function in
`packages\vcpkg-cpprestsdk.2.10.14\scripts\BuildSystems\msbuild\AppLocal.ps1`.
That function does the actual job of copying the file. It copies it outside of
MsBuild. MsBuild then, in the `_CopyFilesMarkedCopyLocal` target, determines
that it needs to copy `cpprest142*.dll`, because that dll is a member of
`@(ReferencesCopiedInThisBuild)`. However, the file's already been copied, so
MsBuild never copies it. But that also prevents MsBuild from setting
`WroteAtLeastOneFile`, which then means that MsBuild will never create the
.CopyComplete file for this project.
Because that file is missing, MsBuild will never think the project is up to
date, and the FastUpToDate check in VS will always force MsBuild to run a pass
on this project.
To mitigate this, we're adding this other target here, which runs after
_CopyFilesMarkedCopyLocal, and always creates the CopyUpToDateMarker. This
makes the FastUpToDate check succeed.
-->
<Target
Name="_Post_CopyFilesMarkedCopyLocal"
AfterTargets="_CopyFilesMarkedCopyLocal"
Condition="'@(ReferenceCopyLocalPaths)' != ''">
<Touch Files="@(CopyUpToDateMarker)"
AlwaysCreate="true" />
</Target>
</Project>
</Project>

View file

@ -1089,7 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::color ControlCore::BackgroundColor() const
{
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
return _terminal->GetDefaultBackground();
}
// Method Description:

View file

@ -773,15 +773,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_HidePointerCursorHandlers(*this, nullptr);
const auto ch = e.Character();
const auto keyStatus = e.KeyStatus();
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
auto modifiers = _GetPressedModifierKeys();
if (keyStatus.IsExtendedKey)
if (e.KeyStatus().IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
e.Handled(handled);
}
@ -876,11 +873,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
auto modifiers = _GetPressedModifierKeys();
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab.
@ -914,6 +906,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
@ -991,7 +988,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
@ -2063,7 +2060,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// don't necessarily include that state.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept
ControlKeyStates TermControl::_GetPressedModifierKeys() const
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE

View file

@ -245,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);

View file

@ -40,10 +40,13 @@ namespace Microsoft::Terminal::Core
virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
virtual bool SetCursorColor(const DWORD color) noexcept = 0;
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;

View file

@ -41,6 +41,8 @@ Terminal::Terminal() :
_mutableViewport{ Viewport::Empty() },
_title{},
_colorTable{},
_defaultFg{ RGB(255, 255, 255) },
_defaultBg{ ARGB(0, 0, 0, 0) },
_screenReversed{ false },
_pfnWriteInput{ nullptr },
_scrollOffset{ 0 },
@ -79,10 +81,6 @@ Terminal::Terminal() :
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
_InitializeColorTable();
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = RGB(255, 255, 255);
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = ARGB(0, 0, 0, 0);
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
}
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
@ -182,13 +180,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
{
// Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect
const til::color newBackgroundColor{ appearance.DefaultBackground() };
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0);
const til::color newForegroundColor{ appearance.DefaultForeground() };
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = newForegroundColor;
const til::color newCursorColor{ appearance.CursorColor() };
_colorTable.at(TextColor::CURSOR_COLOR) = newCursorColor;
til::color newBackgroundColor{ appearance.DefaultBackground() };
_defaultBg = newBackgroundColor.with_alpha(0);
_defaultFg = appearance.DefaultForeground();
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
@ -227,7 +221,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
if (_buffer)
{
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
til::color{ appearance.CursorColor() },
cursorShape);
}
_defaultCursorShape = cursorShape;

View file

@ -106,9 +106,11 @@ public:
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool WarningBell() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
bool SetCursorColor(const COLORREF color) noexcept override;
bool SetDefaultForeground(const COLORREF color) noexcept override;
bool SetDefaultBackground(const COLORREF color) noexcept override;
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
@ -210,6 +212,7 @@ public:
void ClearPatternTree() noexcept;
const std::optional<til::color> GetTabColor() const noexcept;
til::color GetDefaultBackground() const noexcept;
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
@ -278,7 +281,9 @@ private:
std::optional<til::color> _startingTabColor;
// This is still stored as a COLORREF because it interacts with some code in ConTypes
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
til::color _defaultFg;
til::color _defaultBg;
CursorType _defaultCursorShape;
bool _screenReversed;
mutable Microsoft::Console::Render::BlinkingState _blinkingState;

View file

@ -69,6 +69,14 @@ COORD Terminal::GetCursorPosition() noexcept
return newPos;
}
bool Terminal::SetCursorColor(const COLORREF color) noexcept
try
{
_buffer->GetCursor().SetColor(color);
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Moves the cursor down one line, and possibly also to the leftmost column.
// Arguments:
@ -362,22 +370,6 @@ try
}
CATCH_RETURN_FALSE()
// Method Description:
// - Retrieves the value in the colortable at the specified index.
// Arguments:
// - tableIndex: the index of the color table to retrieve.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
try
{
return _colorTable.at(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
}
// Method Description:
// - Updates the value in the colortable at index tableIndex to the new color
// color. color is a COLORREF, format 0x00BBGGRR.
@ -391,11 +383,6 @@ try
{
_colorTable.at(tableIndex) = color;
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
{
_pfnBackgroundColorChanged(color);
}
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
@ -455,6 +442,46 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
return true;
}
// Method Description:
// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default foreground color
// Return Value:
// - true
bool Terminal::SetDefaultForeground(const COLORREF color) noexcept
try
{
_defaultFg = color;
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Updates the default background color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default background color
// Return Value:
// - true
bool Terminal::SetDefaultBackground(const COLORREF color) noexcept
try
{
_defaultBg = color;
_pfnBackgroundColorChanged(color);
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
til::color Terminal::GetDefaultBackground() const noexcept
{
return _defaultBg;
}
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
try
{

View file

@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
return _terminalApi.SetCursorColor(color);
}
CATCH_LOG_RETURN_FALSE()
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
return _terminalApi.SetDefaultForeground(color);
}
CATCH_LOG_RETURN_FALSE()
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
return _terminalApi.SetDefaultBackground(color);
}
CATCH_LOG_RETURN_FALSE()

View file

@ -73,19 +73,19 @@ std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute&
if (attr.IsReverseVideo() ^ _screenReversed)
{
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
colors.second = fgTextColor.GetColor(_colorTable, TextColor::DEFAULT_FOREGROUND);
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
}
else
{
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND);
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
}
}
else
{
colors = attr.CalculateRgbColors(_colorTable,
TextColor::DEFAULT_FOREGROUND,
TextColor::DEFAULT_BACKGROUND,
_defaultFg,
_defaultBg,
_screenReversed,
_blinkingState.IsBlinkingFaint(),
_intenseIsBright);
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
COLORREF Terminal::GetCursorColor() const noexcept
{
return _colorTable.at(TextColor::CURSOR_COLOR);
return _buffer->GetCursor().GetColor();
}
bool Terminal::IsCursorDoubleWidth() const
@ -312,8 +312,8 @@ void Terminal::_MakeAdjustedColorArray()
// to include the default background and default foreground colors
std::array<COLORREF, 18> colorTableWithDefaults;
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
colorTableWithDefaults[DefaultBgIndex] = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
{
const auto fg = til::at(colorTableWithDefaults, fgIndex);

View file

@ -197,29 +197,9 @@
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
manually include the winmds as References below -->
</ItemGroup>
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
@ -286,5 +266,4 @@
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
</Project>

View file

@ -65,7 +65,7 @@
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
<!-- Private:false and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->

View file

@ -96,10 +96,9 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR);
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer();

View file

@ -59,6 +59,7 @@ void TerminalApiTest::SetColorTableEntry()
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(256, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
}

View file

@ -115,23 +115,6 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

@ -219,6 +219,36 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
return pInputBuffer;
}
// Method Description:
// - Return the default foreground color of the console. If the settings are
// configured to have a default foreground color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default foreground color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
{
const auto fg = GetDefaultForegroundColor();
return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
}
// Method Description:
// - Return the default background color of the console. If the settings are
// configured to have a default background color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default background color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
{
const auto bg = GetDefaultBackgroundColor();
return bg != INVALID_COLOR ? bg : GetLegacyColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and our configured default attributes.
@ -227,12 +257,26 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
{
return LookupAttributeColors(attr, GetDefaultForeground(), GetDefaultBackground());
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and the given default color values.
// Arguments:
// - attr: the TextAttribute to retrieve the foreground and background color of.
// - defaultFg: the COLORREF to use for a default foreground color.
// - defaultBg: the COLORREF to use for a default background color.
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept
{
_blinkingState.RecordBlinkingUsage(attr);
return attr.CalculateRgbColors(
GetColorTable(),
GetDefaultForegroundIndex(),
GetDefaultBackgroundIndex(),
defaultFg,
defaultBg,
IsScreenReversed(),
_blinkingState.IsBlinkingFaint());
}

View file

@ -82,7 +82,7 @@
<!-- In theory, we may want to build with a normal main() when Fuzzing is not enabled. -->
<!-- So, let's only add the fuzzer to the link line when we're building for Fuzzing. -->
<Link>
<AdditionalDependencies>clang_rt.fuzzer-$(OCClangArchitectureName).lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>WinMM.Lib;clang_rt.fuzzer_MT-$(OCClangArchitectureName).lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->

View file

@ -143,7 +143,7 @@
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy &quot;$(SolutionDir)\dep\WinAppDriver\*&quot; &quot;$(OutDir)\&quot;</PostBuildEvent>
<PostBuildEvent>copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\</PostBuildEvent>
</PropertyGroup>
<Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@ -152,4 +152,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" />
</Target>
</Project>
</Project>

View file

@ -1499,6 +1499,12 @@ void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
}
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor)
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetColor(cursorColor);
}
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri,
const std::wstring_view params)
@ -1957,6 +1963,115 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
screenInfo.GetActiveBuffer().MoveToBottom();
}
// Method Description:
// - Retrieve the color table value at the specified index.
// Arguments:
// - index: the index in the table to retrieve.
// - value: receives the RGB value for the color at that index in the table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
value = gci.GetColorTableEntry(index);
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the color table value in index to the color specified in value.
// Can be used to set the 256-color table as well as the 16-color table.
// Arguments:
// - index: the index in the table to change.
// - value: the new RGB value to use for that index in the color table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
// Notes:
// Does not take a buffer parameter. The color table for a console and for
// terminals as well is global, not per-screen-buffer.
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetColorTableEntry(index, value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default foreground color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultForegroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default background color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultBackgroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Routine Description:
// - A private API call for filling a region of the screen buffer.
// Arguments:

View file

@ -36,6 +36,8 @@ void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo);
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
const CursorType cursorType);
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor);
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri,
@ -61,6 +63,13 @@ void DoSrvPrivateInsertLines(const size_t count);
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept;
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
const COORD startPosition,
const size_t fillLength,

View file

@ -552,6 +552,21 @@ bool ConhostInternalGetSet::PrivateSuppressResizeRepaint()
return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint());
}
// Routine Description:
// - Connects the SetCursorStyle call directly into our Driver Message servicing call inside Conhost.exe
// SetCursorStyle is an internal-only "API" call that the vt commands can execute,
// but it is not represented as a function call on our public API surface.
// Arguments:
// - cursorColor: The color to change the cursor to. INVALID_COLOR will revert
// it to the legacy inverting behavior.
// Return Value:
// - true if successful (see DoSrvSetCursorStyle). false otherwise.
bool ConhostInternalGetSet::SetCursorColor(const COLORREF cursorColor)
{
DoSrvSetCursorColor(_io.GetActiveOutputBuffer(), cursorColor);
return true;
}
// Routine Description:
// - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe
// - NOTE: This ONE method behaves differently! The rest of the methods on this
@ -593,61 +608,54 @@ bool ConhostInternalGetSet::MoveToBottom() const
}
// Method Description:
// - Retrieves the value in the colortable at the specified index.
// - Connects the PrivateGetColorTableEntry call directly into our Driver Message servicing
// call inside Conhost.exe
// Arguments:
// - tableIndex: the index of the color table to retrieve.
// - index: the index in the table to retrieve.
// - value: receives the RGB value for the color at that index in the table.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF ConhostInternalGetSet::GetColorTableEntry(const size_t tableIndex) const noexcept
try
// - true if successful (see DoSrvPrivateGetColorTableEntry). false otherwise.
bool ConhostInternalGetSet::PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept
{
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
return gci.GetColorTableEntry(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
return SUCCEEDED(DoSrvPrivateGetColorTableEntry(index, value));
}
// Method Description:
// - Updates the value in the colortable at index tableIndex to the new color
// color. color is a COLORREF, format 0x00BBGGRR.
// - Connects the PrivateSetColorTableEntry call directly into our Driver Message servicing
// call inside Conhost.exe
// Arguments:
// - tableIndex: the index of the color table to update.
// - color: the new COLORREF to use as that color table value.
// - index: the index in the table to change.
// - value: the new RGB value to use for that index in the color table.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept
try
// - true if successful (see DoSrvPrivateSetColorTableEntry). false otherwise.
bool ConhostInternalGetSet::PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept
{
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
gci.SetColorTableEntry(tableIndex, color);
// If we're setting the default foreground or background colors
// we need to make sure the index is correctly set as well.
if (tableIndex == TextColor::DEFAULT_FOREGROUND)
{
gci.SetDefaultForegroundIndex(TextColor::DEFAULT_FOREGROUND);
}
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
{
gci.SetDefaultBackgroundIndex(TextColor::DEFAULT_BACKGROUND);
}
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return true;
return SUCCEEDED(DoSrvPrivateSetColorTableEntry(index, value));
}
// Method Description:
// - Connects the PrivateSetDefaultForeground call directly into our Driver Message servicing
// call inside Conhost.exe
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - true if successful (see DoSrvPrivateSetDefaultForegroundColor). false otherwise.
bool ConhostInternalGetSet::PrivateSetDefaultForeground(const COLORREF value) const noexcept
{
return SUCCEEDED(DoSrvPrivateSetDefaultForegroundColor(value));
}
// Method Description:
// - Connects the PrivateSetDefaultBackground call directly into our Driver Message servicing
// call inside Conhost.exe
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - true if successful (see DoSrvPrivateSetDefaultBackgroundColor). false otherwise.
bool ConhostInternalGetSet::PrivateSetDefaultBackground(const COLORREF value) const noexcept
{
return SUCCEEDED(DoSrvPrivateSetDefaultBackgroundColor(value));
}
CATCH_RETURN_FALSE()
// Routine Description:
// - Connects the PrivateFillRegion call directly into our Driver Message servicing

View file

@ -101,6 +101,7 @@ public:
bool GetUserDefaultCursorStyle(CursorType& style) override;
bool SetCursorStyle(CursorType const style) override;
bool SetCursorColor(COLORREF const color) override;
bool PrivateRefreshWindow() override;
@ -118,8 +119,12 @@ public:
bool MoveToBottom() const override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept override;
bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept override;
bool PrivateSetDefaultForeground(const COLORREF value) const noexcept override;
bool PrivateSetDefaultBackground(const COLORREF value) const noexcept override;
bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength,

View file

@ -7,6 +7,7 @@
<ProjectName>OpenConsoleProxy</ProjectName>
<TargetName>OpenConsoleProxy</TargetName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<ConfigurationType Condition="'$(Configuration)'=='Fuzzing'">StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>

View file

@ -110,6 +110,8 @@ void RenderData::UnlockConsole() noexcept
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
_defaultForeground = gci.GetDefaultForeground();
_defaultBackground = gci.GetDefaultBackground();
return gci.GetActiveOutputBuffer().GetAttributes();
}
@ -224,7 +226,8 @@ ULONG RenderData::GetCursorPixelWidth() const noexcept
COLORREF RenderData::GetCursorColor() const noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetColorTableEntry(TextColor::CURSOR_COLOR);
const auto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.GetColor();
}
// Routine Description:
@ -361,7 +364,7 @@ const std::vector<size_t> RenderData::GetPatternId(const COORD /*location*/) con
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.LookupAttributeColors(attr);
return gci.LookupAttributeColors(attr, _defaultForeground, _defaultBackground);
}
#pragma endregion

View file

@ -72,4 +72,8 @@ public:
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
const bool IsUiaDataInitialized() const noexcept override { return true; }
#pragma endregion
private:
COLORREF _defaultForeground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 7);
COLORREF _defaultBackground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 0);
};

View file

@ -123,6 +123,7 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION()
pScreen->_renderTarget);
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
pScreen->_textBuffer->GetCursor().SetColor(gci.GetCursorColor());
pScreen->_textBuffer->GetCursor().SetType(gci.GetCursorType());
const NTSTATUS status = pScreen->_InitializeOutputStateMachine();
@ -1629,6 +1630,29 @@ void SCREEN_INFORMATION::SetCursorInformation(const ULONG Size,
}
}
// Routine Description:
// - This routine sets the cursor color. Also updates the cursor information of
// this buffer's main buffer, if this buffer is an alt buffer.
// Arguments:
// - Color - The new color to set the cursor to
// - setMain - If true, propagate change to main buffer as well.
// Return Value:
// - None
void SCREEN_INFORMATION::SetCursorColor(const unsigned int Color, const bool setMain) noexcept
{
Cursor& cursor = _textBuffer->GetCursor();
cursor.SetColor(Color);
// If we're an alt buffer, DON'T propagate this setting up to the main buffer.
// We don't want to pollute that buffer with this state,
// UNLESS we're getting called from the propsheet, then we DO want to update this.
if (_psiMainBuffer && setMain)
{
_psiMainBuffer->SetCursorColor(Color);
}
}
// Routine Description:
// - This routine sets the cursor shape both in the data
// structures and on the screen. Also updates the cursor information of
@ -1884,7 +1908,7 @@ const SCREEN_INFORMATION& SCREEN_INFORMATION::GetMainBuffer() const
auto& myCursor = GetTextBuffer().GetCursor();
auto* const createdBuffer = *ppsiNewScreenBuffer;
auto& altCursor = createdBuffer->GetTextBuffer().GetCursor();
altCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
altCursor.SetStyle(myCursor.GetSize(), myCursor.GetColor(), myCursor.GetType());
altCursor.SetIsVisible(myCursor.IsVisible());
altCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
// The new position should match the viewport-relative position of the main buffer.
@ -1982,7 +2006,7 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
// Copy the alt buffer's cursor style and visibility back to the main buffer.
const auto& altCursor = psiAlt->GetTextBuffer().GetCursor();
auto& mainCursor = psiMain->GetTextBuffer().GetCursor();
mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetType());
mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetColor(), altCursor.GetType());
mainCursor.SetIsVisible(altCursor.IsVisible());
mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed());

View file

@ -189,6 +189,8 @@ public:
void SetCursorInformation(const ULONG Size,
const bool Visible) noexcept;
void SetCursorColor(const unsigned int Color, const bool setMain = false) noexcept;
void SetCursorType(const CursorType Type, const bool setMain = false) noexcept;
void SetCursorDBMode(const bool DoubleCursor);

View file

@ -16,6 +16,7 @@ Selection::Selection() :
_fSelectionVisible(false),
_ulSavedCursorSize(0),
_fSavedCursorVisible(false),
_savedCursorColor(INVALID_COLOR),
_savedCursorType(CursorType::Legacy),
_dwSelectionFlags(0),
_fLineSelection(true),

View file

@ -174,6 +174,7 @@ private:
COORD _coordSavedCursorPosition;
ULONG _ulSavedCursorSize;
bool _fSavedCursorVisible;
COLORREF _savedCursorColor;
CursorType _savedCursorType;
#ifdef UNIT_TESTING

View file

@ -168,6 +168,7 @@ void Selection::_SaveCursorData(const Cursor& cursor) noexcept
_coordSavedCursorPosition = cursor.GetPosition();
_ulSavedCursorSize = cursor.GetSize();
_fSavedCursorVisible = cursor.IsVisible();
_savedCursorColor = cursor.GetColor();
_savedCursorType = cursor.GetType();
}
@ -181,6 +182,7 @@ void Selection::_RestoreDataToCursor(Cursor& cursor) noexcept
{
cursor.SetSize(_ulSavedCursorSize);
cursor.SetIsVisible(_fSavedCursorVisible);
cursor.SetColor(_savedCursorColor);
cursor.SetType(_savedCursorType);
cursor.SetIsOn(true);
cursor.SetPosition(_coordSavedCursorPosition);

View file

@ -124,7 +124,10 @@ public:
COOKED_READ_DATA& CookedReadData() noexcept;
void SetCookedReadData(COOKED_READ_DATA* readData) noexcept;
COLORREF GetDefaultForeground() const noexcept;
COLORREF GetDefaultBackground() const noexcept;
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const noexcept;
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept;
void SetTitle(const std::wstring_view newTitle);
void SetTitlePrefix(const std::wstring_view newTitlePrefix);

View file

@ -56,8 +56,8 @@ Settings::Settings() :
_fScreenReversed(false),
// window size pixels initialized below
_fInterceptCopyPaste(0),
_defaultForegroundIndex(TextColor::DARK_WHITE),
_defaultBackgroundIndex(TextColor::DARK_BLACK),
_DefaultForeground(INVALID_COLOR),
_DefaultBackground(INVALID_COLOR),
_fUseDx(UseDx::Disabled),
_fCopyColor(false)
{
@ -78,14 +78,11 @@ Settings::Settings() :
ZeroMemory((void*)&_FaceName, sizeof(_FaceName));
wcscpy_s(_FaceName, DEFAULT_TT_FONT_FACENAME);
_CursorColor = Cursor::s_InvertCursorColor;
_CursorType = CursorType::Legacy;
gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
::Microsoft::Console::Utils::InitializeColorTable(tableView);
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = INVALID_COLOR;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = INVALID_COLOR;
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
}
// Routine Description:
@ -232,11 +229,11 @@ void Settings::InitFromStateInfo(_In_ PCONSOLE_STATE_INFO pStateInfo)
_fCtrlKeyShortcutsDisabled = pStateInfo->fCtrlKeyShortcutsDisabled;
_bLineSelection = pStateInfo->fLineSelection;
_bWindowAlpha = pStateInfo->bWindowTransparency;
_CursorColor = pStateInfo->CursorColor;
_CursorType = static_cast<CursorType>(pStateInfo->CursorType);
_fInterceptCopyPaste = pStateInfo->InterceptCopyPaste;
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = pStateInfo->DefaultForeground;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = pStateInfo->DefaultBackground;
_colorTable.at(TextColor::CURSOR_COLOR) = pStateInfo->CursorColor;
_DefaultForeground = pStateInfo->DefaultForeground;
_DefaultBackground = pStateInfo->DefaultBackground;
_TerminalScrolling = pStateInfo->TerminalScrolling;
}
@ -277,11 +274,11 @@ CONSOLE_STATE_INFO Settings::CreateConsoleStateInfo() const
csi.fCtrlKeyShortcutsDisabled = _fCtrlKeyShortcutsDisabled;
csi.fLineSelection = _bLineSelection;
csi.bWindowTransparency = _bWindowAlpha;
csi.CursorColor = _CursorColor;
csi.CursorType = static_cast<unsigned int>(_CursorType);
csi.InterceptCopyPaste = _fInterceptCopyPaste;
csi.DefaultForeground = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
csi.DefaultBackground = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
csi.CursorColor = _colorTable.at(TextColor::CURSOR_COLOR);
csi.DefaultForeground = _DefaultForeground;
csi.DefaultBackground = _DefaultBackground;
csi.TerminalScrolling = _TerminalScrolling;
return csi;
}
@ -333,22 +330,16 @@ void Settings::Validate()
WI_ClearAllFlags(_wFillAttribute, ~(FG_ATTRS | BG_ATTRS));
WI_ClearAllFlags(_wPopupFillAttribute, ~(FG_ATTRS | BG_ATTRS));
const auto defaultForeground = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
const auto defaultBackground = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
const auto cursorColor = _colorTable.at(TextColor::CURSOR_COLOR);
// If the extended color options are set to invalid values (all the same color), reset them.
if (cursorColor != INVALID_COLOR && cursorColor == defaultBackground)
if (_CursorColor != Cursor::s_InvertCursorColor && _CursorColor == _DefaultBackground)
{
// INVALID_COLOR is used to represent "Invert Colors"
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
_CursorColor = Cursor::s_InvertCursorColor;
}
if (defaultForeground != INVALID_COLOR && defaultForeground == defaultBackground)
if (_DefaultForeground != INVALID_COLOR && _DefaultForeground == _DefaultBackground)
{
// INVALID_COLOR is used as an "unset" sentinel in future attribute functions.
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = INVALID_COLOR;
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = INVALID_COLOR;
_DefaultForeground = _DefaultBackground = INVALID_COLOR;
// If the damaged settings _further_ propagated to the default fill attribute, fix it.
if (_wFillAttribute == 0)
{
@ -360,8 +351,6 @@ void Settings::Validate()
// At this point the default fill attributes are fully initialized
// so we can pass on the final colors to the TextAttribute class.
TextAttribute::SetLegacyDefaultAttributes(_wFillAttribute);
// And calculate the position of the default colors in the color table.
CalculateDefaultColorIndices();
FAIL_FAST_IF(!(_dwWindowSize.X > 0));
FAIL_FAST_IF(!(_dwWindowSize.Y > 0));
@ -771,11 +760,21 @@ COLORREF Settings::GetLegacyColorTableEntry(const size_t index) const
return _colorTable.at(TextColor::TransposeLegacyIndex(index));
}
COLORREF Settings::GetCursorColor() const noexcept
{
return _CursorColor;
}
CursorType Settings::GetCursorType() const noexcept
{
return _CursorType;
}
void Settings::SetCursorColor(const COLORREF CursorColor) noexcept
{
_CursorColor = CursorColor;
}
void Settings::SetCursorType(const CursorType cursorType) noexcept
{
_CursorType = cursorType;
@ -791,35 +790,24 @@ void Settings::SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept
_fInterceptCopyPaste = interceptCopyPaste;
}
void Settings::CalculateDefaultColorIndices() noexcept
COLORREF Settings::GetDefaultForegroundColor() const noexcept
{
const auto foregroundColor = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
const auto foregroundIndex = TextColor::TransposeLegacyIndex(_wFillAttribute & FG_ATTRS);
_defaultForegroundIndex = foregroundColor != INVALID_COLOR ? TextColor::DEFAULT_FOREGROUND : foregroundIndex;
const auto backgroundColor = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
const auto backgroundIndex = TextColor::TransposeLegacyIndex((_wFillAttribute & BG_ATTRS) >> 4);
_defaultBackgroundIndex = backgroundColor != INVALID_COLOR ? TextColor::DEFAULT_BACKGROUND : backgroundIndex;
return _DefaultForeground;
}
size_t Settings::GetDefaultForegroundIndex() const noexcept
void Settings::SetDefaultForegroundColor(const COLORREF defaultForeground) noexcept
{
return _defaultForegroundIndex;
_DefaultForeground = defaultForeground;
}
void Settings::SetDefaultForegroundIndex(const size_t index) noexcept
COLORREF Settings::GetDefaultBackgroundColor() const noexcept
{
_defaultForegroundIndex = index;
return _DefaultBackground;
}
size_t Settings::GetDefaultBackgroundIndex() const noexcept
void Settings::SetDefaultBackgroundColor(const COLORREF defaultBackground) noexcept
{
return _defaultBackgroundIndex;
}
void Settings::SetDefaultBackgroundIndex(const size_t index) noexcept
{
_defaultBackgroundIndex = index;
_DefaultBackground = defaultBackground;
}
bool Settings::IsTerminalScrolling() const noexcept

View file

@ -167,7 +167,7 @@ public:
void SetHistoryNoDup(const bool fHistoryNoDup);
// The first 16 items of the color table are the same as the 16-color palette.
inline const std::array<COLORREF, TextColor::TABLE_SIZE>& GetColorTable() const noexcept
inline const std::array<COLORREF, XTERM_COLOR_TABLE_SIZE>& GetColorTable() const noexcept
{
return _colorTable;
}
@ -177,17 +177,20 @@ public:
void SetLegacyColorTableEntry(const size_t index, const COLORREF ColorValue);
COLORREF GetLegacyColorTableEntry(const size_t index) const;
COLORREF GetCursorColor() const noexcept;
CursorType GetCursorType() const noexcept;
void SetCursorColor(const COLORREF CursorColor) noexcept;
void SetCursorType(const CursorType cursorType) noexcept;
bool GetInterceptCopyPaste() const noexcept;
void SetInterceptCopyPaste(const bool interceptCopyPaste) noexcept;
void CalculateDefaultColorIndices() noexcept;
size_t GetDefaultForegroundIndex() const noexcept;
void SetDefaultForegroundIndex(const size_t index) noexcept;
size_t GetDefaultBackgroundIndex() const noexcept;
void SetDefaultBackgroundIndex(const size_t index) noexcept;
COLORREF GetDefaultForegroundColor() const noexcept;
void SetDefaultForegroundColor(const COLORREF defaultForeground) noexcept;
COLORREF GetDefaultBackgroundColor() const noexcept;
void SetDefaultBackgroundColor(const COLORREF defaultBackground) noexcept;
bool IsTerminalScrolling() const noexcept;
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;
@ -239,19 +242,20 @@ private:
UseDx _fUseDx;
bool _fCopyColor;
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
// this is used for the special STARTF_USESIZE mode.
bool _fUseWindowSizePixels;
COORD _dwWindowSizePixels;
// Technically a COLORREF, but using INVALID_COLOR as "Invert Colors"
unsigned int _CursorColor;
CursorType _CursorType;
bool _fInterceptCopyPaste;
size_t _defaultForegroundIndex;
size_t _defaultBackgroundIndex;
COLORREF _DefaultForeground;
COLORREF _DefaultBackground;
bool _TerminalScrolling;
friend class RegistrySerialization;
};

View file

@ -67,10 +67,9 @@ class ConptyOutputTests
// Set up some sane defaults
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR);
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer();

View file

@ -59,10 +59,9 @@ class ScreenBufferTests
{
// Set up some sane defaults
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR);
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo();
auto& currentBuffer = gci.GetActiveOutputBuffer();
@ -360,11 +359,12 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
auto mainCursorPos = COORD{ 3, 5 };
auto mainCursorVisible = false;
auto mainCursorSize = 33u;
auto mainCursorColor = RGB(1, 2, 3);
auto mainCursorType = CursorType::DoubleUnderscore;
auto mainCursorBlinking = false;
mainCursor.SetPosition(mainCursorPos);
mainCursor.SetIsVisible(mainCursorVisible);
mainCursor.SetStyle(mainCursorSize, mainCursorType);
mainCursor.SetStyle(mainCursorSize, mainCursorColor, mainCursorType);
mainCursor.SetBlinkingAllowed(mainCursorBlinking);
Log::Comment(L"Switch to the alternate buffer.");
@ -379,6 +379,7 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
VERIFY_ARE_EQUAL(mainCursorVisible, altCursor.IsVisible());
Log::Comment(L"Confirm the cursor style is inherited from the main buffer.");
VERIFY_ARE_EQUAL(mainCursorSize, altCursor.GetSize());
VERIFY_ARE_EQUAL(mainCursorColor, altCursor.GetColor());
VERIFY_ARE_EQUAL(mainCursorType, altCursor.GetType());
VERIFY_ARE_EQUAL(mainCursorBlinking, altCursor.IsBlinkingAllowed());
@ -386,11 +387,12 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
auto altCursorPos = COORD{ 5, 3 };
auto altCursorVisible = true;
auto altCursorSize = 66u;
auto altCursorColor = RGB(3, 2, 1);
auto altCursorType = CursorType::EmptyBox;
auto altCursorBlinking = true;
altCursor.SetPosition(altCursorPos);
altCursor.SetIsVisible(altCursorVisible);
altCursor.SetStyle(altCursorSize, altCursorType);
altCursor.SetStyle(altCursorSize, altCursorColor, altCursorType);
altCursor.SetBlinkingAllowed(altCursorBlinking);
Log::Comment(L"Switch back to the main buffer.");
@ -404,6 +406,7 @@ void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
VERIFY_ARE_EQUAL(altCursorVisible, mainCursor.IsVisible());
Log::Comment(L"Confirm the cursor style is inherited from the alt buffer.");
VERIFY_ARE_EQUAL(altCursorSize, mainCursor.GetSize());
VERIFY_ARE_EQUAL(altCursorColor, mainCursor.GetColor());
VERIFY_ARE_EQUAL(altCursorType, mainCursor.GetType());
VERIFY_ARE_EQUAL(altCursorBlinking, mainCursor.IsBlinkingAllowed());
}
@ -1385,9 +1388,8 @@ void ScreenBufferTests::VtScrollMarginsNewlineColor()
const COLORREF yellow = RGB(255, 255, 0);
const COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultForegroundColor(yellow);
gci.SetDefaultBackgroundColor(magenta);
const TextAttribute defaultAttrs = {};
si.SetAttributes(defaultAttrs);
@ -1739,6 +1741,7 @@ void ScreenBufferTests::ResizeCursorUnchanged()
// Get initial cursor values
const CursorType initialType = initialCursor.GetType();
const auto initialSize = initialCursor.GetSize();
const COLORREF initialColor = initialCursor.GetColor();
// set our wrap mode accordingly - ResizeScreenBuffer will be smart enough
// to call the appropriate implementation
@ -1753,8 +1756,10 @@ void ScreenBufferTests::ResizeCursorUnchanged()
const auto& finalCursor = si.GetTextBuffer().GetCursor();
const CursorType finalType = finalCursor.GetType();
const auto finalSize = finalCursor.GetSize();
const COLORREF finalColor = finalCursor.GetColor();
VERIFY_ARE_EQUAL(initialType, finalType);
VERIFY_ARE_EQUAL(initialColor, finalColor);
VERIFY_ARE_EQUAL(initialSize, finalSize);
}
@ -2117,6 +2122,7 @@ void ScreenBufferTests::TestAltBufferCursorState()
// Validate that the cursor state was copied appropriately into the
// alternate buffer
VERIFY_ARE_EQUAL(mainCursor.GetSize(), altCursor.GetSize());
VERIFY_ARE_EQUAL(mainCursor.GetColor(), altCursor.GetColor());
VERIFY_ARE_EQUAL(mainCursor.GetType(), altCursor.GetType());
}
}
@ -2253,9 +2259,8 @@ void ScreenBufferTests::SetDefaultsIndividuallyBothDefault()
COLORREF brightGreen = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
COLORREF darkBlue = gci.GetColorTableEntry(TextColor::DARK_BLUE);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultForegroundColor(yellow);
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 6 X's:"));
@ -2356,9 +2361,8 @@ void ScreenBufferTests::SetDefaultsTogether()
COLORREF yellow = RGB(255, 255, 0);
COLORREF color250 = gci.GetColorTableEntry(250);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, yellow);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultForegroundColor(yellow);
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 6 X's:"));
@ -2428,9 +2432,8 @@ void ScreenBufferTests::ReverseResetWithDefaultBackground()
COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 3 X's:"));
@ -2498,8 +2501,7 @@ void ScreenBufferTests::BackspaceDefaultAttrs()
COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one."));
@ -2562,8 +2564,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsWriteCharsLegacy()
COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
Log::Comment(NoThrowString().Format(L"Write 2 X's, then backspace one."));
@ -2631,8 +2632,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsInPrompt()
COLORREF magenta = RGB(255, 0, 255);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, magenta);
gci.CalculateDefaultColorIndices();
gci.SetDefaultBackgroundColor(magenta);
si.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });
TextAttribute expectedDefaults{};
@ -2889,15 +2889,15 @@ void ScreenBufferTests::SetDefaultForegroundColor()
StateMachine& stateMachine = mainBuffer.GetStateMachine();
COLORREF originalColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
COLORREF newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
COLORREF originalColor = gci.GetDefaultForegroundColor();
COLORREF newColor = gci.GetDefaultForegroundColor();
COLORREF testColor = RGB(0x33, 0x66, 0x99);
VERIFY_ARE_NOT_EQUAL(originalColor, testColor);
Log::Comment(L"Valid Hexadecimal Notation");
stateMachine.ProcessString(L"\x1b]10;rgb:33/66/99\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
newColor = gci.GetDefaultForegroundColor();
VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Valid Hexadecimal Notation");
@ -2905,7 +2905,7 @@ void ScreenBufferTests::SetDefaultForegroundColor()
testColor = RGB(0xff, 0xff, 0xff);
stateMachine.ProcessString(L"\x1b]10;rgb:ff/ff/ff\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
newColor = gci.GetDefaultForegroundColor();
VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Invalid syntax");
@ -2913,7 +2913,7 @@ void ScreenBufferTests::SetDefaultForegroundColor()
testColor = RGB(153, 102, 51);
stateMachine.ProcessString(L"\x1b]10;99/66/33\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
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);
@ -2934,15 +2934,15 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
StateMachine& stateMachine = mainBuffer.GetStateMachine();
COLORREF originalColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
COLORREF newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
COLORREF originalColor = gci.GetDefaultBackgroundColor();
COLORREF newColor = gci.GetDefaultBackgroundColor();
COLORREF testColor = RGB(0x33, 0x66, 0x99);
VERIFY_ARE_NOT_EQUAL(originalColor, testColor);
Log::Comment(L"Valid Hexadecimal Notation");
stateMachine.ProcessString(L"\x1b]11;rgb:33/66/99\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
newColor = gci.GetDefaultBackgroundColor();
VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Valid Hexadecimal Notation");
@ -2950,7 +2950,7 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
testColor = RGB(0xff, 0xff, 0xff);
stateMachine.ProcessString(L"\x1b]11;rgb:ff/ff/ff\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
newColor = gci.GetDefaultBackgroundColor();
VERIFY_ARE_EQUAL(testColor, newColor);
Log::Comment(L"Invalid Syntax");
@ -2958,7 +2958,7 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
testColor = RGB(153, 102, 51);
stateMachine.ProcessString(L"\x1b]11;99/66/33\x1b\\");
newColor = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
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);

View file

@ -37,3 +37,4 @@ enum class CursorType : unsigned int
constexpr COLORREF INVALID_COLOR = 0xffffffff;
constexpr WORD COLOR_TABLE_SIZE = 16;
constexpr WORD XTERM_COLOR_TABLE_SIZE = 256;

View file

@ -3,136 +3,130 @@
#pragma once
#ifdef __cpp_concepts
#define TIL_ENUMSET_VARARG template<std::same_as<T>... Args>
#else
#define TIL_ENUMSET_VARARG template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<T, Args>...>>>
#endif
#include <bitset>
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
// til::enumset stores a fixed size array of boolean elements, the positions
// in the array being identified by values from a given enumerated type.
// Position N corresponds to bit 1<<N in the UnderlyingType integer.
//
// If you only need 32 positions for your T, UnderlyingType can be set uint32_t.
// It defaults to uintptr_t allowing you to set as many positions as a pointer has bits.
// This class doesn't statically assert that your given position fits into UnderlyingType.
template<typename T, typename UnderlyingType = uintptr_t>
class enumset
// By design, this class hides several methods in the std::bitset class
// so they can be called with an enum parameter instead of a size_t, so
// we need to disable the "hides a non-virtual function" warning.
#pragma warning(push)
#pragma warning(disable : 26434)
// til::enumset is a subclass of std::bitset, storing a fixed size array of
// boolean elements, the positions in the array being identified by values
// from a given enumerated type. By default it holds the same number of
// bits as a size_t value.
template<typename Type, size_t Bits = std::numeric_limits<size_t>::digits>
class enumset : public std::bitset<Bits>
{
static_assert(std::is_unsigned_v<UnderlyingType>);
using _base = std::bitset<Bits>;
public:
using reference = typename _base::reference;
enumset() = default;
// Method Description:
// - Constructs a new bitset with the given list of positions set to true.
TIL_ENUMSET_VARARG
constexpr enumset(Args... positions) noexcept :
_data{ to_underlying(positions...) }
template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
constexpr enumset(const Args... positions) noexcept :
_base((... | (1ULL << static_cast<size_t>(positions))))
{
}
// Method Description:
// - Returns the underlying bit positions as a copy.
constexpr UnderlyingType bits() const noexcept
// - Returns the value of the bit at the given position.
constexpr bool operator[](const Type pos) const
{
return _data;
return _base::operator[](static_cast<size_t>(pos));
}
// Method Description:
// - Returns a reference to the bit at the given position.
reference operator[](const Type pos)
{
return _base::operator[](static_cast<size_t>(pos));
}
// Method Description:
// - Returns the value of the bit at the given position.
// Throws std::out_of_range if it is not a valid position
// in the bitset.
constexpr bool test(const T pos) const noexcept
bool test(const Type pos) const
{
const auto mask = to_underlying(pos);
return (_data & mask) != 0;
return _base::test(static_cast<size_t>(pos));
}
// Method Description:
// - Returns true if any of the bits are set to true.
constexpr bool any() const noexcept
bool any() const noexcept
{
return _data != 0;
return _base::any();
}
// Method Description:
// - Returns true if any of the bits in the given positions are true.
TIL_ENUMSET_VARARG
constexpr bool any(Args... positions) const noexcept
template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
bool any(const Args... positions) const noexcept
{
const auto mask = to_underlying(positions...);
return (_data & mask) != 0;
return (enumset{ positions... } & *this) != 0;
}
// Method Description:
// - Returns true if all of the bits are set to true.
constexpr bool all() const noexcept
bool all() const noexcept
{
return _data == ~UnderlyingType{ 0 };
return _base::all();
}
// Method Description:
// - Returns true if all of the bits in the given positions are true.
TIL_ENUMSET_VARARG
constexpr bool all(Args... positions) const noexcept
template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Type, Args>...>>>
bool all(const Args... positions) const noexcept
{
const auto mask = to_underlying(positions...);
return (_data & mask) == mask;
}
// Method Description:
// - Sets all of the bits in the given positions to true.
TIL_ENUMSET_VARARG
constexpr enumset& set(Args... positions) noexcept
{
_data |= to_underlying(positions...);
return *this;
return (enumset{ positions... } & *this) == enumset{ positions... };
}
// Method Description:
// - Sets the bit in the given position to the specified value.
constexpr enumset& set(const T pos, const bool val) noexcept
enumset& set(const Type pos, const bool val = true)
{
const auto mask = to_underlying(pos);
// false == 0 --> UnderlyingType(-0) == 0b0000...
// true == 1 --> UnderlyingType(-1) == 0b1111...
#pragma warning(suppress : 4804) // '-': unsafe use of type 'bool' in operation
_data = (_data & ~mask) | (-val & mask);
_base::set(static_cast<size_t>(pos), val);
return *this;
}
// Method Description:
// - Resets all of the bits in the given positions to false.
TIL_ENUMSET_VARARG
constexpr enumset& reset(Args... positions) noexcept
// - Resets the bit in the given position to false.
enumset& reset(const Type pos)
{
_data &= ~to_underlying(positions...);
_base::reset(static_cast<size_t>(pos));
return *this;
}
// Method Description:
// - Flips the bit at the given position.
TIL_ENUMSET_VARARG
constexpr enumset& flip(Args... positions) noexcept
enumset& flip(const Type pos)
{
_data ^= to_underlying(positions...);
_base::flip(static_cast<size_t>(pos));
return *this;
}
private:
// Method Description:
// - Sets all of the bits in the given positions to true.
template<typename... Args>
static constexpr UnderlyingType to_underlying(Args... positions) noexcept
enumset& set_all(const Args... positions)
{
return ((UnderlyingType{ 1 } << static_cast<UnderlyingType>(positions)) | ...);
return (..., set(positions));
}
template<>
static constexpr UnderlyingType to_underlying() noexcept
// Method Description:
// - Resets all of the bits in the given positions to false.
template<typename... Args>
enumset& reset_all(const Args... positions)
{
return 0;
return (..., reset(positions));
}
UnderlyingType _data{};
};
#pragma warning(pop)
}

View file

@ -208,8 +208,10 @@ void Clipboard::StoreSelectionToClipboard(bool const copyFormatting)
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& buffer = gci.GetActiveOutputBuffer().GetTextBuffer();
const auto defaultForeground = gci.GetDefaultForeground();
const auto defaultBackground = gci.GetDefaultBackground();
const auto GetAttributeColors = [=, &gci](const auto& attr) {
return gci.LookupAttributeColors(attr);
return gci.LookupAttributeColors(attr, defaultForeground, defaultBackground);
};
bool includeCRLF, trimTrailingWhitespace;
@ -274,10 +276,9 @@ void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows,
if (fAlsoCopyFormatting)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& fontData = gci.GetActiveOutputBuffer().GetCurrentFont();
const auto& fontData = ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetCurrentFont();
int const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi;
const COLORREF bgColor = gci.GetColorTableEntry(gci.GetDefaultBackgroundIndex());
const COLORREF bgColor = ServiceLocator::LocateGlobals().getConsoleInformation().GetDefaultBackground();
std::string HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
CopyToSystemClipboard(HTMLToPlaceOnClip, L"HTML Format");

View file

@ -315,7 +315,7 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
const Cursor& cursor = ScreenInfo.GetTextBuffer().GetCursor();
pStateInfo->CursorSize = cursor.GetSize();
pStateInfo->CursorColor = gci.GetColorTableEntry(TextColor::CURSOR_COLOR);
pStateInfo->CursorColor = cursor.GetColor();
pStateInfo->CursorType = static_cast<unsigned int>(cursor.GetType());
// Retrieve small icon for use in displaying the dialog
@ -376,8 +376,8 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
pStateInfo->InterceptCopyPaste = gci.GetInterceptCopyPaste();
// Get the properties from the settings
pStateInfo->DefaultForeground = gci.GetColorTableEntry(TextColor::DEFAULT_FOREGROUND);
pStateInfo->DefaultBackground = gci.GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
pStateInfo->DefaultForeground = gci.GetDefaultForegroundColor();
pStateInfo->DefaultBackground = gci.GetDefaultBackgroundColor();
pStateInfo->TerminalScrolling = gci.IsTerminalScrolling();
// end console v2 properties
@ -461,12 +461,13 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
// Set the cursor properties in the Settings
const auto cursorType = static_cast<CursorType>(pStateInfo->CursorType);
gci.SetCursorColor(pStateInfo->CursorColor);
gci.SetCursorType(cursorType);
gci.SetColorTableEntry(TextColor::CURSOR_COLOR, pStateInfo->CursorColor);
// Then also apply them to the buffer's cursor
ScreenInfo.SetCursorInformation(pStateInfo->CursorSize,
ScreenInfo.GetTextBuffer().GetCursor().IsVisible());
ScreenInfo.SetCursorColor(pStateInfo->CursorColor, true);
ScreenInfo.SetCursorType(cursorType, true);
gci.SetTerminalScrolling(pStateInfo->TerminalScrolling);
@ -578,13 +579,11 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
gci.SetFillAttribute(pStateInfo->ScreenAttributes);
gci.SetPopupFillAttribute(pStateInfo->PopupAttributes);
// Store our updated Default Color values
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, pStateInfo->DefaultForeground);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, pStateInfo->DefaultBackground);
gci.SetDefaultForegroundColor(pStateInfo->DefaultForeground);
gci.SetDefaultBackgroundColor(pStateInfo->DefaultBackground);
// Make sure the updated fill attributes are passed on to the TextAttribute class.
TextAttribute::SetLegacyDefaultAttributes(pStateInfo->ScreenAttributes);
// And recalculate the position of the default colors in the color table.
gci.CalculateDefaultColorIndices();
// Set the screen info's default text attributes to defaults -
ScreenInfo.SetDefaultAttributes({}, TextAttribute{ gci.GetPopupFillAttribute() });

View file

@ -78,10 +78,8 @@
<AdditionalIncludeDirectories>$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<!-- If you don't include a '.' at the end of the $(IntermediateOutputPath),
mc.exe will get confused by the trailing slash. -->
<Target Name="MessageCompile" Inputs="@(MessageCompile)" Outputs="$(IntermediateOutputPath)\%(MessageCompile.Filename).h" BeforeTargets="ClCompile">
<Exec Command="mc.exe /h &quot;$(IntermediateOutputPath).&quot; /r &quot;$(IntermediateOutputPath).&quot; @(MessageCompile)" />
<Exec Command="mc.exe /h $(IntermediateOutputPath) /r $(IntermediateOutputPath) @(MessageCompile)" />
</Target>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="..\common.build.post.props" />

View file

@ -7,7 +7,7 @@
#pragma hdrstop
#define SET_FIELD_AND_SIZE(x) UFIELD_OFFSET(Settings, x), RTL_FIELD_SIZE(Settings, x)
#define SET_FIELD_AND_SIZE(x) FIELD_OFFSET(Settings, x), RTL_FIELD_SIZE(Settings, x)
#define NT_TESTNULL(var) (((var) == nullptr) ? STATUS_NO_MEMORY : STATUS_SUCCESS)
@ -57,14 +57,14 @@ const RegistrySerialization::_RegPropertyMap RegistrySerialization::s_PropertyMa
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TRIMZEROHEADINGS, SET_FIELD_AND_SIZE(_fTrimLeadingZeros) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_ENABLE_COLOR_SELECTION, SET_FIELD_AND_SIZE(_fEnableColorSelection) },
{ _RegPropertyType::Coordinate, CONSOLE_REGISTRY_WINDOWPOS, SET_FIELD_AND_SIZE(_dwWindowOrigin) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORCOLOR, SET_FIELD_AND_SIZE(_CursorColor) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORTYPE, SET_FIELD_AND_SIZE(_CursorType) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_INTERCEPTCOPYPASTE, SET_FIELD_AND_SIZE(_fInterceptCopyPaste) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_DefaultForeground) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_DefaultBackground) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_colorTable[TextColor::DEFAULT_FOREGROUND]) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_colorTable[TextColor::DEFAULT_BACKGROUND]) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORCOLOR, SET_FIELD_AND_SIZE(_colorTable[TextColor::CURSOR_COLOR]) }
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) }
};
const size_t RegistrySerialization::s_PropertyMappingsSize = ARRAYSIZE(s_PropertyMappings);

View file

@ -2250,7 +2250,7 @@ bool AdaptDispatch::SetCursorColor(const COLORREF cursorColor)
return false;
}
return _pConApi->SetColorTableEntry(TextColor::CURSOR_COLOR, cursorColor);
return _pConApi->SetCursorColor(cursorColor);
}
// Routine Description:
@ -2273,7 +2273,7 @@ bool AdaptDispatch::SetClipboard(const std::wstring_view /*content*/) noexcept
// True if handled successfully. False otherwise.
bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor)
{
const bool success = _pConApi->SetColorTableEntry(tableIndex, dwColor);
const bool success = _pConApi->PrivateSetColorTableEntry(tableIndex, dwColor);
// If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use
@ -2293,10 +2293,10 @@ bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwCo
// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::SetDefaultForeground(const DWORD dwColor)
bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultForeground(const DWORD dwColor)
{
bool success = true;
success = _pConApi->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, dwColor);
success = _pConApi->PrivateSetDefaultForeground(dwColor);
// If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use
@ -2316,10 +2316,10 @@ bool AdaptDispatch::SetDefaultForeground(const DWORD dwColor)
// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// True if handled successfully. False otherwise.
bool AdaptDispatch::SetDefaultBackground(const DWORD dwColor)
bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultBackground(const DWORD dwColor)
{
bool success = true;
success = _pConApi->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, dwColor);
success = _pConApi->PrivateSetDefaultBackground(dwColor);
// If we're a conpty, always return false, so that we send the updated color
// value to the terminal. Still handle the sequence so apps that use

View file

@ -72,6 +72,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool PrivateClearBuffer() = 0;
virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0;
virtual bool SetCursorStyle(const CursorType style) = 0;
virtual bool SetCursorColor(const COLORREF color) = 0;
virtual bool PrivateWriteConsoleControlInput(const KeyEvent key) = 0;
virtual bool PrivateRefreshWindow() = 0;
@ -86,8 +87,10 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool MoveToBottom() const = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) = 0;
virtual bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const = 0;
virtual bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const = 0;
virtual bool PrivateSetDefaultForeground(const COLORREF value) const = 0;
virtual bool PrivateSetDefaultBackground(const COLORREF value) const = 0;
virtual bool PrivateFillRegion(const COORD startPosition,
const size_t fillLength,

View file

@ -370,6 +370,16 @@ public:
return _setCursorStyleResult;
}
bool SetCursorColor(const COLORREF cursorColor) override
{
Log::Comment(L"SetCursorColor MOCK called...");
if (_setCursorColorResult)
{
VERIFY_ARE_EQUAL(_expectedCursorColor, cursorColor);
}
return _setCursorColorResult;
}
bool PrivateRefreshWindow() override
{
Log::Comment(L"PrivateRefreshWindow MOCK called...");
@ -428,31 +438,53 @@ public:
return _moveToBottomResult;
}
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override
bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept override
{
Log::Comment(L"GetColorTableEntry MOCK called...");
Log::Comment(L"PrivateGetColorTableEntry MOCK called...");
if (_getColorTableEntryResult)
if (_privateGetColorTableEntryResult)
{
VERIFY_ARE_EQUAL(_expectedColorTableIndex, tableIndex);
VERIFY_ARE_EQUAL(_expectedColorTableIndex, index);
// Simply returning the index as the color value makes it easy for
// tests to confirm that they've received the color they expected.
return gsl::narrow_cast<COLORREF>(tableIndex);
value = gsl::narrow_cast<COLORREF>(index);
}
return INVALID_COLOR;
return _privateGetColorTableEntryResult;
}
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override
bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept override
{
Log::Comment(L"SetColorTableEntry MOCK called...");
if (_setColorTableEntryResult)
Log::Comment(L"PrivateSetColorTableEntry MOCK called...");
if (_privateSetColorTableEntryResult)
{
VERIFY_ARE_EQUAL(_expectedColorTableIndex, tableIndex);
VERIFY_ARE_EQUAL(_expectedColorValue, color);
VERIFY_ARE_EQUAL(_expectedColorTableIndex, index);
VERIFY_ARE_EQUAL(_expectedColorValue, value);
}
return _setColorTableEntryResult;
return _privateSetColorTableEntryResult;
}
bool PrivateSetDefaultForeground(const COLORREF value) const noexcept override
{
Log::Comment(L"PrivateSetDefaultForeground MOCK called...");
if (_privateSetDefaultForegroundResult)
{
VERIFY_ARE_EQUAL(_expectedDefaultForegroundColorValue, value);
}
return _privateSetDefaultForegroundResult;
}
bool PrivateSetDefaultBackground(const COLORREF value) const noexcept override
{
Log::Comment(L"PrivateSetDefaultForeground MOCK called...");
if (_privateSetDefaultBackgroundResult)
{
VERIFY_ARE_EQUAL(_expectedDefaultBackgroundColorValue, value);
}
return _privateSetDefaultBackgroundResult;
}
bool PrivateFillRegion(const COORD /*startPosition*/,
@ -707,15 +739,23 @@ public:
std::wstring_view _expectedWindowTitle{};
bool _setCursorStyleResult = false;
CursorType _expectedCursorStyle;
bool _setCursorColorResult = false;
COLORREF _expectedCursorColor = 0;
bool _setConsoleOutputCPResult = false;
bool _getConsoleOutputCPResult = false;
bool _moveToBottomResult = false;
bool _getColorTableEntryResult = false;
bool _setColorTableEntryResult = false;
bool _privateGetColorTableEntryResult = false;
bool _privateSetColorTableEntryResult = false;
size_t _expectedColorTableIndex = SIZE_MAX;
COLORREF _expectedColorValue = INVALID_COLOR;
bool _privateSetDefaultForegroundResult = false;
COLORREF _expectedDefaultForegroundColorValue = INVALID_COLOR;
bool _privateSetDefaultBackgroundResult = false;
COLORREF _expectedDefaultBackgroundColorValue = INVALID_COLOR;
SIZE _expectedCellSize = {};
private:
@ -2266,7 +2306,7 @@ public:
VTParameter rgOptions[16];
size_t cOptions = 3;
_testGetSet->_getColorTableEntryResult = true;
_testGetSet->_privateGetColorTableEntryResult = true;
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
Log::Comment(L"Test 1: Change Foreground");
@ -2316,7 +2356,7 @@ public:
VTParameter rgOptions[16];
_testGetSet->_getColorTableEntryResult = true;
_testGetSet->_privateGetColorTableEntryResult = true;
_testGetSet->_expectedAttribute = _testGetSet->_attribute;
Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter");
@ -2359,7 +2399,7 @@ public:
{
_testGetSet->PrepData();
_testGetSet->_setColorTableEntryResult = true;
_testGetSet->_privateSetColorTableEntryResult = true;
const auto testColor = RGB(1, 2, 3);
_testGetSet->_expectedColorValue = testColor;
@ -2369,7 +2409,7 @@ public:
VERIFY_IS_TRUE(_pDispatch.get()->SetColorTableEntry(i, testColor));
}
// Test in pty mode - we should fail, but SetColorTableEntry should still be called
// Test in pty mode - we should fail, but PrivateSetColorTableEntry should still be called
_testGetSet->_isPty = true;
_testGetSet->_expectedColorTableIndex = 15; // Windows BRIGHT_WHITE

View file

@ -542,7 +542,7 @@ std::wstring TerminalInput::_GenerateSGRSequence(const COORD position,
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the alternate buffer is active and alternate scroll mode is enabled and the event is a mouse wheel event.
bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept
bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const short delta) const
{
return _mouseInputState.inAlternateBuffer &&
_inputMode.test(Mode::AlternateScroll) &&
@ -555,7 +555,7 @@ bool TerminalInput::_ShouldSendAlternateScroll(const unsigned int button, const
// - delta: The scroll wheel delta of the input event
// Return value:
// True iff the input sequence was sent successfully.
bool TerminalInput::_SendAlternateScroll(const short delta) const noexcept
bool TerminalInput::_SendAlternateScroll(const short delta) const
{
if (delta > 0)
{

View file

@ -250,13 +250,13 @@ const wchar_t* const CTRL_QUESTIONMARK_SEQUENCE = L"\x7F";
const wchar_t* const CTRL_ALT_SLASH_SEQUENCE = L"\x1b\x1f";
const wchar_t* const CTRL_ALT_QUESTIONMARK_SEQUENCE = L"\x1b\x7F";
void TerminalInput::SetInputMode(const Mode mode, const bool enabled) noexcept
void TerminalInput::SetInputMode(const Mode mode, const bool enabled)
{
// If we're changing a tracking mode, we always clear other tracking modes first.
// We also clear out the last saved mouse position & button.
if (mode == Mode::DefaultMouseTracking || mode == Mode::ButtonEventMouseTracking || mode == Mode::AnyEventMouseTracking)
{
_inputMode.reset(Mode::DefaultMouseTracking, Mode::ButtonEventMouseTracking, Mode::AnyEventMouseTracking);
_inputMode.reset_all(Mode::DefaultMouseTracking, Mode::ButtonEventMouseTracking, Mode::AnyEventMouseTracking);
_mouseInputState.lastPos = { -1, -1 };
_mouseInputState.lastButton = 0;
}
@ -265,13 +265,13 @@ void TerminalInput::SetInputMode(const Mode mode, const bool enabled) noexcept
// when enabling a new encoding - not when disabling.
if ((mode == Mode::Utf8MouseEncoding || mode == Mode::SgrMouseEncoding) && enabled)
{
_inputMode.reset(Mode::Utf8MouseEncoding, Mode::SgrMouseEncoding);
_inputMode.reset_all(Mode::Utf8MouseEncoding, Mode::SgrMouseEncoding);
}
_inputMode.set(mode, enabled);
}
bool TerminalInput::GetInputMode(const Mode mode) const noexcept
bool TerminalInput::GetInputMode(const Mode mode) const
{
return _inputMode.test(mode);
}

View file

@ -52,8 +52,8 @@ namespace Microsoft::Console::VirtualTerminal
AlternateScroll
};
void SetInputMode(const Mode mode, const bool enabled) noexcept;
bool GetInputMode(const Mode mode) const noexcept;
void SetInputMode(const Mode mode, const bool enabled);
bool GetInputMode(const Mode mode) const;
void ForceDisableWin32InputMode(const bool win32InputMode) noexcept;
#pragma region MouseInput
@ -127,8 +127,8 @@ namespace Microsoft::Console::VirtualTerminal
const short modifierKeyState,
const short delta);
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept;
bool _SendAlternateScroll(const short delta) const noexcept;
bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const;
bool _SendAlternateScroll(const short delta) const;
static constexpr unsigned int s_GetPressedButton(const MouseButtonState state) noexcept;
#pragma endregion

View file

@ -23,12 +23,12 @@ StateMachine::StateMachine(std::unique_ptr<IStateMachineEngine> engine) :
_ActionClear();
}
void StateMachine::SetParserMode(const Mode mode, const bool enabled) noexcept
void StateMachine::SetParserMode(const Mode mode, const bool enabled)
{
_parserMode.set(mode, enabled);
}
bool StateMachine::GetParserMode(const Mode mode) const noexcept
bool StateMachine::GetParserMode(const Mode mode) const
{
return _parserMode.test(mode);
}

View file

@ -48,8 +48,8 @@ namespace Microsoft::Console::VirtualTerminal
Ansi,
};
void SetParserMode(const Mode mode, const bool enabled) noexcept;
bool GetParserMode(const Mode mode) const noexcept;
void SetParserMode(const Mode mode, const bool enabled);
bool GetParserMode(const Mode mode) const;
void ProcessCharacter(const wchar_t wch);
void ProcessString(const std::wstring_view string);

View file

@ -24,19 +24,19 @@ class EnumSetTests
{
Log::Comment(L"Default constructor with no bits set");
til::enumset<Flags> flags;
VERIFY_ARE_EQUAL(0b00000u, flags.bits());
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
}
{
Log::Comment(L"Constructor with bit 3 set");
til::enumset<Flags> flags{ Flags::Three };
VERIFY_ARE_EQUAL(0b01000u, flags.bits());
VERIFY_ARE_EQUAL(0b01000u, flags.to_ulong());
}
{
Log::Comment(L"Constructor with bits 0, 2, and 4 set");
til::enumset<Flags> flags{ Flags::Zero, Flags::Two, Flags::Four };
VERIFY_ARE_EQUAL(0b10101u, flags.bits());
VERIFY_ARE_EQUAL(0b10101u, flags.to_ulong());
}
}
@ -53,39 +53,39 @@ class EnumSetTests
Log::Comment(L"Start with no bits set");
til::enumset<Flags> flags;
VERIFY_ARE_EQUAL(0b00000u, flags.bits());
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
Log::Comment(L"Set bit 2 to true");
flags.set(Flags::Two);
VERIFY_ARE_EQUAL(0b00100u, flags.bits());
VERIFY_ARE_EQUAL(0b00100u, flags.to_ulong());
Log::Comment(L"Flip bit 4 to true");
flags.flip(Flags::Four);
VERIFY_ARE_EQUAL(0b10100u, flags.bits());
VERIFY_ARE_EQUAL(0b10100u, flags.to_ulong());
Log::Comment(L"Set bit 0 to true");
flags.set(Flags::Zero, true);
VERIFY_ARE_EQUAL(0b10101u, flags.bits());
flags.set(Flags::Zero);
VERIFY_ARE_EQUAL(0b10101u, flags.to_ulong());
Log::Comment(L"Reset bit 2 to false, leaving 0 and 4 true");
flags.reset(Flags::Two);
VERIFY_ARE_EQUAL(0b10001u, flags.bits());
VERIFY_ARE_EQUAL(0b10001u, flags.to_ulong());
Log::Comment(L"Set bit 0 to false, leaving 4 true");
flags.set(Flags::Zero, false);
VERIFY_ARE_EQUAL(0b10000u, flags.bits());
VERIFY_ARE_EQUAL(0b10000u, flags.to_ulong());
Log::Comment(L"Flip bit 4, leaving all bits false ");
flags.flip(Flags::Four);
VERIFY_ARE_EQUAL(0b00000u, flags.bits());
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
Log::Comment(L"Set bits 0, 3, and 2");
flags.set(Flags::Zero, Flags::Three, Flags::Two);
VERIFY_ARE_EQUAL(0b01101u, flags.bits());
flags.set_all(Flags::Zero, Flags::Three, Flags::Two);
VERIFY_ARE_EQUAL(0b01101u, flags.to_ulong());
Log::Comment(L"Reset bits 3, 4 (already reset), and 0, leaving 2 true");
flags.reset(Flags::Three, Flags::Four, Flags::Zero);
VERIFY_ARE_EQUAL(0b00100u, flags.bits());
flags.reset_all(Flags::Three, Flags::Four, Flags::Zero);
VERIFY_ARE_EQUAL(0b00100u, flags.to_ulong());
}
TEST_METHOD(TestMethods)
@ -101,13 +101,15 @@ class EnumSetTests
Log::Comment(L"Start with bits 0, 2, and 4 set");
til::enumset<Flags> flags{ Flags::Zero, Flags::Two, Flags::Four };
VERIFY_ARE_EQUAL(0b10101u, flags.bits());
VERIFY_ARE_EQUAL(0b10101u, flags.to_ulong());
Log::Comment(L"Test bits 1 through 4 with the test method");
Log::Comment(L"Test bits 1 and 2 with the test method");
VERIFY_IS_FALSE(flags.test(Flags::One));
VERIFY_IS_TRUE(flags.test(Flags::Two));
VERIFY_IS_FALSE(flags.test(Flags::Three));
VERIFY_IS_TRUE(flags.test(Flags::Four));
Log::Comment(L"Test bit 3 and 4 with the array operator");
VERIFY_IS_FALSE(flags[Flags::Three]);
VERIFY_IS_TRUE(flags[Flags::Four]);
Log::Comment(L"Test if any bits are set");
VERIFY_IS_TRUE(flags.any());
@ -123,4 +125,45 @@ class EnumSetTests
Log::Comment(L"Test if both bits 0 and 3 are set");
VERIFY_IS_FALSE(flags.all(Flags::Zero, Flags::Three));
}
TEST_METHOD(ArrayReferenceOperator)
{
enum class Flags
{
Zero,
One,
Two,
Three,
Four
};
Log::Comment(L"Start with no bits set");
til::enumset<Flags> flags;
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
Log::Comment(L"Test bit 3 reference is false");
auto reference = flags[Flags::Three];
VERIFY_IS_FALSE(reference);
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
Log::Comment(L"Set bit 3 reference to true");
flags.set(Flags::Three);
VERIFY_IS_TRUE(reference);
VERIFY_ARE_EQUAL(0b01000u, flags.to_ulong());
Log::Comment(L"Reset bit 3 reference to false");
flags.reset(Flags::Three);
VERIFY_IS_FALSE(reference);
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
Log::Comment(L"Flip bit 3 reference to true");
reference.flip();
VERIFY_IS_TRUE(reference);
VERIFY_ARE_EQUAL(0b01000u, flags.to_ulong());
Log::Comment(L"Flip bit 3 reference back to false");
reference.flip();
VERIFY_IS_FALSE(reference);
VERIFY_ARE_EQUAL(0b00000u, flags.to_ulong());
}
};

View file

@ -23,16 +23,6 @@ set PATH=%PATH%%OPENCON%\dep\nuget;
rem Run nuget restore so you can use vswhere
nuget restore %OPENCON%\OpenConsole.sln -Verbosity quiet
:FIND_MSBUILD
set MSBUILD=
rem GH#1313: If msbuild is already on the path, we don't need to look for it.
for %%X in (msbuild.exe) do (set MSBUILD=%%~$PATH:X)
if defined MSBUILD (
echo Using MsBuild at %MSBUILD% which was already on the path.
goto :FOUND_MSBUILD
)
rem Find vswhere
rem from https://github.com/microsoft/vs-setup-samples/blob/master/tools/vswhere.cmd
for /f "usebackq delims=" %%I in (`dir /b /aD /o-N /s "%~dp0..\packages\vswhere*" 2^>nul`) do (
@ -47,23 +37,22 @@ if not defined VSWHERE (
)
rem Add path to MSBuild Binaries
rem
rem We're going to always prefer prerelease version of VS. This lets people who
rem are using VS 2022 use that from the commandline over the 2019 version. This
rem will use whatever the newest version of VS is, regardless if it's stable or
rem not.
rem
for /f "usebackq tokens=*" %%B in (`%VSWHERE% -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe 2^>nul`) do (
for /f "usebackq tokens=*" %%B in (`%VSWHERE% -latest -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe 2^>nul`) do (
set MSBUILD=%%B
)
rem Try to find MSBuild in prerelease versions of MSVS
if not defined MSBUILD (
for /f "usebackq tokens=*" %%B in (`%VSWHERE% -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe 2^>nul`) do (
set MSBUILD=%%B
)
)
if not defined MSBUILD (
echo Could not find MsBuild on your machine. Please set the MSBUILD variable to the location of MSBuild.exe and run razzle again.
goto :EXIT
)
:FOUND_MSBUILD
set PATH=%PATH%%MSBUILD%\..;
if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (