diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000000..bf0e54a56b8
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* -text
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000000..4071eab2408
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,245 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+objfre/
+objchk/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+
+# Visual Studio Code cache/options directory
+.vscode/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
+*.opendb
+*.db
+
+# Windows Build System files
+build*.dbb
+build*.err
+build*.evt
+build*.log
+build*.prf
+build*.trc
+build*.rec
+build*.wrn
+build*.metadata
+
+# .razzlerc.cmd file - used by dev environment
+tools/.razzlerc.*
+# message compiler output
+MSG*.bin
+/*.exe
+
+# python
+*.pyc
+
+**Generated Files/
+**/Merged/*
+**/Unmerged/*
+profiles.json
+*.metaproj
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000000..29473197807
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "dep/gsl"]
+ path = dep/gsl
+ url = https://github.com/Microsoft/gsl
+[submodule "dep/wil"]
+ path = dep/wil
+ url = https://github.com/Microsoft/wil
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000000..017b9885a46
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 00000000000..01bacfe553d
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenConsole.sln b/OpenConsole.sln
new file mode 100644
index 00000000000..8ca6a8c45f8
--- /dev/null
+++ b/OpenConsole.sln
@@ -0,0 +1,1164 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27004.2008
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.EXE", "src\host\exe\Host.EXE.vcxproj", "{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropertiesLibrary", "src\propslib\propslib.vcxproj", "{345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Dependencies", "_Dependencies", "{81C352DB-1818-45B7-A284-18E259F1CC87}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wil", "wil", "{4C8E6BB0-4713-4ADB-BD04-81628ECEAF20}"
+ ProjectSection(SolutionItems) = preProject
+ dep\wil\include\wil\common.h = dep\wil\include\wil\common.h
+ dep\wil\include\wil\filesystem.h = dep\wil\include\wil\filesystem.h
+ dep\wil\include\wil\functional.h = dep\wil\include\wil\functional.h
+ dep\wil\include\wil\registry.h = dep\wil\include\wil\registry.h
+ dep\wil\include\wil\resource.h = dep\wil\include\wil\resource.h
+ dep\wil\include\wil\result.h = dep\wil\include\wil\result.h
+ dep\wil\include\wil\resultmacros.h = dep\wil\include\wil\resultmacros.h
+ dep\wil\include\wil\stl.h = dep\wil\include\wil\stl.h
+ dep\wil\include\wil\win32helpers.h = dep\wil\include\wil\win32helpers.h
+ dep\wil\include\wil\wistd_functional.h = dep\wil\include\wil\wistd_functional.h
+ dep\wil\include\wil\wistd_memory.h = dep\wil\include\wil\wistd_memory.h
+ dep\wil\include\wil\wistd_type_traits.h = dep\wil\include\wil\wistd_type_traits.h
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Console", "Console", "{D57841D1-8294-4F2B-BB8B-D2A35738DECD}"
+ ProjectSection(SolutionItems) = preProject
+ dep\Console\winconp.h = dep\Console\winconp.h
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextServicesFramework", "src\tsf\tsf.vcxproj", "{2FD12FBB-1DDB-46D8-B818-1023C624CACA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser", "src\terminal\parser\lib\parser.vcxproj", "{3AE13314-1939-4DFA-9C14-38CA0834050C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAdapter", "src\terminal\adapter\lib\adapter.vcxproj", "{DCF55140-EF6A-4736-A403-957E4F7430BB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalInput", "src\terminal\input\lib\terminalinput.vcxproj", "{1CF55140-EF6A-4736-A403-957E4F7430BB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererBase", "src\renderer\base\lib\base.vcxproj", "{AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererGdi", "src\renderer\gdi\lib\gdi.vcxproj", "{1C959542-BAC2-4E55-9A6D-13251914CBB9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host", "src\host\lib\hostlib.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954746}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.unittest", "src\host\ut_lib\host.unittest.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954747}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Unit", "src\host\ut_host\Host.UnitTests.vcxproj", "{531C23E7-4B76-4C08-8AAD-04164CB628C9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
+ {06EC74CB-9A12-429C-B551-8562EC954747} = {06EC74CB-9A12-429C-B551-8562EC954747}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextBuffer.UnitTests", "src\buffer\out\ut_textbuffer\TextBuffer.UnitTests.vcxproj", "{531C23E7-4B76-4C08-8BBD-04164CB628C9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Feature", "src\host\ft_host\Host.FeatureTests.vcxproj", "{8CDB8850-7484-4EC7-B45B-181F85B2EE54}"
+ ProjectSection(ProjectDependencies) = postProject
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79} = {FC802440-AD6A-4919-8F2C-7701F2B38D79}
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.UnitTests", "src\terminal\parser\ut_parser\Parser.UnitTests.vcxproj", "{12144E07-FE63-4D33-9231-748B8D8C3792}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAdapter.UnitTests", "src\terminal\adapter\ut_adapter\Adapter.UnitTests.vcxproj", "{6AF01638-84CF-4B65-9870-484DFFCAC772}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.Fuzzer", "src\terminal\parser\ft_fuzzer\VTCommandFuzzer.vcxproj", "{96927B31-D6E8-4ABD-B03E-A5088A30BEBE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.FuzzWrapper", "src\terminal\parser\ft_fuzzwrapper\FuzzWrapper.vcxproj", "{F210A4AE-E02A-4BFC-80BB-F50A672FE763}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Propsheet.DLL", "src\propsheet\propsheet.vcxproj", "{5D23E8E1-3C64-4CC1-A8F7-6861677F7239}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build Common", "_Build Common", "{04170EEF-983A-4195-BFEF-2321E5E38A1E}"
+ ProjectSection(SolutionItems) = preProject
+ src\common.build.dll.props = src\common.build.dll.props
+ src\common.build.exe.or.dll.props = src\common.build.exe.or.dll.props
+ src\common.build.exe.props = src\common.build.exe.props
+ src\common.build.lib.props = src\common.build.lib.props
+ src\common.build.post.props = src\common.build.post.props
+ src\common.build.pre.props = src\common.build.pre.props
+ src\common.build.tests.props = src\common.build.tests.props
+ common.openconsole.props = common.openconsole.props
+ src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
+ src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
+ src\wap-common.build.post.props = src\wap-common.build.post.props
+ src\wap-common.build.pre.props = src\wap-common.build.pre.props
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "src\server\lib\server.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820262}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Host.Tests.UIA", "src\host\ft_uia\Host.Tests.UIA.csproj", "{C17E1BF3-9D34-4779-9458-A8EF98CC5662}"
+ ProjectSection(ProjectDependencies) = postProject
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF} = {099193A0-1E43-4BBC-BA7F-7B351E1342DF}
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB} = {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTApp", "src\tools\vtapp\VTApp.csproj", "{099193A0-1E43-4BBC-BA7F-7B351E1342DF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Tools", "_Tools", "{A10C4720-DCA4-4640-9749-67F4314F527C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Nihilist", "src\tools\nihilist\Nihilist.vcxproj", "{FC802440-AD6A-4919-8F2C-7701F2B38D79}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FontList", "src\tools\fontlist\FontList.vcxproj", "{919544AC-D39B-463F-8414-3C3C67CF727C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scratch", "src\tools\scratch\Scratch.vcxproj", "{ED82003F-FC5D-4E94-8B36-F480018ED064}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InteractivityWin32", "src\interactivity\win32\lib\win32.LIB.vcxproj", "{06EC74CB-9A12-429C-B551-8532EC964726}"
+ ProjectSection(ProjectDependencies) = postProject
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9} = {1C959542-BAC2-4E55-9A6D-13251914CBB9}
+ {990F2657-8580-4828-943F-5DD657D11842} = {990F2657-8580-4828-943F-5DD657D11842}
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "buffersize", "src\tools\buffersize\buffersize.vcxproj", "{ED82003F-FC5D-4E94-8B47-F480018ED064}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InteractivityBase", "src\interactivity\base\lib\InteractivityBase.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC964846}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Interactivity.Win32.Tests.Unit", "src\interactivity\win32\ut_interactivity_win32\Interactivity.Win32.UnitTests.vcxproj", "{D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {990F2657-8580-4828-943F-5DD657D11842} = {990F2657-8580-4828-943F-5DD657D11842}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CloseTest", "src\tools\closetest\CloseTest.vcxproj", "{C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererVt", "src\renderer\vt\lib\vt.vcxproj", "{990F2657-8580-4828-943F-5DD657D11842}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VtPipeTerm", "src\tools\vtpipeterm\VtPipeTerm.vcxproj", "{814DBDDE-894E-4327-A6E1-740504850098}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConEchoKey", "src\tools\echokey\ConEchoKey.vcxproj", "{814CBEEE-894E-4327-A6E1-740504850098}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererVt.unittest", "src\renderer\vt\ut_lib\vt.unittest.vcxproj", "{990F2657-8580-4828-943F-5DD657D11843}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BufferOut", "src\buffer\out\lib\bufferout.vcxproj", "{0CF235BD-2DA0-407E-90EE-C467E8BBC714}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererDx", "src\renderer\dx\lib\dx.vcxproj", "{48D21369-3D7B-4431-9967-24E81292CF62}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Terminal", "Terminal", "{59840756-302F-44DF-AA47-441A9D673202}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalConnection", "src\cascadia\TerminalConnection\TerminalConnection.vcxproj", "{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalCore", "src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj", "{CA5CAD1A-ABCD-429C-B551-8562EC954746}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\TerminalControl.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
+ {1CF55140-EF6A-4736-A403-957E4F7430BB} = {1CF55140-EF6A-4736-A403-957E4F7430BB}
+ EndProjectSection
+EndProject
+Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "CascadiaPackage", "src\cascadia\CascadiaPackage\CascadiaPackage.wapproj", "{CA5CAD1A-224A-4171-B13A-F16E576FDD12}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalSettings", "src\cascadia\TerminalSettings\TerminalSettings.vcxproj", "{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}"
+EndProject
+Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "OpenConsolePackage", "pkg\appx\OpenConsolePackage.wapproj", "{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Markup", "src\cascadia\Microsoft.UI.Xaml.Markup\Microsoft.UI.Xaml.Markup.vcxproj", "{015A0047-772D-4F1A-88C9-45C18F0ADFB6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalCore", "src\cascadia\UnitTests_TerminalCore\UnitTests.vcxproj", "{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Internal", "src\internal\internal.vcxproj", "{EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gsl", "gsl", "{16376381-CE22-42BE-B667-C6B35007008D}"
+ ProjectSection(SolutionItems) = preProject
+ dep\gsl\include\gsl\gsl = dep\gsl\include\gsl\gsl
+ dep\gsl\include\gsl\gsl_algorithm = dep\gsl\include\gsl\gsl_algorithm
+ dep\gsl\include\gsl\gsl_assert = dep\gsl\include\gsl\gsl_assert
+ dep\gsl\include\gsl\gsl_byte = dep\gsl\include\gsl\gsl_byte
+ dep\gsl\include\gsl\gsl_util = dep\gsl\include\gsl\gsl_util
+ dep\gsl\include\gsl\multi_span = dep\gsl\include\gsl\multi_span
+ dep\gsl\include\gsl\pointers = dep\gsl\include\gsl\pointers
+ dep\gsl\include\gsl\span = dep\gsl\include\gsl\span
+ dep\gsl\include\gsl\string_span = dep\gsl\include\gsl\string_span
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Virtual Terminal", "Virtual Terminal", "{F1995847-4AE5-479A-BBAF-382E51A63532}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rendering", "Rendering", "{05500DEF-2294-41E3-AF9A-24E580B82836}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Conhost", "Conhost", "{E8F24881-5E37-4362-B191-A3BA0ED7F4EB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Buffer", "Buffer", "{1E4A062E-293B-4817-B20D-BF16B979E350}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{89CDCC5C-9F53-4054-97A4-639D99F169CD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ AuditMode|ARM64 = AuditMode|ARM64
+ AuditMode|x64 = AuditMode|x64
+ AuditMode|x86 = AuditMode|x86
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x64.ActiveCfg = Release|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x64.Build.0 = Release|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x86.ActiveCfg = Release|Win32
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x86.Build.0 = Release|Win32
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.ActiveCfg = Debug|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Build.0 = Debug|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.ActiveCfg = Debug|Win32
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.Build.0 = Debug|Win32
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.Build.0 = Release|ARM64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|x64.ActiveCfg = Release|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|x64.Build.0 = Release|x64
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|x86.ActiveCfg = Release|Win32
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|x86.Build.0 = Release|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|x64.ActiveCfg = Release|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|x64.Build.0 = Release|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|x86.ActiveCfg = Release|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.AuditMode|x86.Build.0 = Release|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|ARM64.Build.0 = Debug|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x64.ActiveCfg = Debug|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x64.Build.0 = Debug|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x86.ActiveCfg = Debug|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x86.Build.0 = Debug|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|ARM64.ActiveCfg = Release|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|ARM64.Build.0 = Release|ARM64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|x64.ActiveCfg = Release|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|x64.Build.0 = Release|x64
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|x86.ActiveCfg = Release|Win32
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|x86.Build.0 = Release|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|x64.ActiveCfg = Release|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|x64.Build.0 = Release|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|x86.ActiveCfg = Release|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.AuditMode|x86.Build.0 = Release|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x64.ActiveCfg = Debug|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x64.Build.0 = Debug|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x86.ActiveCfg = Debug|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x86.Build.0 = Debug|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|ARM64.Build.0 = Release|ARM64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|x64.ActiveCfg = Release|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|x64.Build.0 = Release|x64
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|x86.ActiveCfg = Release|Win32
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|x86.Build.0 = Release|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.ActiveCfg = Release|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x64.Build.0 = Release|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x86.ActiveCfg = Release|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.AuditMode|x86.Build.0 = Release|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x64.ActiveCfg = Debug|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x64.Build.0 = Debug|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x86.ActiveCfg = Debug|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x86.Build.0 = Debug|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|ARM64.Build.0 = Release|ARM64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|x64.ActiveCfg = Release|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|x64.Build.0 = Release|x64
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|x86.ActiveCfg = Release|Win32
+ {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|x86.Build.0 = Release|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = Release|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.Build.0 = Release|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.ActiveCfg = Release|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.Build.0 = Release|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.Build.0 = Debug|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.ActiveCfg = Debug|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.ActiveCfg = Debug|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.Build.0 = Debug|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.Build.0 = Release|ARM64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.ActiveCfg = Release|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.Build.0 = Release|x64
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x86.ActiveCfg = Release|Win32
+ {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x86.Build.0 = Release|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.ActiveCfg = Release|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x64.Build.0 = Release|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.ActiveCfg = Release|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.AuditMode|x86.Build.0 = Release|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.Build.0 = Debug|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.ActiveCfg = Debug|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.ActiveCfg = Debug|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.Build.0 = Debug|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.Build.0 = Release|ARM64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.ActiveCfg = Release|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.Build.0 = Release|x64
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|x86.ActiveCfg = Release|Win32
+ {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|x86.Build.0 = Release|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|x64.ActiveCfg = Release|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|x64.Build.0 = Release|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|x86.ActiveCfg = Release|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.AuditMode|x86.Build.0 = Release|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x64.ActiveCfg = Debug|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x64.Build.0 = Debug|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x86.ActiveCfg = Debug|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x86.Build.0 = Debug|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|ARM64.Build.0 = Release|ARM64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|x64.ActiveCfg = Release|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|x64.Build.0 = Release|x64
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|x86.ActiveCfg = Release|Win32
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|x86.Build.0 = Release|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|x64.ActiveCfg = Release|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|x64.Build.0 = Release|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|x86.ActiveCfg = Release|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.AuditMode|x86.Build.0 = Release|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|ARM64.Build.0 = Debug|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x64.ActiveCfg = Debug|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x64.Build.0 = Debug|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x86.ActiveCfg = Debug|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x86.Build.0 = Debug|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|ARM64.ActiveCfg = Release|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|ARM64.Build.0 = Release|ARM64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|x64.ActiveCfg = Release|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|x64.Build.0 = Release|x64
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|x86.ActiveCfg = Release|Win32
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.AuditMode|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|ARM64.Build.0 = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x64.ActiveCfg = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x64.Build.0 = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x86.ActiveCfg = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x86.Build.0 = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954746}.Release|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.AuditMode|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|ARM64.Build.0 = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x64.ActiveCfg = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x64.Build.0 = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x86.ActiveCfg = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x86.Build.0 = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC954747}.Release|x86.Build.0 = Release|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|x64.ActiveCfg = Release|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|x64.Build.0 = Release|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|x86.ActiveCfg = Release|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.AuditMode|x86.Build.0 = Release|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|ARM64.Build.0 = Debug|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x64.ActiveCfg = Debug|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x64.Build.0 = Debug|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x86.ActiveCfg = Debug|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x86.Build.0 = Debug|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|ARM64.ActiveCfg = Release|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|ARM64.Build.0 = Release|ARM64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|x64.ActiveCfg = Release|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|x64.Build.0 = Release|x64
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|x86.ActiveCfg = Release|Win32
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|x86.Build.0 = Release|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|x64.ActiveCfg = Release|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|x64.Build.0 = Release|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|x86.ActiveCfg = Release|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.AuditMode|x86.Build.0 = Release|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|ARM64.Build.0 = Debug|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x64.ActiveCfg = Debug|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x64.Build.0 = Debug|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x86.ActiveCfg = Debug|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x86.Build.0 = Debug|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|ARM64.ActiveCfg = Release|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|ARM64.Build.0 = Release|ARM64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|x64.ActiveCfg = Release|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|x64.Build.0 = Release|x64
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|x86.ActiveCfg = Release|Win32
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|x86.Build.0 = Release|Win32
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|x64.ActiveCfg = Release|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|x64.Build.0 = Release|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|x86.ActiveCfg = Release|Win32
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.AuditMode|x86.Build.0 = Release|Win32
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x64.ActiveCfg = Debug|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x64.Build.0 = Debug|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x86.ActiveCfg = Debug|Win32
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|ARM64.Build.0 = Release|ARM64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|x64.ActiveCfg = Release|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|x64.Build.0 = Release|x64
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|x86.ActiveCfg = Release|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|x64.ActiveCfg = Release|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|x64.Build.0 = Release|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|x86.ActiveCfg = Release|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.AuditMode|x86.Build.0 = Release|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|ARM64.Build.0 = Debug|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x64.ActiveCfg = Debug|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x64.Build.0 = Debug|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x86.ActiveCfg = Debug|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x86.Build.0 = Debug|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|ARM64.ActiveCfg = Release|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|ARM64.Build.0 = Release|ARM64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|x64.ActiveCfg = Release|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|x64.Build.0 = Release|x64
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|x86.ActiveCfg = Release|Win32
+ {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|x86.Build.0 = Release|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|x64.ActiveCfg = Release|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|x64.Build.0 = Release|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|x86.ActiveCfg = Release|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.AuditMode|x86.Build.0 = Release|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x64.ActiveCfg = Debug|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x64.Build.0 = Debug|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x86.ActiveCfg = Debug|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x86.Build.0 = Debug|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|ARM64.Build.0 = Release|ARM64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|x64.ActiveCfg = Release|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|x64.Build.0 = Release|x64
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|x86.ActiveCfg = Release|Win32
+ {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|x86.Build.0 = Release|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|x64.ActiveCfg = Release|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|x64.Build.0 = Release|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|x86.ActiveCfg = Release|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.AuditMode|x86.Build.0 = Release|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|ARM64.Build.0 = Debug|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x64.ActiveCfg = Debug|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x64.Build.0 = Debug|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x86.ActiveCfg = Debug|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x86.Build.0 = Debug|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|ARM64.ActiveCfg = Release|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|ARM64.Build.0 = Release|ARM64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|x64.ActiveCfg = Release|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|x64.Build.0 = Release|x64
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|x86.ActiveCfg = Release|Win32
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|x86.Build.0 = Release|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|x64.ActiveCfg = Release|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|x64.Build.0 = Release|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|x86.ActiveCfg = Release|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.AuditMode|x86.Build.0 = Release|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|ARM64.Build.0 = Debug|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x64.ActiveCfg = Debug|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x64.Build.0 = Debug|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x86.ActiveCfg = Debug|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x86.Build.0 = Debug|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|ARM64.ActiveCfg = Release|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|ARM64.Build.0 = Release|ARM64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|x64.ActiveCfg = Release|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|x64.Build.0 = Release|x64
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|x86.ActiveCfg = Release|Win32
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|x86.Build.0 = Release|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|x64.ActiveCfg = Release|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|x64.Build.0 = Release|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|x86.ActiveCfg = Release|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.AuditMode|x86.Build.0 = Release|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|ARM64.Build.0 = Debug|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x64.ActiveCfg = Debug|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x64.Build.0 = Debug|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x86.ActiveCfg = Debug|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x86.Build.0 = Debug|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|ARM64.ActiveCfg = Release|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|ARM64.Build.0 = Release|ARM64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|x64.ActiveCfg = Release|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|x64.Build.0 = Release|x64
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|x86.ActiveCfg = Release|Win32
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|x86.Build.0 = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|x64.ActiveCfg = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|x64.Build.0 = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|x86.ActiveCfg = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.AuditMode|x86.Build.0 = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|ARM64.Build.0 = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x64.ActiveCfg = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x64.Build.0 = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x86.ActiveCfg = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x86.Build.0 = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|ARM64.ActiveCfg = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|ARM64.Build.0 = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|x64.ActiveCfg = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|x64.Build.0 = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|x86.ActiveCfg = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|x86.Build.0 = Release|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|ARM64.ActiveCfg = Debug|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|ARM64.Build.0 = Debug|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|x64.ActiveCfg = Release|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|x64.Build.0 = Release|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|x86.ActiveCfg = Release|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.AuditMode|x86.Build.0 = Release|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|ARM64.ActiveCfg = Debug|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x64.ActiveCfg = Debug|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x64.Build.0 = Debug|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x86.ActiveCfg = Debug|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x86.Build.0 = Debug|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|ARM64.ActiveCfg = Release|ARM64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|x64.ActiveCfg = Release|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|x64.Build.0 = Release|x64
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|x86.ActiveCfg = Release|Win32
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|x86.Build.0 = Release|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|ARM64.ActiveCfg = Debug|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|ARM64.Build.0 = Debug|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|x64.ActiveCfg = Release|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|x64.Build.0 = Release|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|x86.ActiveCfg = Release|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.AuditMode|x86.Build.0 = Release|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|ARM64.ActiveCfg = Debug|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x64.ActiveCfg = Debug|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x64.Build.0 = Debug|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x86.ActiveCfg = Debug|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x86.Build.0 = Debug|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|ARM64.ActiveCfg = Release|ARM64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|x64.ActiveCfg = Release|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|x64.Build.0 = Release|x64
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|x86.ActiveCfg = Release|Win32
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|x86.Build.0 = Release|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|x64.ActiveCfg = Release|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|x64.Build.0 = Release|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|x86.ActiveCfg = Release|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.AuditMode|x86.Build.0 = Release|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x64.ActiveCfg = Debug|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x64.Build.0 = Debug|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x86.Build.0 = Debug|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|ARM64.Build.0 = Release|ARM64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|x64.ActiveCfg = Release|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|x64.Build.0 = Release|x64
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|x86.ActiveCfg = Release|Win32
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|x86.Build.0 = Release|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|x64.ActiveCfg = Release|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|x64.Build.0 = Release|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|x86.ActiveCfg = Release|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.AuditMode|x86.Build.0 = Release|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x64.ActiveCfg = Debug|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x64.Build.0 = Debug|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x86.ActiveCfg = Debug|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x86.Build.0 = Debug|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|ARM64.Build.0 = Release|ARM64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|x64.ActiveCfg = Release|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|x64.Build.0 = Release|x64
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|x86.ActiveCfg = Release|Win32
+ {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|x86.Build.0 = Release|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|x64.ActiveCfg = Release|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|x64.Build.0 = Release|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|x86.ActiveCfg = Release|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.AuditMode|x86.Build.0 = Release|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|ARM64.Build.0 = Debug|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x64.ActiveCfg = Debug|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x64.Build.0 = Debug|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x86.ActiveCfg = Debug|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x86.Build.0 = Debug|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|ARM64.ActiveCfg = Release|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|ARM64.Build.0 = Release|ARM64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|x64.ActiveCfg = Release|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|x64.Build.0 = Release|x64
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|x86.ActiveCfg = Release|Win32
+ {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.AuditMode|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|ARM64.Build.0 = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x64.ActiveCfg = Debug|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x64.Build.0 = Debug|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x86.ActiveCfg = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x86.Build.0 = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8532EC964726}.Release|x86.Build.0 = Release|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|x64.ActiveCfg = Release|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|x64.Build.0 = Release|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|x86.ActiveCfg = Release|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.AuditMode|x86.Build.0 = Release|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|ARM64.Build.0 = Debug|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x64.ActiveCfg = Debug|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x64.Build.0 = Debug|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x86.ActiveCfg = Debug|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x86.Build.0 = Debug|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|ARM64.ActiveCfg = Release|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|ARM64.Build.0 = Release|ARM64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|x64.ActiveCfg = Release|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|x64.Build.0 = Release|x64
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|x86.ActiveCfg = Release|Win32
+ {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.AuditMode|x86.Build.0 = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|ARM64.Build.0 = Debug|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x64.ActiveCfg = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x64.Build.0 = Debug|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x86.ActiveCfg = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x86.Build.0 = Debug|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|ARM64.ActiveCfg = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|ARM64.Build.0 = Release|ARM64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|x64.ActiveCfg = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|x64.Build.0 = Release|x64
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|x86.ActiveCfg = Release|Win32
+ {06EC74CB-9A12-429C-B551-8562EC964846}.Release|x86.Build.0 = Release|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|x64.ActiveCfg = Release|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|x64.Build.0 = Release|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|x86.ActiveCfg = Release|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.AuditMode|x86.Build.0 = Release|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x64.ActiveCfg = Debug|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x64.Build.0 = Debug|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x86.ActiveCfg = Debug|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x86.Build.0 = Debug|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|ARM64.Build.0 = Release|ARM64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|x64.ActiveCfg = Release|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|x64.Build.0 = Release|x64
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|x86.ActiveCfg = Release|Win32
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|x86.Build.0 = Release|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|x64.ActiveCfg = Release|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|x64.Build.0 = Release|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|x86.ActiveCfg = Release|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.AuditMode|x86.Build.0 = Release|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|ARM64.Build.0 = Debug|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x64.ActiveCfg = Debug|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x64.Build.0 = Debug|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x86.ActiveCfg = Debug|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x86.Build.0 = Debug|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|ARM64.ActiveCfg = Release|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|ARM64.Build.0 = Release|ARM64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|x64.ActiveCfg = Release|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|x64.Build.0 = Release|x64
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|x86.ActiveCfg = Release|Win32
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|x86.Build.0 = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|x64.ActiveCfg = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|x64.Build.0 = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|x86.ActiveCfg = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.AuditMode|x86.Build.0 = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|ARM64.Build.0 = Debug|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|x64.ActiveCfg = Debug|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|x64.Build.0 = Debug|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|x86.ActiveCfg = Debug|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.Debug|x86.Build.0 = Debug|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|ARM64.ActiveCfg = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|ARM64.Build.0 = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|x64.ActiveCfg = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|x64.Build.0 = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|x86.ActiveCfg = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11842}.Release|x86.Build.0 = Release|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|x64.ActiveCfg = Release|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|x64.Build.0 = Release|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|x86.ActiveCfg = Release|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.AuditMode|x86.Build.0 = Release|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|ARM64.Build.0 = Debug|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x64.ActiveCfg = Debug|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x64.Build.0 = Debug|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x86.ActiveCfg = Debug|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x86.Build.0 = Debug|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|ARM64.ActiveCfg = Release|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|ARM64.Build.0 = Release|ARM64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|x64.ActiveCfg = Release|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|x64.Build.0 = Release|x64
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|x86.ActiveCfg = Release|Win32
+ {814DBDDE-894E-4327-A6E1-740504850098}.Release|x86.Build.0 = Release|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|x64.ActiveCfg = Release|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|x64.Build.0 = Release|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|x86.ActiveCfg = Release|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.AuditMode|x86.Build.0 = Release|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|ARM64.Build.0 = Debug|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x64.ActiveCfg = Debug|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x64.Build.0 = Debug|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x86.ActiveCfg = Debug|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x86.Build.0 = Debug|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|ARM64.ActiveCfg = Release|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|ARM64.Build.0 = Release|ARM64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|x64.ActiveCfg = Release|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|x64.Build.0 = Release|x64
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|x86.ActiveCfg = Release|Win32
+ {814CBEEE-894E-4327-A6E1-740504850098}.Release|x86.Build.0 = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|x64.ActiveCfg = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|x64.Build.0 = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|x86.ActiveCfg = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.AuditMode|x86.Build.0 = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|ARM64.Build.0 = Debug|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|x64.ActiveCfg = Debug|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|x64.Build.0 = Debug|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|x86.ActiveCfg = Debug|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.Debug|x86.Build.0 = Debug|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|ARM64.ActiveCfg = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|ARM64.Build.0 = Release|ARM64
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|x64.ActiveCfg = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|x64.Build.0 = Release|x64
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|x86.ActiveCfg = Release|Win32
+ {990F2657-8580-4828-943F-5DD657D11843}.Release|x86.Build.0 = Release|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|x64.Build.0 = AuditMode|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|ARM64.Build.0 = Debug|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x64.ActiveCfg = Debug|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x64.Build.0 = Debug|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x86.ActiveCfg = Debug|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x86.Build.0 = Debug|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|ARM64.ActiveCfg = Release|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|ARM64.Build.0 = Release|ARM64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|x64.ActiveCfg = Release|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|x64.Build.0 = Release|x64
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|x86.ActiveCfg = Release|Win32
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|x86.Build.0 = Release|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|x64.Build.0 = AuditMode|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|ARM64.Build.0 = Debug|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x64.ActiveCfg = Debug|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x64.Build.0 = Debug|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x86.ActiveCfg = Debug|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x86.Build.0 = Debug|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|ARM64.ActiveCfg = Release|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|ARM64.Build.0 = Release|ARM64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|x64.ActiveCfg = Release|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|x64.Build.0 = Release|x64
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|x86.ActiveCfg = Release|Win32
+ {48D21369-3D7B-4431-9967-24E81292CF62}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|ARM64.Deploy.0 = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x64.Deploy.0 = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x86.ActiveCfg = Release|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x86.Build.0 = Release|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.AuditMode|x86.Deploy.0 = Release|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x64.Deploy.0 = Debug|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.ActiveCfg = Debug|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Build.0 = Debug|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Deploy.0 = Debug|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|ARM64.Deploy.0 = Release|ARM64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.Deploy.0 = Release|x64
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.ActiveCfg = Release|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.Build.0 = Release|x86
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.Deploy.0 = Release|x86
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|x86.Build.0 = Release|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|x64.Build.0 = Release|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.AuditMode|x86.Build.0 = Release|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x64.ActiveCfg = Debug|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x64.Build.0 = Debug|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x86.ActiveCfg = Debug|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x86.Build.0 = Debug|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|ARM64.Build.0 = Release|ARM64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x64.ActiveCfg = Release|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x64.Build.0 = Release|x64
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x86.ActiveCfg = Release|Win32
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x86.Build.0 = Release|Win32
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|ARM64.Deploy.0 = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x64.ActiveCfg = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x64.Build.0 = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x64.Deploy.0 = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x86.ActiveCfg = Release|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x86.Build.0 = Release|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.AuditMode|x86.Deploy.0 = Release|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x64.ActiveCfg = Debug|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x64.Build.0 = Debug|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x64.Deploy.0 = Debug|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x86.ActiveCfg = Debug|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x86.Build.0 = Debug|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Debug|x86.Deploy.0 = Debug|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|ARM64.Build.0 = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|ARM64.Deploy.0 = Release|ARM64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x64.ActiveCfg = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x64.Build.0 = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x64.Deploy.0 = Release|x64
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.ActiveCfg = Release|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.Build.0 = Release|x86
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.Deploy.0 = Release|x86
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|ARM64.ActiveCfg = Release|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|ARM64.Build.0 = Release|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x64.ActiveCfg = Release|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x64.Build.0 = Release|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x86.ActiveCfg = Release|Win32
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x86.Build.0 = Release|Win32
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|ARM64.Build.0 = Debug|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x64.ActiveCfg = Debug|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x64.Build.0 = Debug|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x86.ActiveCfg = Debug|Win32
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x86.Build.0 = Debug|Win32
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|ARM64.ActiveCfg = Release|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|ARM64.Build.0 = Release|ARM64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x64.ActiveCfg = Release|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x64.Build.0 = Release|x64
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x86.ActiveCfg = Release|Win32
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x86.Build.0 = Release|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x64.Build.0 = AuditMode|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x64.ActiveCfg = Debug|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x64.Build.0 = Debug|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x86.ActiveCfg = Debug|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x86.Build.0 = Debug|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|ARM64.Build.0 = Release|ARM64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|x64.ActiveCfg = Release|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|x64.Build.0 = Release|x64
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|x86.ActiveCfg = Release|Win32
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|x86.Build.0 = Release|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|x64.Build.0 = AuditMode|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|ARM64.Build.0 = Debug|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x64.ActiveCfg = Debug|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x64.Build.0 = Debug|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x86.ActiveCfg = Debug|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x86.Build.0 = Debug|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|ARM64.ActiveCfg = Release|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|ARM64.Build.0 = Release|ARM64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|x64.ActiveCfg = Release|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|x64.Build.0 = Release|x64
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|x86.ActiveCfg = Release|Win32
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {4C8E6BB0-4713-4ADB-BD04-81628ECEAF20} = {81C352DB-1818-45B7-A284-18E259F1CC87}
+ {D57841D1-8294-4F2B-BB8B-D2A35738DECD} = {81C352DB-1818-45B7-A284-18E259F1CC87}
+ {2FD12FBB-1DDB-46D8-B818-1023C624CACA} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {3AE13314-1939-4DFA-9C14-38CA0834050C} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {DCF55140-EF6A-4736-A403-957E4F7430BB} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {1CF55140-EF6A-4736-A403-957E4F7430BB} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
+ {1C959542-BAC2-4E55-9A6D-13251914CBB9} = {05500DEF-2294-41E3-AF9A-24E580B82836}
+ {06EC74CB-9A12-429C-B551-8562EC954746} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {06EC74CB-9A12-429C-B551-8562EC954747} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {531C23E7-4B76-4C08-8AAD-04164CB628C9} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9} = {1E4A062E-293B-4817-B20D-BF16B979E350}
+ {8CDB8850-7484-4EC7-B45B-181F85B2EE54} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {12144E07-FE63-4D33-9231-748B8D8C3792} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {6AF01638-84CF-4B65-9870-484DFFCAC772} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {96927B31-D6E8-4ABD-B03E-A5088A30BEBE} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {F210A4AE-E02A-4BFC-80BB-F50A672FE763} = {F1995847-4AE5-479A-BBAF-382E51A63532}
+ {5D23E8E1-3C64-4CC1-A8F7-6861677F7239} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {18D09A24-8240-42D6-8CB6-236EEE820262} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {C17E1BF3-9D34-4779-9458-A8EF98CC5662} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {099193A0-1E43-4BBC-BA7F-7B351E1342DF} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {FC802440-AD6A-4919-8F2C-7701F2B38D79} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {919544AC-D39B-463F-8414-3C3C67CF727C} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {ED82003F-FC5D-4E94-8B36-F480018ED064} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {06EC74CB-9A12-429C-B551-8532EC964726} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {ED82003F-FC5D-4E94-8B47-F480018ED064} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {06EC74CB-9A12-429C-B551-8562EC964846} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {990F2657-8580-4828-943F-5DD657D11842} = {05500DEF-2294-41E3-AF9A-24E580B82836}
+ {814DBDDE-894E-4327-A6E1-740504850098} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {814CBEEE-894E-4327-A6E1-740504850098} = {A10C4720-DCA4-4640-9749-67F4314F527C}
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
+ {990F2657-8580-4828-943F-5DD657D11843} = {05500DEF-2294-41E3-AF9A-24E580B82836}
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {1E4A062E-293B-4817-B20D-BF16B979E350}
+ {48D21369-3D7B-4431-9967-24E81292CF62} = {05500DEF-2294-41E3-AF9A-24E580B82836}
+ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-224A-4171-B13A-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202}
+ {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {59840756-302F-44DF-AA47-441A9D673202}
+ {2D310963-F3E0-4EE5-8AC6-FBC94DCC3310} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {015A0047-772D-4F1A-88C9-45C18F0ADFB6} = {59840756-302F-44DF-AA47-441A9D673202}
+ {2C2BEEF4-9333-4D05-B12A-1905CBF112F9} = {59840756-302F-44DF-AA47-441A9D673202}
+ {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
+ {16376381-CE22-42BE-B667-C6B35007008D} = {81C352DB-1818-45B7-A284-18E259F1CC87}
+ {F1995847-4AE5-479A-BBAF-382E51A63532} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
+ {05500DEF-2294-41E3-AF9A-24E580B82836} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
+ {1E4A062E-293B-4817-B20D-BF16B979E350} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
+ EndGlobalSection
+EndGlobal
diff --git a/README.md b/README.md
new file mode 100644
index 00000000000..d3aa5883d56
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+# Welcome to the Console Project!
+
+This project is currently controlled by the Windows Developer Platform Tools & Runtimes' Open Source Software team (*WDG > DEP > DART > OSS*).
+
+Our team can be reached at `dartcon@microsoft.com`.
+
+The code is stored at .
+
+The area path within the Microsoft.VisualStudio.com database for our Work Items is `OS\CORE-OS Core\DEP-Developer Ecosystem Platform\DART-Developer Tools and Runtimes\Open Source Software\Console`.
+
+## Jumping In
+
+To get started, feel free to read up on some of our documentation on the way we get things done and hop in.
+
+Make a branch off of `dev/main` for yourself of the pattern `dev/myalias/foo` and feel free to push it to the server to get automatic builds and unit test runs.
+
+Choose a bit of code to clean up, try to add a new feature, or improve something that you try to use every day.
+
+When you are ready, use the [web portal](https://microsoft.visualstudio.com/Dart/_git/OpenConsole/pullrequests) to send a pull request into our `dev/main` branch and we'll be happy to help you get your code in line with the rest of the console.
+
+## Building
+
+OpenConsole uses submodules for some of its dependencies. To make sure submodules are restored or updated:
+
+```
+git submodule update --init --recursive
+```
+
+OpenConsole.sln may be built from within Visual Studio or from the command line using msbuild. To build from the command line:
+
+```
+nuget.exe restore OpenConsole.sln
+msbuild.exe OpenConsole.sln
+```
+
+We provide a set of convienence scripts in the /tools directory to help automate the process of building and running tests.
+
+## Assorted Notes
+
+Here's some assorted notes on the way we do things. If you learn something about how we do things, feel free to contribute to any of our documentation files anywhere in the repository (or make some new ones!) This is a work in progress as we try to learn what we'll need to train people on in order to be effective contributors to our project. We're pretty blind to these things after staring at this code for so long... so mind the gaps and ask us plenty of questions!
+
+* [Coding Style](./doc/STYLE.md)
+* [Code Organization](./doc/ORGANIZATION.md)
+* [Exceptions in our legacy codebase](./doc/EXCEPTIONS.md)
+* [Helpful smart pointers and macros for interfacing with Windows in WIL](./doc/WIL.md)
diff --git a/build/config/SignConfig.WindowsTerminal.xml b/build/config/SignConfig.WindowsTerminal.xml
new file mode 100644
index 00000000000..56f59563830
--- /dev/null
+++ b/build/config/SignConfig.WindowsTerminal.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/build/scripts/Create-AppxBundle.ps1 b/build/scripts/Create-AppxBundle.ps1
new file mode 100644
index 00000000000..8dd29b2a527
--- /dev/null
+++ b/build/scripts/Create-AppxBundle.ps1
@@ -0,0 +1,57 @@
+Param(
+ [Parameter(Mandatory,
+ HelpMessage="Base name for input .appx files")]
+ [string]
+ $ProjectName,
+
+ [Parameter(Mandatory,
+ HelpMessage="Appx Bundle Version")]
+ [version]
+ $BundleVersion,
+
+ [Parameter(Mandatory,
+ HelpMessage="Path under which to locate appx/msix files")]
+ [string]
+ $InputPath,
+
+ [Parameter(Mandatory,
+ HelpMessage="Output Path")]
+ [string]
+ $OutputPath,
+
+ [Parameter(HelpMessage="Path to makeappx.exe")]
+ [ValidateScript({Test-Path $_ -Type Leaf})]
+ [string]
+ $MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\MakeAppx.exe"
+)
+
+If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
+ Write-Error "Could not find MakeAppx.exe at `"$MakeAppxPath`".`nMake sure that -MakeAppxPath points to a valid SDK."
+ Exit 1
+}
+
+# Enumerates a set of appx files beginning with a project name
+# and generates a temporary file containing a bundle content map.
+Function Create-AppxBundleMapping {
+ Param(
+ [Parameter(Mandatory)]
+ [string]
+ $InputPath,
+
+ [Parameter(Mandatory)]
+ [string]
+ $ProjectName
+ )
+
+ $lines = @("[Files]")
+ Get-ChildItem -Path:$InputPath -Recurse -Filter:*$ProjectName* -Include *.appx, *.msix | % {
+ $lines += ("`"{0}`" `"{1}`"" -f ($_.FullName, $_.Name))
+ }
+ $outputFile = New-TemporaryFile
+ $lines | Out-File -Encoding:ASCII $outputFile
+ $outputFile
+}
+
+$NewMapping = Create-AppxBundleMapping -InputPath:$InputPath -ProjectName:$ProjectName
+
+& $MakeAppxPath bundle /v /bv $BundleVersion.ToString() /f $NewMapping.FullName /p $OutputPath
diff --git a/common.openconsole.props b/common.openconsole.props
new file mode 100644
index 00000000000..e521ad61996
--- /dev/null
+++ b/common.openconsole.props
@@ -0,0 +1,13 @@
+
+
+
+
+
+ $(MSBuildThisFileDirectory)
+
+
+
diff --git a/consolegit2gitfilters.json b/consolegit2gitfilters.json
new file mode 100644
index 00000000000..24d2a503df5
--- /dev/null
+++ b/consolegit2gitfilters.json
@@ -0,0 +1,31 @@
+{
+ "PrefixFilters": [
+ "."
+ ],
+ "ContainsFilters": [
+ "/.",
+ "/.git/",
+ "/obj/",
+ "/bin/",
+ "/TestResults/",
+ "/packages/",
+ "/ipch/",
+ "/dep/",
+ "/.vs/"
+ ],
+ "SuffixFilters": [
+ ".dbb",
+ ".evt",
+ ".log",
+ ".metadata",
+ ".prf",
+ ".trc",
+ ".user",
+ ".tmp",
+ ".TMP",
+ ".db",
+ ".wrn",
+ ".rec",
+ ".err"
+ ]
+}
diff --git a/dep/Console/conapi.h b/dep/Console/conapi.h
new file mode 100644
index 00000000000..84535ec6800
--- /dev/null
+++ b/dep/Console/conapi.h
@@ -0,0 +1,24 @@
+/*++
+Copyright (c) Microsoft Corporation
+
+Module Name:
+- conapi.h
+
+Abstract:
+- This module contains the internal structures and definitions used by the console server.
+
+Author:
+- Therese Stowell (ThereseS) 12-Nov-1990
+
+Revision History:
+--*/
+
+#pragma once
+// these should be in precomp but aren't being picked up...
+#include
+#define STATUS_SHARING_VIOLATION ((NTSTATUS)0xC0000043L)
+
+#include "conmsgl1.h"
+#include "conmsgl2.h"
+#include "conmsgl3.h"
+
diff --git a/dep/Console/condrv.h b/dep/Console/condrv.h
new file mode 100644
index 00000000000..b5654d98bbd
--- /dev/null
+++ b/dep/Console/condrv.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ condrv.h
+
+Abstract:
+
+ This module contains the declarations shared by the console driver and the
+ user-mode components that use it.
+
+Author:
+
+ Wedson Almeida Filho (wedsonaf) 24-Sep-2009
+
+Environment:
+
+ Kernel and user modes.
+
+--*/
+
+#pragma once
+
+#include "..\NT\ntioapi_x.h"
+
+//
+// Messages that can be received by servers, used in CD_IO_DESCRIPTOR::Function.
+//
+
+#define CONSOLE_IO_CONNECT 0x01
+#define CONSOLE_IO_DISCONNECT 0x02
+#define CONSOLE_IO_CREATE_OBJECT 0x03
+#define CONSOLE_IO_CLOSE_OBJECT 0x04
+#define CONSOLE_IO_RAW_WRITE 0x05
+#define CONSOLE_IO_RAW_READ 0x06
+#define CONSOLE_IO_USER_DEFINED 0x07
+#define CONSOLE_IO_RAW_FLUSH 0x08
+
+//
+// Header of all IOs submitted to a server.
+//
+
+typedef struct _CD_IO_DESCRIPTOR {
+ LUID Identifier;
+ ULONG_PTR Process;
+ ULONG_PTR Object;
+ ULONG Function;
+ ULONG InputSize;
+ ULONG OutputSize;
+ ULONG Reserved;
+} CD_IO_DESCRIPTOR, *PCD_IO_DESCRIPTOR;
+
+//
+// Types of objects, used in CREATE_OBJECT_INFORMATION::ObjectType.
+//
+
+#define CD_IO_OBJECT_TYPE_CURRENT_INPUT 0x01
+#define CD_IO_OBJECT_TYPE_CURRENT_OUTPUT 0x02
+#define CD_IO_OBJECT_TYPE_NEW_OUTPUT 0x03
+#define CD_IO_OBJECT_TYPE_GENERIC 0x04
+
+//
+// Payload of the CONSOLE_IO_CREATE_OBJECT io.
+//
+
+typedef struct _CD_CREATE_OBJECT_INFORMATION {
+ ULONG ObjectType;
+ ULONG ShareMode;
+ ACCESS_MASK DesiredAccess;
+} CD_CREATE_OBJECT_INFORMATION, *PCD_CREATE_OBJECT_INFORMATION;
+
+//
+// Create EA buffers.
+//
+
+#define CD_BROKER_EA_NAME "broker"
+#define CD_SERVER_EA_NAME "server"
+#define CD_ATTACH_EA_NAME "attach"
+
+typedef struct _CD_CREATE_SERVER {
+ HANDLE BrokerHandle;
+ LUID BrokerRequest;
+} CD_CREATE_SERVER, *PCD_CREATE_SERVER;
+
+typedef struct _CD_ATTACH_INFORMATION {
+ HANDLE ProcessId;
+} CD_ATTACH_INFORMATION, *PCD_ATTACH_INFORMATION;
+
+typedef struct _CD_ATTACH_INFORMATION64 {
+ PVOID64 ProcessId;
+} CD_ATTACH_INFORMATION64, *PCD_ATTACH_INFORMATION64;
+
+//
+// Information passed to the driver by a server when a connection is accepted.
+//
+
+typedef struct _CD_CONNECTION_INFORMATION {
+ ULONG_PTR Process;
+ ULONG_PTR Input;
+ ULONG_PTR Output;
+} CD_CONNECTION_INFORMATION, *PCD_CONNECTION_INFORMATION;
+
+//
+// Ioctls.
+//
+
+typedef struct _CD_IO_BUFFER {
+ ULONG Size;
+ PVOID Buffer;
+} CD_IO_BUFFER, *PCD_IO_BUFFER;
+
+typedef struct _CD_IO_BUFFER64 {
+ ULONG Size;
+ PVOID64 Buffer;
+} CD_IO_BUFFER64, *PCD_IO_BUFFER64;
+
+typedef struct _CD_USER_DEFINED_IO {
+ HANDLE Client;
+ ULONG InputCount;
+ ULONG OutputCount;
+ CD_IO_BUFFER Buffers[ANYSIZE_ARRAY];
+} CD_USER_DEFINED_IO, *PCD_USER_DEFINED_IO;
+
+typedef struct _CD_USER_DEFINED_IO64 {
+ PVOID64 Client;
+ ULONG InputCount;
+ ULONG OutputCount;
+ CD_IO_BUFFER64 Buffers[ANYSIZE_ARRAY];
+} CD_USER_DEFINED_IO64, *PCD_USER_DEFINED_IO64;
+
+typedef struct _CD_IO_BUFFER_DESCRIPTOR {
+ PVOID Data;
+ ULONG Size;
+ ULONG Offset;
+} CD_IO_BUFFER_DESCRIPTOR, *PCD_IO_BUFFER_DESCRIPTOR;
+
+typedef struct _CD_IO_COMPLETE {
+ LUID Identifier;
+ IO_STATUS_BLOCK IoStatus;
+ CD_IO_BUFFER_DESCRIPTOR Write;
+} CD_IO_COMPLETE, *PCD_IO_COMPLETE;
+
+typedef struct _CD_IO_OPERATION {
+ LUID Identifier;
+ CD_IO_BUFFER_DESCRIPTOR Buffer;
+} CD_IO_OPERATION, *PCD_IO_OPERATION;
+
+typedef struct _CD_IO_SERVER_INFORMATION {
+ HANDLE InputAvailableEvent;
+} CD_IO_SERVER_INFORMATION, *PCD_IO_SERVER_INFORMATION;
+
+typedef struct _CD_IO_DISPLAY_SIZE {
+ ULONG Width;
+ ULONG Height;
+} CD_IO_DISPLAY_SIZE, *PCD_IO_DISPLAY_SIZE;
+
+typedef struct _CD_IO_CHARACTER {
+ WCHAR Character;
+ USHORT Atribute;
+} CD_IO_CHARACTER, *PCD_IO_CHARACTER;
+
+typedef struct _CD_IO_ROW_INFORMATION {
+ SHORT Index;
+ PCD_IO_CHARACTER Old;
+ PCD_IO_CHARACTER New;
+} CD_IO_ROW_INFORMATION, *PCD_IO_ROW_INFORMATION;
+
+typedef struct _CD_IO_CURSOR_INFORMATION {
+ USHORT Column;
+ USHORT Row;
+ ULONG Height;
+ BOOLEAN IsVisible;
+} CD_IO_CURSOR_INFORMATION, *PCD_IO_CURSOR_INFORMATION;
+
+#define IOCTL_CONDRV_READ_IO \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 1, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_COMPLETE_IO \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 2, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_READ_INPUT \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 3, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_WRITE_OUTPUT \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 4, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_ISSUE_USER_IO \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 5, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_DISCONNECT_PIPE \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 6, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_SET_SERVER_INFORMATION \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 7, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_GET_SERVER_PID \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 8, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_GET_DISPLAY_SIZE \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 9, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_UPDATE_DISPLAY \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 10, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_SET_CURSOR \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 11, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_ALLOW_VIA_UIACCESS \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 12, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define IOCTL_CONDRV_LAUNCH_SERVER \
+ CTL_CODE(FILE_DEVICE_CONSOLE, 13, METHOD_NEITHER, FILE_ANY_ACCESS)
diff --git a/dep/Console/conmsgl1.h b/dep/Console/conmsgl1.h
new file mode 100644
index 00000000000..41ef9c74108
--- /dev/null
+++ b/dep/Console/conmsgl1.h
@@ -0,0 +1,156 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ conmsgl1.h
+
+Abstract:
+
+ This include file defines the layer 1 message formats used to communicate
+ between the client and server portions of the CONSOLE portion of the
+ Windows subsystem.
+
+Author:
+
+ Therese Stowell (thereses) 10-Nov-1990
+
+Revision History:
+
+ Wedson Almeida Filho (wedsonaf) 23-May-2010
+ Modified the messages for use with the console driver.
+
+--*/
+
+#pragma once
+
+#define CONSOLE_FIRST_API_NUMBER(Layer) \
+ (Layer << 24) \
+
+typedef struct _CONSOLE_SERVER_MSG {
+ ULONG IconId;
+ ULONG HotKey;
+ ULONG StartupFlags;
+ USHORT FillAttribute;
+ USHORT ShowWindow;
+ COORD ScreenBufferSize;
+ COORD WindowSize;
+ COORD WindowOrigin;
+ ULONG ProcessGroupId;
+ BOOLEAN ConsoleApp;
+ BOOLEAN WindowVisible;
+ USHORT TitleLength;
+ WCHAR Title[MAX_PATH + 1];
+ USHORT ApplicationNameLength;
+ WCHAR ApplicationName[128];
+ USHORT CurrentDirectoryLength;
+ WCHAR CurrentDirectory[MAX_PATH + 1];
+} CONSOLE_SERVER_MSG, *PCONSOLE_SERVER_MSG;
+
+typedef struct _CONSOLE_BROKER_DATA {
+ WCHAR DesktopName[MAX_PATH];
+} CONSOLE_BROKER_MSG, *PCONSOLE_BROKER_MSG;
+
+typedef struct _CONSOLE_GETCP_MSG {
+ OUT ULONG CodePage;
+ IN BOOLEAN Output;
+} CONSOLE_GETCP_MSG, *PCONSOLE_GETCP_MSG;
+
+typedef struct _CONSOLE_MODE_MSG {
+ IN OUT ULONG Mode;
+} CONSOLE_MODE_MSG, *PCONSOLE_MODE_MSG;
+
+typedef struct _CONSOLE_GETNUMBEROFINPUTEVENTS_MSG {
+ OUT ULONG ReadyEvents;
+} CONSOLE_GETNUMBEROFINPUTEVENTS_MSG, *PCONSOLE_GETNUMBEROFINPUTEVENTS_MSG;
+
+typedef struct _CONSOLE_GETCONSOLEINPUT_MSG {
+ OUT ULONG NumRecords;
+ IN USHORT Flags;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETCONSOLEINPUT_MSG, *PCONSOLE_GETCONSOLEINPUT_MSG;
+
+typedef struct _CONSOLE_READCONSOLE_MSG {
+ IN BOOLEAN Unicode;
+ IN BOOLEAN ProcessControlZ;
+ IN USHORT ExeNameLength;
+ IN ULONG InitialNumBytes;
+ IN ULONG CtrlWakeupMask;
+ OUT ULONG ControlKeyState;
+ OUT ULONG NumBytes;
+} CONSOLE_READCONSOLE_MSG, *PCONSOLE_READCONSOLE_MSG;
+
+typedef struct _CONSOLE_WRITECONSOLE_MSG {
+ OUT ULONG NumBytes;
+ IN BOOLEAN Unicode;
+} CONSOLE_WRITECONSOLE_MSG, *PCONSOLE_WRITECONSOLE_MSG;
+
+typedef struct _CONSOLE_LANGID_MSG {
+ OUT LANGID LangId;
+} CONSOLE_LANGID_MSG, *PCONSOLE_LANGID_MSG;
+
+typedef struct _CONSOLE_MAPBITMAP_MSG {
+ OUT HANDLE Mutex;
+ OUT PVOID Bitmap;
+} CONSOLE_MAPBITMAP_MSG, *PCONSOLE_MAPBITMAP_MSG;
+
+typedef struct _CONSOLE_MAPBITMAP_MSG64 {
+ OUT PVOID64 Mutex;
+ OUT PVOID64 Bitmap;
+} CONSOLE_MAPBITMAP_MSG64, *PCONSOLE_MAPBITMAP_MSG64;
+
+typedef enum _CONSOLE_API_NUMBER_L1 {
+ ConsolepGetCP = CONSOLE_FIRST_API_NUMBER(1),
+ ConsolepGetMode,
+ ConsolepSetMode,
+ ConsolepGetNumberOfInputEvents,
+ ConsolepGetConsoleInput,
+ ConsolepReadConsole,
+ ConsolepWriteConsole,
+ ConsolepNotifyLastClose,
+ ConsolepGetLangId,
+ ConsolepMapBitmap,
+} CONSOLE_API_NUMBER_L1, *PCONSOLE_API_NUMBER_L1;
+
+typedef struct _CONSOLE_MSG_HEADER {
+ ULONG ApiNumber;
+ ULONG ApiDescriptorSize;
+} CONSOLE_MSG_HEADER, *PCONSOLE_MSG_HEADER;
+
+typedef union _CONSOLE_MSG_BODY_L1 {
+ CONSOLE_GETCP_MSG GetConsoleCP;
+ CONSOLE_MODE_MSG GetConsoleMode;
+ CONSOLE_MODE_MSG SetConsoleMode;
+ CONSOLE_GETNUMBEROFINPUTEVENTS_MSG GetNumberOfConsoleInputEvents;
+ CONSOLE_GETCONSOLEINPUT_MSG GetConsoleInput;
+ CONSOLE_READCONSOLE_MSG ReadConsole;
+ CONSOLE_WRITECONSOLE_MSG WriteConsole;
+ CONSOLE_LANGID_MSG GetConsoleLangId;
+
+#if defined(BUILD_WOW6432) && !defined(BUILD_WOW3232)
+
+ CONSOLE_MAPBITMAP_MSG64 MapBitmap;
+
+#else
+
+ CONSOLE_MAPBITMAP_MSG MapBitmap;
+
+#endif
+
+} CONSOLE_MSG_BODY_L1, *PCONSOLE_MSG_BODY_L1;
+
+#ifndef __cplusplus
+typedef struct _CONSOLE_MSG_L1 {
+ CONSOLE_MSG_HEADER Header;
+ union {
+ CONSOLE_MSG_BODY_L1;
+ } u;
+} CONSOLE_MSG_L1, *PCONSOLE_MSG_L1;
+#else
+typedef struct _CONSOLE_MSG_L1 :
+ public CONSOLE_MSG_HEADER
+{
+ CONSOLE_MSG_BODY_L1 u;
+} CONSOLE_MSG_L1, *PCONSOLE_MSG_L1;
+#endif // __cplusplus
diff --git a/dep/Console/conmsgl2.h b/dep/Console/conmsgl2.h
new file mode 100644
index 00000000000..d1abb749ab5
--- /dev/null
+++ b/dep/Console/conmsgl2.h
@@ -0,0 +1,207 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ conmsgl2.h
+
+Abstract:
+
+ This include file defines the layer 2 message formats used to communicate
+ between the client and server portions of the CONSOLE portion of the
+ Windows subsystem.
+
+Author:
+
+ Therese Stowell (thereses) 10-Nov-1990
+
+Revision History:
+
+ Wedson Almeida Filho (wedsonaf) 23-May-2010
+ Modified the messages for use with the console driver.
+
+--*/
+
+#pragma once
+
+typedef struct _CONSOLE_CREATESCREENBUFFER_MSG {
+ IN ULONG Flags;
+ IN ULONG BitmapInfoLength;
+ IN ULONG Usage;
+} CONSOLE_CREATESCREENBUFFER_MSG, *PCONSOLE_CREATESCREENBUFFER_MSG;
+
+#define CONSOLE_ASCII 0x1
+#define CONSOLE_REAL_UNICODE 0x2
+#define CONSOLE_ATTRIBUTE 0x3
+#define CONSOLE_FALSE_UNICODE 0x4
+
+typedef struct _CONSOLE_FILLCONSOLEOUTPUT_MSG {
+ IN COORD WriteCoord;
+ IN ULONG ElementType;
+ IN USHORT Element;
+ IN OUT ULONG Length;
+} CONSOLE_FILLCONSOLEOUTPUT_MSG, *PCONSOLE_FILLCONSOLEOUTPUT_MSG;
+
+typedef struct _CONSOLE_CTRLEVENT_MSG {
+ IN ULONG CtrlEvent;
+ IN ULONG ProcessGroupId;
+} CONSOLE_CTRLEVENT_MSG, *PCONSOLE_CTRLEVENT_MSG;
+
+typedef struct _CONSOLE_SETCP_MSG {
+ IN ULONG CodePage;
+ IN BOOLEAN Output;
+} CONSOLE_SETCP_MSG, *PCONSOLE_SETCP_MSG;
+
+typedef struct _CONSOLE_GETCURSORINFO_MSG {
+ OUT ULONG CursorSize;
+ OUT BOOLEAN Visible;
+} CONSOLE_GETCURSORINFO_MSG, *PCONSOLE_GETCURSORINFO_MSG;
+
+typedef struct _CONSOLE_SETCURSORINFO_MSG {
+ IN ULONG CursorSize;
+ IN BOOLEAN Visible;
+} CONSOLE_SETCURSORINFO_MSG, *PCONSOLE_SETCURSORINFO_MSG;
+
+typedef struct _CONSOLE_SCREENBUFFERINFO_MSG {
+ IN OUT COORD Size;
+ IN OUT COORD CursorPosition;
+ IN OUT COORD ScrollPosition;
+ IN OUT USHORT Attributes;
+ IN OUT COORD CurrentWindowSize;
+ IN OUT COORD MaximumWindowSize;
+ IN OUT USHORT PopupAttributes;
+ IN OUT BOOLEAN FullscreenSupported;
+ IN OUT COLORREF ColorTable[16];
+} CONSOLE_SCREENBUFFERINFO_MSG, *PCONSOLE_SCREENBUFFERINFO_MSG;
+
+typedef struct _CONSOLE_SETSCREENBUFFERSIZE_MSG {
+ IN COORD Size;
+} CONSOLE_SETSCREENBUFFERSIZE_MSG, *PCONSOLE_SETSCREENBUFFERSIZE_MSG;
+
+typedef struct _CONSOLE_SETCURSORPOSITION_MSG {
+ IN COORD CursorPosition;
+} CONSOLE_SETCURSORPOSITION_MSG, *PCONSOLE_SETCURSORPOSITION_MSG;
+
+typedef struct _CONSOLE_GETLARGESTWINDOWSIZE_MSG {
+ OUT COORD Size;
+} CONSOLE_GETLARGESTWINDOWSIZE_MSG, *PCONSOLE_GETLARGESTWINDOWSIZE_MSG;
+
+typedef struct _CONSOLE_SCROLLSCREENBUFFER_MSG {
+ IN SMALL_RECT ScrollRectangle;
+ IN SMALL_RECT ClipRectangle;
+ IN BOOLEAN Clip;
+ IN BOOLEAN Unicode;
+ IN COORD DestinationOrigin;
+ IN CHAR_INFO Fill;
+} CONSOLE_SCROLLSCREENBUFFER_MSG, *PCONSOLE_SCROLLSCREENBUFFER_MSG;
+
+typedef struct _CONSOLE_SETTEXTATTRIBUTE_MSG {
+ IN USHORT Attributes;
+} CONSOLE_SETTEXTATTRIBUTE_MSG, *PCONSOLE_SETTEXTATTRIBUTE_MSG;
+
+typedef struct _CONSOLE_SETWINDOWINFO_MSG {
+ IN BOOLEAN Absolute;
+ IN SMALL_RECT Window;
+} CONSOLE_SETWINDOWINFO_MSG, *PCONSOLE_SETWINDOWINFO_MSG;
+
+typedef struct _CONSOLE_READCONSOLEOUTPUTSTRING_MSG {
+ IN COORD ReadCoord;
+ IN ULONG StringType;
+ OUT ULONG NumRecords;
+} CONSOLE_READCONSOLEOUTPUTSTRING_MSG, *PCONSOLE_READCONSOLEOUTPUTSTRING_MSG;
+
+typedef struct _CONSOLE_WRITECONSOLEINPUT_MSG {
+ OUT ULONG NumRecords;
+ IN BOOLEAN Unicode;
+ IN BOOLEAN Append;
+} CONSOLE_WRITECONSOLEINPUT_MSG, *PCONSOLE_WRITECONSOLEINPUT_MSG;
+
+typedef struct _CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG {
+ IN COORD WriteCoord;
+ IN ULONG StringType;
+ OUT ULONG NumRecords;
+} CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG, *PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG;
+
+typedef struct _CONSOLE_WRITECONSOLEOUTPUT_MSG {
+ IN OUT SMALL_RECT CharRegion;
+ IN BOOLEAN Unicode;
+} CONSOLE_WRITECONSOLEOUTPUT_MSG, *PCONSOLE_WRITECONSOLEOUTPUT_MSG;
+
+typedef struct _CONSOLE_READCONSOLEOUTPUT_MSG {
+ IN OUT SMALL_RECT CharRegion;
+ IN BOOLEAN Unicode;
+} CONSOLE_READCONSOLEOUTPUT_MSG, *PCONSOLE_READCONSOLEOUTPUT_MSG;
+
+typedef struct _CONSOLE_GETTITLE_MSG {
+ OUT ULONG TitleLength;
+ IN BOOLEAN Unicode;
+ IN BOOLEAN Original;
+} CONSOLE_GETTITLE_MSG, *PCONSOLE_GETTITLE_MSG;
+
+typedef struct _CONSOLE_SETTITLE_MSG {
+ IN BOOLEAN Unicode;
+} CONSOLE_SETTITLE_MSG, *PCONSOLE_SETTITLE_MSG;
+
+typedef enum _CONSOLE_API_NUMBER_L2 {
+ ConsolepFillConsoleOutput = CONSOLE_FIRST_API_NUMBER(2),
+ ConsolepGenerateCtrlEvent,
+ ConsolepSetActiveScreenBuffer,
+ ConsolepFlushInputBuffer,
+ ConsolepSetCP,
+ ConsolepGetCursorInfo,
+ ConsolepSetCursorInfo,
+ ConsolepGetScreenBufferInfo,
+ ConsolepSetScreenBufferInfo,
+ ConsolepSetScreenBufferSize,
+ ConsolepSetCursorPosition,
+ ConsolepGetLargestWindowSize,
+ ConsolepScrollScreenBuffer,
+ ConsolepSetTextAttribute,
+ ConsolepSetWindowInfo,
+ ConsolepReadConsoleOutputString,
+ ConsolepWriteConsoleInput,
+ ConsolepWriteConsoleOutput,
+ ConsolepWriteConsoleOutputString,
+ ConsolepReadConsoleOutput,
+ ConsolepGetTitle,
+ ConsolepSetTitle,
+} CONSOLE_API_NUMBER_L2, *PCONSOLE_API_NUMBER_L2;
+
+typedef union _CONSOLE_MSG_BODY_L2 {
+ CONSOLE_CTRLEVENT_MSG GenerateConsoleCtrlEvent;
+ CONSOLE_FILLCONSOLEOUTPUT_MSG FillConsoleOutput;
+ CONSOLE_SETCP_MSG SetConsoleCP;
+ CONSOLE_GETCURSORINFO_MSG GetConsoleCursorInfo;
+ CONSOLE_SETCURSORINFO_MSG SetConsoleCursorInfo;
+ CONSOLE_SCREENBUFFERINFO_MSG GetConsoleScreenBufferInfo;
+ CONSOLE_SCREENBUFFERINFO_MSG SetConsoleScreenBufferInfo;
+ CONSOLE_SETSCREENBUFFERSIZE_MSG SetConsoleScreenBufferSize;
+ CONSOLE_SETCURSORPOSITION_MSG SetConsoleCursorPosition;
+ CONSOLE_GETLARGESTWINDOWSIZE_MSG GetLargestConsoleWindowSize;
+ CONSOLE_SCROLLSCREENBUFFER_MSG ScrollConsoleScreenBuffer;
+ CONSOLE_SETTEXTATTRIBUTE_MSG SetConsoleTextAttribute;
+ CONSOLE_SETWINDOWINFO_MSG SetConsoleWindowInfo;
+ CONSOLE_READCONSOLEOUTPUTSTRING_MSG ReadConsoleOutputString;
+ CONSOLE_WRITECONSOLEINPUT_MSG WriteConsoleInput;
+ CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG WriteConsoleOutputString;
+ CONSOLE_WRITECONSOLEOUTPUT_MSG WriteConsoleOutput;
+ CONSOLE_READCONSOLEOUTPUT_MSG ReadConsoleOutput;
+ CONSOLE_SETTITLE_MSG SetConsoleTitle;
+ CONSOLE_GETTITLE_MSG GetConsoleTitle;
+} CONSOLE_MSG_BODY_L2, *PCONSOLE_MSG_BODY_L2;
+
+#ifndef __cplusplus
+typedef struct _CONSOLE_MSG_L2 {
+ CONSOLE_MSG_HEADER Header;
+ union {
+ CONSOLE_MSG_BODY_L2;
+ } u;
+} CONSOLE_MSG_L2, *PCONSOLE_MSG_L2;
+#else
+typedef struct _CONSOLE_MSG_L2 :
+ public CONSOLE_MSG_HEADER
+{
+ CONSOLE_MSG_BODY_L2 u;
+} CONSOLE_MSG_L2, *PCONSOLE_MSG_L2;
+#endif // __cplusplus
diff --git a/dep/Console/conmsgl3.h b/dep/Console/conmsgl3.h
new file mode 100644
index 00000000000..9e3d8e65453
--- /dev/null
+++ b/dep/Console/conmsgl3.h
@@ -0,0 +1,392 @@
+/*++
+
+Copyright (c) 1985 - 1999, Microsoft Corporation
+
+Module Name:
+
+ conmsgl3.h
+
+Abstract:
+
+ This include file defines the message formats used to communicate
+ between the client and server portions of the CONSOLE portion of the
+ Windows subsystem.
+
+Author:
+
+ Therese Stowell (thereses) 10-Nov-1990
+
+Revision History:
+
+ Wedson Almeida Filho (wedsonaf) 23-May-2010
+ Modified the messages for use with the console driver.
+
+--*/
+
+#pragma once
+
+#include // need FONT_SELECT
+
+typedef struct _CONSOLE_GETNUMBEROFFONTS_MSG {
+ OUT ULONG NumberOfFonts;
+} CONSOLE_GETNUMBEROFFONTS_MSG, *PCONSOLE_GETNUMBEROFFONTS_MSG;
+
+typedef struct _CONSOLE_GETSELECTIONINFO_MSG {
+ OUT CONSOLE_SELECTION_INFO SelectionInfo;
+} CONSOLE_GETSELECTIONINFO_MSG, *PCONSOLE_GETSELECTIONINFO_MSG;
+
+typedef struct _CONSOLE_GETMOUSEINFO_MSG {
+ OUT ULONG NumButtons;
+} CONSOLE_GETMOUSEINFO_MSG, *PCONSOLE_GETMOUSEINFO_MSG;
+
+typedef struct _CONSOLE_GETFONTINFO_MSG {
+ IN BOOLEAN MaximumWindow;
+ OUT ULONG NumFonts; // this value is valid even for error cases
+} CONSOLE_GETFONTINFO_MSG, *PCONSOLE_GETFONTINFO_MSG;
+
+typedef struct _CONSOLE_GETFONTSIZE_MSG {
+ IN ULONG FontIndex;
+ OUT COORD FontSize;
+} CONSOLE_GETFONTSIZE_MSG, *PCONSOLE_GETFONTSIZE_MSG;
+
+typedef struct _CONSOLE_CURRENTFONT_MSG {
+ IN BOOLEAN MaximumWindow;
+ IN OUT ULONG FontIndex;
+ IN OUT COORD FontSize;
+ IN OUT ULONG FontFamily;
+ IN OUT ULONG FontWeight;
+ IN OUT WCHAR FaceName[LF_FACESIZE];
+} CONSOLE_CURRENTFONT_MSG, *PCONSOLE_CURRENTFONT_MSG;
+
+typedef struct _CONSOLE_SETFONT_MSG {
+ IN ULONG FontIndex;
+} CONSOLE_SETFONT_MSG, *PCONSOLE_SETFONT_MSG;
+
+typedef struct _CONSOLE_SETICON_MSG {
+ IN HICON hIcon;
+} CONSOLE_SETICON_MSG, *PCONSOLE_SETICON_MSG;
+
+typedef struct _CONSOLE_SETICON_MSG64 {
+ IN PVOID64 hIcon;
+} CONSOLE_SETICON_MSG64, *PCONSOLE_SETICON_MSG64;
+
+typedef struct _CONSOLE_ADDALIAS_MSG {
+ IN USHORT SourceLength;
+ IN USHORT TargetLength;
+ IN USHORT ExeLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_ADDALIAS_MSG, *PCONSOLE_ADDALIAS_MSG;
+
+typedef struct _CONSOLE_GETALIAS_MSG {
+ IN USHORT SourceLength;
+ OUT USHORT TargetLength;
+ IN USHORT ExeLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETALIAS_MSG, *PCONSOLE_GETALIAS_MSG;
+
+typedef struct _CONSOLE_GETALIASESLENGTH_MSG {
+ OUT ULONG AliasesLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETALIASESLENGTH_MSG, *PCONSOLE_GETALIASESLENGTH_MSG;
+
+typedef struct _CONSOLE_GETALIASEXESLENGTH_MSG {
+ OUT ULONG AliasExesLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETALIASEXESLENGTH_MSG, *PCONSOLE_GETALIASEXESLENGTH_MSG;
+
+typedef struct _CONSOLE_GETALIASES_MSG {
+ IN BOOLEAN Unicode;
+ OUT ULONG AliasesBufferLength;
+} CONSOLE_GETALIASES_MSG, *PCONSOLE_GETALIASES_MSG;
+
+typedef struct _CONSOLE_GETALIASEXES_MSG {
+ OUT ULONG AliasExesBufferLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETALIASEXES_MSG, *PCONSOLE_GETALIASEXES_MSG;
+
+typedef struct _CONSOLE_EXPUNGECOMMANDHISTORY_MSG {
+ IN BOOLEAN Unicode;
+} CONSOLE_EXPUNGECOMMANDHISTORY_MSG, *PCONSOLE_EXPUNGECOMMANDHISTORY_MSG;
+
+typedef struct _CONSOLE_SETNUMBEROFCOMMANDS_MSG {
+ IN ULONG NumCommands;
+ IN BOOLEAN Unicode;
+} CONSOLE_SETNUMBEROFCOMMANDS_MSG, *PCONSOLE_SETNUMBEROFCOMMANDS_MSG;
+
+typedef struct _CONSOLE_GETCOMMANDHISTORYLENGTH_MSG {
+ OUT ULONG CommandHistoryLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETCOMMANDHISTORYLENGTH_MSG, *PCONSOLE_GETCOMMANDHISTORYLENGTH_MSG;
+
+typedef struct _CONSOLE_GETCOMMANDHISTORY_MSG {
+ OUT ULONG CommandBufferLength;
+ IN BOOLEAN Unicode;
+} CONSOLE_GETCOMMANDHISTORY_MSG, *PCONSOLE_GETCOMMANDHISTORY_MSG;
+
+typedef struct _CONSOLE_INVALIDATERECT_MSG {
+ IN SMALL_RECT Rect;
+} CONSOLE_INVALIDATERECT_MSG, *PCONSOLE_INVALIDATERECT_MSG;
+
+typedef struct _CONSOLE_VDM_MSG {
+ IN ULONG iFunction;
+ OUT BOOLEAN Bool;
+ IN OUT POINT Point;
+ OUT RECT Rect;
+} CONSOLE_VDM_MSG, *PCONSOLE_VDM_MSG;
+
+typedef struct _CONSOLE_SETCURSOR_MSG {
+ IN HCURSOR CursorHandle;
+} CONSOLE_SETCURSOR_MSG, *PCONSOLE_SETCURSOR_MSG;
+
+typedef struct _CONSOLE_SETCURSOR_MSG64 {
+ IN PVOID64 CursorHandle;
+} CONSOLE_SETCURSOR_MSG64, *PCONSOLE_SETCURSOR_MSG64;
+
+typedef struct _CONSOLE_SHOWCURSOR_MSG {
+ IN BOOLEAN bShow;
+ OUT ULONG DisplayCount;
+} CONSOLE_SHOWCURSOR_MSG, *PCONSOLE_SHOWCURSOR_MSG;
+
+typedef struct _CONSOLE_MENUCONTROL_MSG {
+ IN ULONG CommandIdLow;
+ IN ULONG CommandIdHigh;
+ OUT HMENU hMenu;
+} CONSOLE_MENUCONTROL_MSG, *PCONSOLE_MENUCONTROL_MSG;
+
+typedef struct _CONSOLE_MENUCONTROL_MSG64 {
+ IN ULONG CommandIdLow;
+ IN ULONG CommandIdHigh;
+ OUT PVOID64 hMenu;
+} CONSOLE_MENUCONTROL_MSG64, *PCONSOLE_MENUCONTROL_MSG64;
+
+typedef struct _CONSOLE_SETPALETTE_MSG {
+ IN HPALETTE hPalette;
+ IN ULONG dwUsage;
+} CONSOLE_SETPALETTE_MSG, *PCONSOLE_SETPALETTE_MSG;
+
+typedef struct _CONSOLE_SETPALETTE_MSG64 {
+ IN PVOID64 hPalette;
+ IN ULONG dwUsage;
+} CONSOLE_SETPALETTE_MSG64, *PCONSOLE_SETPALETTE_MSG64;
+
+typedef struct _CONSOLE_SETDISPLAYMODE_MSG {
+ IN ULONG dwFlags;
+ OUT COORD ScreenBufferDimensions;
+} CONSOLE_SETDISPLAYMODE_MSG, *PCONSOLE_SETDISPLAYMODE_MSG;
+
+typedef struct _CONSOLE_REGISTERVDM_MSG {
+ IN ULONG RegisterFlags;
+ IN HANDLE StartEvent;
+ IN HANDLE EndEvent;
+ IN HANDLE ErrorEvent;
+ OUT ULONG StateLength;
+ OUT PVOID StateBuffer;
+ OUT PVOID VDMBuffer;
+} CONSOLE_REGISTERVDM_MSG, *PCONSOLE_REGISTERVDM_MSG;
+
+typedef struct _CONSOLE_REGISTERVDM_MSG64 {
+ IN ULONG RegisterFlags;
+ IN PVOID64 StartEvent;
+ IN PVOID64 EndEvent;
+ IN PVOID64 ErrorEvent;
+ OUT ULONG StateLength;
+ OUT PVOID64 StateBuffer;
+ OUT PVOID64 VDMBuffer;
+} CONSOLE_REGISTERVDM_MSG64, *PCONSOLE_REGISTERVDM_MSG64;
+
+typedef struct _CONSOLE_GETHARDWARESTATE_MSG {
+ OUT COORD Resolution;
+ OUT COORD FontSize;
+} CONSOLE_GETHARDWARESTATE_MSG, *PCONSOLE_GETHARDWARESTATE_MSG;
+
+typedef struct _CONSOLE_SETHARDWARESTATE_MSG {
+ IN COORD Resolution;
+ IN COORD FontSize;
+} CONSOLE_SETHARDWARESTATE_MSG, *PCONSOLE_SETHARDWARESTATE_MSG;
+
+typedef struct _CONSOLE_GETDISPLAYMODE_MSG {
+ OUT ULONG ModeFlags;
+} CONSOLE_GETDISPLAYMODE_MSG, *PCONSOLE_GETDISPLAYMODE_MSG;
+
+typedef struct _CONSOLE_GETKEYBOARDLAYOUTNAME_MSG {
+ union {
+ WCHAR awchLayout[9];
+ char achLayout[9];
+ };
+ BOOLEAN bAnsi;
+} CONSOLE_GETKEYBOARDLAYOUTNAME_MSG, *PCONSOLE_GETKEYBOARDLAYOUTNAME_MSG;
+
+typedef struct _CONSOLE_SETKEYSHORTCUTS_MSG {
+ IN BOOLEAN Set;
+ IN BYTE ReserveKeys;
+} CONSOLE_SETKEYSHORTCUTS_MSG, *PCONSOLE_SETKEYSHORTCUTS_MSG;
+
+typedef struct _CONSOLE_SETMENUCLOSE_MSG {
+ IN BOOLEAN Enable;
+} CONSOLE_SETMENUCLOSE_MSG, *PCONSOLE_SETMENUCLOSE_MSG;
+
+typedef struct _CONSOLE_CHAR_TYPE_MSG {
+ IN COORD coordCheck;
+ OUT ULONG dwType;
+} CONSOLE_CHAR_TYPE_MSG, *PCONSOLE_CHAR_TYPE_MSG;
+
+typedef struct _CONSOLE_LOCAL_EUDC_MSG {
+ IN USHORT CodePoint;
+ IN COORD FontSize;
+} CONSOLE_LOCAL_EUDC_MSG, *PCONSOLE_LOCAL_EUDC_MSG;
+
+typedef struct _CONSOLE_CURSOR_MODE_MSG {
+ IN OUT BOOLEAN Blink;
+ IN OUT BOOLEAN DBEnable;
+} CONSOLE_CURSOR_MODE_MSG, *PCONSOLE_CURSOR_MODE_MSG;
+
+typedef struct _CONSOLE_REGISTEROS2_MSG {
+ IN BOOLEAN fOs2Register;
+} CONSOLE_REGISTEROS2_MSG, *PCONSOLE_REGISTEROS2_MSG;
+
+typedef struct _CONSOLE_SETOS2OEMFORMAT_MSG {
+ IN BOOLEAN fOs2OemFormat;
+} CONSOLE_SETOS2OEMFORMAT_MSG, *PCONSOLE_SETOS2OEMFORMAT_MSG;
+
+typedef struct _CONSOLE_NLS_MODE_MSG {
+ IN OUT BOOLEAN Ready;
+ IN ULONG NlsMode;
+} CONSOLE_NLS_MODE_MSG, *PCONSOLE_NLS_MODE_MSG;
+
+typedef struct _CONSOLE_GETCONSOLEWINDOW_MSG {
+ OUT HWND hwnd;
+} CONSOLE_GETCONSOLEWINDOW_MSG, *PCONSOLE_GETCONSOLEWINDOW_MSG;
+
+typedef struct _CONSOLE_GETCONSOLEWINDOW_MSG64 {
+ OUT PVOID64 hwnd;
+} CONSOLE_GETCONSOLEWINDOW_MSG64, *PCONSOLE_GETCONSOLEWINDOW_MSG64;
+
+typedef struct _CONSOLE_GETPROCESSLIST_MSG {
+ OUT ULONG dwProcessCount;
+} CONSOLE_GETCONSOLEPROCESSLIST_MSG, *PCONSOLE_GETCONSOLEPROCESSLIST_MSG;
+
+typedef struct _CONSOLE_GETHISTORY_MSG {
+ OUT ULONG HistoryBufferSize;
+ OUT ULONG NumberOfHistoryBuffers;
+ OUT ULONG dwFlags;
+} CONSOLE_HISTORY_MSG, *PCONSOLE_HISTORY_MSG;
+
+typedef enum _CONSOLE_API_NUMBER_L3 {
+ ConsolepGetNumberOfFonts = CONSOLE_FIRST_API_NUMBER(3),
+ ConsolepGetMouseInfo,
+ ConsolepGetFontInfo,
+ ConsolepGetFontSize,
+ ConsolepGetCurrentFont,
+ ConsolepSetFont,
+ ConsolepSetIcon,
+ ConsolepInvalidateBitmapRect,
+ ConsolepVDMOperation,
+ ConsolepSetCursor,
+ ConsolepShowCursor,
+ ConsolepMenuControl,
+ ConsolepSetPalette,
+ ConsolepSetDisplayMode,
+ ConsolepRegisterVDM,
+ ConsolepGetHardwareState,
+ ConsolepSetHardwareState,
+ ConsolepGetDisplayMode,
+ ConsolepAddAlias,
+ ConsolepGetAlias,
+ ConsolepGetAliasesLength,
+ ConsolepGetAliasExesLength,
+ ConsolepGetAliases,
+ ConsolepGetAliasExes,
+ ConsolepExpungeCommandHistory,
+ ConsolepSetNumberOfCommands,
+ ConsolepGetCommandHistoryLength,
+ ConsolepGetCommandHistory,
+ ConsolepSetKeyShortcuts,
+ ConsolepSetMenuClose,
+ ConsolepGetKeyboardLayoutName,
+ ConsolepGetConsoleWindow,
+ ConsolepCharType,
+ ConsolepSetLocalEUDC,
+ ConsolepSetCursorMode,
+ ConsolepGetCursorMode,
+ ConsolepRegisterOS2,
+ ConsolepSetOS2OemFormat,
+ ConsolepGetNlsMode,
+ ConsolepSetNlsMode,
+ ConsolepGetSelectionInfo,
+ ConsolepGetConsoleProcessList,
+ ConsolepGetHistory,
+ ConsolepSetHistory,
+ ConsolepSetCurrentFont,
+} CONSOLE_API_NUMBER_L3, *PCONSOLE_API_NUMBER_L3;
+
+typedef union _CONSOLE_MSG_BODY_L3 {
+ CONSOLE_GETNUMBEROFFONTS_MSG GetNumberOfConsoleFonts;
+ CONSOLE_GETMOUSEINFO_MSG GetConsoleMouseInfo;
+ CONSOLE_GETFONTINFO_MSG GetConsoleFontInfo;
+ CONSOLE_GETFONTSIZE_MSG GetConsoleFontSize;
+ CONSOLE_CURRENTFONT_MSG GetCurrentConsoleFont;
+ CONSOLE_SETFONT_MSG SetConsoleFont;
+ CONSOLE_INVALIDATERECT_MSG InvalidateConsoleBitmapRect;
+ CONSOLE_VDM_MSG VDMConsoleOperation;
+ CONSOLE_SHOWCURSOR_MSG ShowConsoleCursor;
+ CONSOLE_SETDISPLAYMODE_MSG SetConsoleDisplayMode;
+#ifdef BUILD_WOW6432
+ CONSOLE_REGISTERVDM_MSG64 RegisterConsoleVDM;
+ CONSOLE_SETCURSOR_MSG64 SetConsoleCursor;
+ CONSOLE_SETICON_MSG64 SetConsoleIcon;
+ CONSOLE_MENUCONTROL_MSG64 ConsoleMenuControl;
+ CONSOLE_SETPALETTE_MSG64 SetConsolePalette;
+ CONSOLE_GETCONSOLEWINDOW_MSG64 GetConsoleWindow;
+#else
+ CONSOLE_REGISTERVDM_MSG RegisterConsoleVDM;
+ CONSOLE_SETCURSOR_MSG SetConsoleCursor;
+ CONSOLE_SETICON_MSG SetConsoleIcon;
+ CONSOLE_MENUCONTROL_MSG ConsoleMenuControl;
+ CONSOLE_SETPALETTE_MSG SetConsolePalette;
+ CONSOLE_GETCONSOLEWINDOW_MSG GetConsoleWindow;
+#endif
+ CONSOLE_GETHARDWARESTATE_MSG GetConsoleHardwareState;
+ CONSOLE_SETHARDWARESTATE_MSG SetConsoleHardwareState;
+ CONSOLE_GETDISPLAYMODE_MSG GetConsoleDisplayMode;
+ CONSOLE_ADDALIAS_MSG AddConsoleAliasW;
+ CONSOLE_GETALIAS_MSG GetConsoleAliasW;
+ CONSOLE_GETALIASESLENGTH_MSG GetConsoleAliasesLengthW;
+ CONSOLE_GETALIASEXESLENGTH_MSG GetConsoleAliasExesLengthW;
+ CONSOLE_GETALIASES_MSG GetConsoleAliasesW;
+ CONSOLE_GETALIASEXES_MSG GetConsoleAliasExesW;
+ CONSOLE_EXPUNGECOMMANDHISTORY_MSG ExpungeConsoleCommandHistoryW;
+ CONSOLE_SETNUMBEROFCOMMANDS_MSG SetConsoleNumberOfCommandsW;
+ CONSOLE_GETCOMMANDHISTORYLENGTH_MSG GetConsoleCommandHistoryLengthW;
+ CONSOLE_GETCOMMANDHISTORY_MSG GetConsoleCommandHistoryW;
+ CONSOLE_SETKEYSHORTCUTS_MSG SetConsoleKeyShortcuts;
+ CONSOLE_SETMENUCLOSE_MSG SetConsoleMenuClose;
+ CONSOLE_GETKEYBOARDLAYOUTNAME_MSG GetKeyboardLayoutName;
+ CONSOLE_CHAR_TYPE_MSG GetConsoleCharType;
+ CONSOLE_LOCAL_EUDC_MSG SetConsoleLocalEUDC;
+ CONSOLE_CURSOR_MODE_MSG SetConsoleCursorMode;
+ CONSOLE_CURSOR_MODE_MSG GetConsoleCursorMode;
+ CONSOLE_REGISTEROS2_MSG RegisterConsoleOS2;
+ CONSOLE_SETOS2OEMFORMAT_MSG SetConsoleOS2OemFormat;
+ CONSOLE_NLS_MODE_MSG GetConsoleNlsMode;
+ CONSOLE_NLS_MODE_MSG SetConsoleNlsMode;
+ CONSOLE_GETSELECTIONINFO_MSG GetConsoleSelectionInfo;
+ CONSOLE_GETCONSOLEPROCESSLIST_MSG GetConsoleProcessList;
+ CONSOLE_CURRENTFONT_MSG SetCurrentConsoleFont;
+ CONSOLE_HISTORY_MSG SetConsoleHistory;
+ CONSOLE_HISTORY_MSG GetConsoleHistory;
+} CONSOLE_MSG_BODY_L3, *PCONSOLE_MSG_BODY_L3;
+
+#ifndef __cplusplus
+typedef struct _CONSOLE_MSG_L3 {
+ CONSOLE_MSG_HEADER Header;
+ union {
+ CONSOLE_MSG_BODY_L3;
+ } u;
+} CONSOLE_MSG_L3, *PCONSOLE_MSG_L3;
+#else
+typedef struct _CONSOLE_MSG_L3 :
+ public CONSOLE_MSG_HEADER
+{
+ CONSOLE_MSG_BODY_L3 u;
+} CONSOLE_MSG_L3, *PCONSOLE_MSG_L3;
+#endif // __cplusplus
diff --git a/dep/Console/ntcon.h b/dep/Console/ntcon.h
new file mode 100644
index 00000000000..9b196672883
--- /dev/null
+++ b/dep/Console/ntcon.h
@@ -0,0 +1,29 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#ifndef _NTCON_
+#define _NTCON_
+
+//
+// originally in winconp.h
+//
+#define CONSOLE_DETACHED_PROCESS ((HANDLE)-1)
+#define CONSOLE_NEW_CONSOLE ((HANDLE)-2)
+#define CONSOLE_CREATE_NO_WINDOW ((HANDLE)-3)
+
+#define SYSTEM_ROOT_CONSOLE_EVENT 3
+
+#define CONSOLE_READ_NOREMOVE 0x0001
+#define CONSOLE_READ_NOWAIT 0x0002
+
+#define CONSOLE_READ_VALID (CONSOLE_READ_NOREMOVE | CONSOLE_READ_NOWAIT)
+
+#define CONSOLE_GRAPHICS_BUFFER 2
+
+//
+// These are flags stored in PEB::ProcessParameters::ConsoleFlags.
+//
+#define CONSOLE_IGNORE_CTRL_C 0x1
+
+
+#endif //_NTCON_
\ No newline at end of file
diff --git a/dep/Console/winconp.h b/dep/Console/winconp.h
new file mode 100644
index 00000000000..eb05f329307
--- /dev/null
+++ b/dep/Console/winconp.h
@@ -0,0 +1,669 @@
+
+#ifndef _WINCONP_
+#define _WINCONP_
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#pragma warning(disable:4820) // padding added after data member
+#endif
+
+#include
+
+//
+// History flags (internal)
+//
+
+#define CHI_VALID_FLAGS (HISTORY_NO_DUP_FLAG)
+
+//
+// Selection flags (internal)
+//
+
+#define CONSOLE_SELECTION_INVERTED 0x0010 // selection is inverted (turned off)
+#define CONSOLE_SELECTION_VALID (CONSOLE_SELECTION_IN_PROGRESS | \
+ CONSOLE_SELECTION_NOT_EMPTY | \
+ CONSOLE_MOUSE_SELECTION | \
+ CONSOLE_MOUSE_DOWN)
+
+
+WINBASEAPI
+BOOL
+WINAPI
+GetConsoleKeyboardLayoutNameA(
+ _Out_writes_(KL_NAMELENGTH) LPSTR pszLayout);
+WINBASEAPI
+BOOL
+WINAPI
+GetConsoleKeyboardLayoutNameW(
+ _Out_writes_(KL_NAMELENGTH) LPWSTR pszLayout);
+#ifdef UNICODE
+#define GetConsoleKeyboardLayoutName GetConsoleKeyboardLayoutNameW
+#else
+#define GetConsoleKeyboardLayoutName GetConsoleKeyboardLayoutNameA
+#endif // !UNICODE
+
+//
+// Registry strings
+//
+
+#define CONSOLE_REGISTRY_STRING L"Console"
+#define CONSOLE_REGISTRY_FONTSIZE L"FontSize"
+#define CONSOLE_REGISTRY_FONTFAMILY L"FontFamily"
+#define CONSOLE_REGISTRY_BUFFERSIZE L"ScreenBufferSize"
+#define CONSOLE_REGISTRY_CURSORSIZE L"CursorSize"
+#define CONSOLE_REGISTRY_WINDOWMAXIMIZED L"WindowMaximized"
+#define CONSOLE_REGISTRY_WINDOWSIZE L"WindowSize"
+#define CONSOLE_REGISTRY_WINDOWPOS L"WindowPosition"
+#define CONSOLE_REGISTRY_WINDOWALPHA L"WindowAlpha"
+#define CONSOLE_REGISTRY_FILLATTR L"ScreenColors"
+#define CONSOLE_REGISTRY_POPUPATTR L"PopupColors"
+#define CONSOLE_REGISTRY_FULLSCR L"FullScreen"
+#define CONSOLE_REGISTRY_QUICKEDIT L"QuickEdit"
+#define CONSOLE_REGISTRY_FACENAME L"FaceName"
+#define CONSOLE_REGISTRY_FONTWEIGHT L"FontWeight"
+#define CONSOLE_REGISTRY_INSERTMODE L"InsertMode"
+#define CONSOLE_REGISTRY_HISTORYSIZE L"HistoryBufferSize"
+#define CONSOLE_REGISTRY_HISTORYBUFS L"NumberOfHistoryBuffers"
+#define CONSOLE_REGISTRY_HISTORYNODUP L"HistoryNoDup"
+#define CONSOLE_REGISTRY_COLORTABLE L"ColorTable%02u"
+#define CONSOLE_REGISTRY_EXTENDEDEDITKEY L"ExtendedEditKey"
+#define CONSOLE_REGISTRY_EXTENDEDEDITKEY_CUSTOM L"ExtendedEditkeyCustom"
+#define CONSOLE_REGISTRY_WORD_DELIM L"WordDelimiters"
+#define CONSOLE_REGISTRY_TRIMZEROHEADINGS L"TrimLeadingZeros"
+#define CONSOLE_REGISTRY_LOAD_CONIME L"LoadConIme"
+#define CONSOLE_REGISTRY_ENABLE_COLOR_SELECTION L"EnableColorSelection"
+#define CONSOLE_REGISTRY_SCROLLSCALE L"ScrollScale"
+
+// V2 console settings
+#define CONSOLE_REGISTRY_FORCEV2 L"ForceV2"
+#define CONSOLE_REGISTRY_LINESELECTION L"LineSelection"
+#define CONSOLE_REGISTRY_FILTERONPASTE L"FilterOnPaste"
+#define CONSOLE_REGISTRY_LINEWRAP L"LineWrap"
+#define CONSOLE_REGISTRY_CTRLKEYSHORTCUTS_DISABLED L"CtrlKeyShortcutsDisabled"
+#define CONSOLE_REGISTRY_ALLOW_ALTF4_CLOSE L"AllowAltF4Close"
+#define CONSOLE_REGISTRY_VIRTTERM_LEVEL L"VirtualTerminalLevel"
+
+#define CONSOLE_REGISTRY_CURSORTYPE L"CursorType"
+#define CONSOLE_REGISTRY_CURSORCOLOR L"CursorColor"
+
+#define CONSOLE_REGISTRY_INTERCEPTCOPYPASTE L"InterceptCopyPaste"
+
+#define CONSOLE_REGISTRY_COPYCOLOR L"CopyColor"
+#define CONSOLE_REGISTRY_USEDX L"UseDx"
+
+#define CONSOLE_REGISTRY_DEFAULTFOREGROUND L"DefaultForeground"
+#define CONSOLE_REGISTRY_DEFAULTBACKGROUND L"DefaultBackground"
+#define CONSOLE_REGISTRY_TERMINALSCROLLING L"TerminalScrolling"
+// end V2 console settings
+
+ /*
+ * Starting code page
+ */
+#define CONSOLE_REGISTRY_CODEPAGE (L"CodePage")
+
+//
+// registry strings on HKEY_LOCAL_MACHINE
+//
+#define MACHINE_REGISTRY_CONSOLE (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console")
+#define MACHINE_REGISTRY_CONSOLEIME (L"ConsoleIME")
+#define MACHINE_REGISTRY_ENABLE_CONIME_ON_SYSTEM_PROCESS (L"EnableConImeOnSystemProcess")
+
+
+#define MACHINE_REGISTRY_CONSOLE_TTFONT (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont")
+#define MACHINE_REGISTRY_CONSOLE_TTFONT_WIN32_PATH (L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont")
+
+
+#define MACHINE_REGISTRY_CONSOLE_NLS (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\Nls")
+
+
+#define MACHINE_REGISTRY_CONSOLE_FULLSCREEN (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\FullScreen")
+#define MACHINE_REGISTRY_INITIAL_PALETTE (L"InitialPalette")
+#define MACHINE_REGISTRY_COLOR_BUFFER (L"ColorBuffer")
+#define MACHINE_REGISTRY_COLOR_BUFFER_NO_TRANSLATE (L"ColorBufferNoTranslate")
+#define MACHINE_REGISTRY_MODE_FONT_PAIRS (L"ModeFontPairs")
+#define MACHINE_REGISTRY_FS_CODEPAGE (L"CodePage")
+
+
+#define MACHINE_REGISTRY_EUDC (L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\CodePage\\EUDCCodeRange")
+
+
+//
+// TrueType font list
+//
+
+// doesn't available bold when add BOLD_MARK on first of face name.
+#define BOLD_MARK (L'*')
+
+typedef struct _TT_FONT_LIST {
+ SINGLE_LIST_ENTRY List;
+ UINT CodePage;
+ BOOL fDisableBold;
+ TCHAR FaceName1[LF_FACESIZE];
+ TCHAR FaceName2[LF_FACESIZE];
+} TTFONTLIST, *LPTTFONTLIST;
+
+//
+// registry strings on HKEY_CURRENT_USER
+//
+#define PRELOAD_REGISTRY_STRING (L"Keyboard Layout\\Preload")
+
+
+//
+// Special key for previous word erase
+//
+#define EXTKEY_ERASE_PREV_WORD (0x7f)
+
+#ifndef NOGDI
+
+typedef struct _CONSOLE_GRAPHICS_BUFFER_INFO {
+ DWORD dwBitMapInfoLength;
+ LPBITMAPINFO lpBitMapInfo;
+ DWORD dwUsage;
+ HANDLE hMutex;
+ PVOID lpBitMap;
+} CONSOLE_GRAPHICS_BUFFER_INFO, *PCONSOLE_GRAPHICS_BUFFER_INFO;
+
+#endif
+
+BOOL
+WINAPI
+InvalidateConsoleDIBits(
+ _In_ HANDLE hConsoleOutput,
+ _In_ PSMALL_RECT lpRect);
+
+VOID
+WINAPI
+SetLastConsoleEventActive(
+ VOID);
+
+#define VDM_HIDE_WINDOW 1
+#define VDM_IS_ICONIC 2
+#define VDM_CLIENT_RECT 3
+#define VDM_CLIENT_TO_SCREEN 4
+#define VDM_SCREEN_TO_CLIENT 5
+#define VDM_IS_HIDDEN 6
+#define VDM_FULLSCREEN_NOPAINT 7
+#define VDM_SET_VIDEO_MODE 8
+
+BOOL
+WINAPI
+VDMConsoleOperation(
+ _In_ DWORD iFunction,
+ _Inout_opt_ LPVOID lpData);
+
+
+BOOL
+WINAPI
+SetConsoleIcon(
+ _In_ HICON hIcon);
+
+//
+// These console font APIs don't appear to be used anywhere. Maybe they
+// should be removed.
+//
+
+BOOL
+WINAPI
+SetConsoleFont(
+ _In_ HANDLE hConsoleOutput,
+ _In_ DWORD nFont);
+
+DWORD
+WINAPI
+GetConsoleFontInfo(
+ _In_ HANDLE hConsoleOutput,
+ _In_ BOOL bMaximumWindow,
+ _In_ DWORD nLength,
+ _Out_ PCONSOLE_FONT_INFO lpConsoleFontInfo);
+
+DWORD
+WINAPI
+GetNumberOfConsoleFonts(
+ VOID);
+
+BOOL
+WINAPI
+SetConsoleCursor(
+ _In_ HANDLE hConsoleOutput,
+ _In_ HCURSOR hCursor);
+
+int
+WINAPI
+ShowConsoleCursor(
+ _In_ HANDLE hConsoleOutput,
+ _In_ BOOL bShow);
+
+HMENU
+APIENTRY
+ConsoleMenuControl(
+ _In_ HANDLE hConsoleOutput,
+ _In_ UINT dwCommandIdLow,
+ _In_ UINT dwCommandIdHigh);
+
+BOOL
+SetConsolePalette(
+ _In_ HANDLE hConsoleOutput,
+ _In_ HPALETTE hPalette,
+ _In_ UINT dwUsage);
+
+#define CONSOLE_UNREGISTER_VDM 0
+#define CONSOLE_REGISTER_VDM 1
+#define CONSOLE_REGISTER_WOW 2
+
+BOOL
+APIENTRY
+RegisterConsoleVDM(
+ _In_ DWORD dwRegisterFlags,
+ _In_ HANDLE hStartHardwareEvent,
+ _In_ HANDLE hEndHardwareEvent,
+ _In_ HANDLE hErrorhardwareEvent,
+ _Reserved_ DWORD Reserved,
+ _Out_ LPDWORD lpStateLength,
+ _Outptr_ PVOID *lpState,
+ _In_opt_ COORD VDMBufferSize,
+ _Outptr_ PVOID *lpVDMBuffer);
+
+BOOL
+APIENTRY
+GetConsoleHardwareState(
+ _In_ HANDLE hConsoleOutput,
+ _Out_ PCOORD lpResolution,
+ _Out_ PCOORD lpFontSize);
+
+BOOL
+APIENTRY
+SetConsoleHardwareState(
+ _In_ HANDLE hConsoleOutput,
+ _In_ COORD dwResolution,
+ _In_ COORD dwFontSize);
+
+#define CONSOLE_NOSHORTCUTKEY 0x00000000 /* no shortcut key */
+#define CONSOLE_ALTTAB 0x00000001 /* Alt + Tab */
+#define CONSOLE_ALTESC 0x00000002 /* Alt + Escape */
+#define CONSOLE_ALTSPACE 0x00000004 /* Alt + Space */
+#define CONSOLE_ALTENTER 0x00000008 /* Alt + Enter */
+#define CONSOLE_ALTPRTSC 0x00000010 /* Alt Print screen */
+#define CONSOLE_PRTSC 0x00000020 /* Print screen */
+#define CONSOLE_CTRLESC 0x00000040 /* Ctrl + Escape */
+
+typedef struct _APPKEY {
+ WORD Modifier;
+ WORD ScanCode;
+} APPKEY, *LPAPPKEY;
+
+#define CONSOLE_MODIFIER_SHIFT 0x0003 // Left shift key
+#define CONSOLE_MODIFIER_CONTROL 0x0004 // Either Control shift key
+#define CONSOLE_MODIFIER_ALT 0x0008 // Either Alt shift key
+
+BOOL
+APIENTRY
+SetConsoleKeyShortcuts(
+ _In_ BOOL bSet,
+ _In_ BYTE bReserveKeys,
+ _In_reads_(dwNumAppKeys) LPAPPKEY lpAppKeys,
+ _In_ DWORD dwNumAppKeys);
+
+BOOL
+APIENTRY
+SetConsoleMenuClose(
+ _In_ BOOL bEnable);
+
+DWORD
+GetConsoleInputExeNameA(
+ _In_ DWORD nBufferLength,
+ _Out_writes_(nBufferLength) LPSTR lpBuffer);
+DWORD
+GetConsoleInputExeNameW(
+ _In_ DWORD nBufferLength,
+ _Out_writes_(nBufferLength) LPWSTR lpBuffer);
+#ifdef UNICODE
+#define GetConsoleInputExeName GetConsoleInputExeNameW
+#else
+#define GetConsoleInputExeName GetConsoleInputExeNameA
+#endif // !UNICODE
+
+BOOL
+SetConsoleInputExeNameA(
+ _In_ LPSTR lpExeName);
+BOOL
+SetConsoleInputExeNameW(
+ _In_ LPWSTR lpExeName);
+#ifdef UNICODE
+#define SetConsoleInputExeName SetConsoleInputExeNameW
+#else
+#define SetConsoleInputExeName SetConsoleInputExeNameA
+#endif // !UNICODE
+
+BOOL
+WINAPI
+ReadConsoleInputExA(
+ _In_ HANDLE hConsoleInput,
+ _Out_writes_(nLength) PINPUT_RECORD lpBuffer,
+ _In_ DWORD nLength,
+ _Out_ LPDWORD lpNumberOfEventsRead,
+ _In_ USHORT wFlags);
+BOOL
+WINAPI
+ReadConsoleInputExW(
+ _In_ HANDLE hConsoleInput,
+ _Out_writes_(nLength) PINPUT_RECORD lpBuffer,
+ _In_ DWORD nLength,
+ _Out_ LPDWORD lpNumberOfEventsRead,
+ _In_ USHORT wFlags);
+#ifdef UNICODE
+#define ReadConsoleInputEx ReadConsoleInputExW
+#else
+#define ReadConsoleInputEx ReadConsoleInputExA
+#endif // !UNICODE
+
+BOOL
+WINAPI
+WriteConsoleInputVDMA(
+ _In_ HANDLE hConsoleInput,
+ _In_reads_(nLength) PINPUT_RECORD lpBuffer,
+ _In_ DWORD nLength,
+ _Out_ LPDWORD lpNumberOfEventsWritten);
+BOOL
+WINAPI
+WriteConsoleInputVDMW(
+ _In_ HANDLE hConsoleInput,
+ _In_reads_(nLength) PINPUT_RECORD lpBuffer,
+ _In_ DWORD nLength,
+ _Out_ LPDWORD lpNumberOfEventsWritten);
+#ifdef UNICODE
+#define WriteConsoleInputVDM WriteConsoleInputVDMW
+#else
+#define WriteConsoleInputVDM WriteConsoleInputVDMA
+#endif // !UNICODE
+
+
+BOOL
+APIENTRY
+GetConsoleNlsMode(
+ _In_ HANDLE hConsole,
+ _Out_ PDWORD lpdwNlsMode);
+
+BOOL
+APIENTRY
+SetConsoleNlsMode(
+ _In_ HANDLE hConsole,
+ _In_ DWORD fdwNlsMode);
+
+BOOL
+APIENTRY
+GetConsoleCharType(
+ _In_ HANDLE hConsole,
+ _In_ COORD coordCheck,
+ _Out_ PDWORD pdwType);
+
+#define CHAR_TYPE_SBCS 0 // Displayed SBCS character
+#define CHAR_TYPE_LEADING 2 // Displayed leading byte of DBCS
+#define CHAR_TYPE_TRAILING 3 // Displayed trailing byte of DBCS
+
+BOOL
+APIENTRY
+SetConsoleLocalEUDC(
+ _In_ HANDLE hConsoleHandle,
+ _In_ WORD wCodePoint,
+ _In_ COORD cFontSize,
+ _In_ PCHAR lpSB);
+
+BOOL
+APIENTRY
+SetConsoleCursorMode(
+ _In_ HANDLE hConsoleHandle,
+ _In_ BOOL Blink,
+ _In_ BOOL DBEnable);
+
+BOOL
+APIENTRY
+GetConsoleCursorMode(
+ _In_ HANDLE hConsoleHandle,
+ _Out_ PBOOL pbBlink,
+ _Out_ PBOOL pbDBEnable);
+
+BOOL
+APIENTRY
+RegisterConsoleOS2(
+ _In_ BOOL fOs2Register);
+
+BOOL
+APIENTRY
+SetConsoleOS2OemFormat(
+ _In_ BOOL fOs2OemFormat);
+
+BOOL
+IsConsoleFullWidth(
+ _In_ HDC hDC,
+ _In_ DWORD CodePage,
+ _In_ WCHAR wch);
+
+#if defined(FE_IME)
+BOOL
+APIENTRY
+RegisterConsoleIME(
+ _In_ HWND hWndConsoleIME,
+ _Out_opt_ DWORD *lpdwConsoleThreadId);
+
+BOOL
+APIENTRY
+UnregisterConsoleIME(
+ VOID);
+#endif // FE_IME
+
+//
+// These bits are always on for console handles and are used for routing
+// by windows.
+//
+
+#define CONSOLE_HANDLE_SIGNATURE 0x00000003
+#define CONSOLE_HANDLE_NEVERSET 0x10000000
+#define CONSOLE_HANDLE_MASK (CONSOLE_HANDLE_SIGNATURE | CONSOLE_HANDLE_NEVERSET)
+
+#define CONSOLE_HANDLE(HANDLE) (((ULONG_PTR)(HANDLE) & CONSOLE_HANDLE_MASK) == CONSOLE_HANDLE_SIGNATURE)
+
+//
+// These strings are used to open console input or output.
+//
+
+#define CONSOLE_INPUT_STRING L"CONIN$"
+#define CONSOLE_OUTPUT_STRING L"CONOUT$"
+#define CONSOLE_GENERIC L"CON"
+
+//
+// this string is used to call RegisterWindowMessage to get
+// progman's handle.
+//
+
+#define CONSOLE_PROGMAN_HANDLE_MESSAGE "ConsoleProgmanHandle"
+
+
+//
+// stream API definitions. these API are only supposed to be used by
+// subsystems (i.e. OpenFile routes to OpenConsoleW).
+//
+
+HANDLE
+APIENTRY
+OpenConsoleW(
+ _In_ LPWSTR lpConsoleDevice,
+ _In_ DWORD dwDesiredAccess,
+ _In_ BOOL bInheritHandle,
+ _In_ DWORD dwShareMode);
+
+HANDLE
+APIENTRY
+DuplicateConsoleHandle(
+ _In_ HANDLE hSourceHandle,
+ _In_ DWORD dwDesiredAccess,
+ _In_ BOOL bInheritHandle,
+ _In_ DWORD dwOptions);
+
+BOOL
+APIENTRY
+GetConsoleHandleInformation(
+ _In_ HANDLE hObject,
+ _Out_ LPDWORD lpdwFlags);
+
+BOOL
+APIENTRY
+SetConsoleHandleInformation(
+ _In_ HANDLE hObject,
+ _In_ DWORD dwMask,
+ _In_ DWORD dwFlags);
+
+BOOL
+APIENTRY
+CloseConsoleHandle(
+ _In_ HANDLE hConsole);
+
+BOOL
+APIENTRY
+VerifyConsoleIoHandle(
+ _In_ HANDLE hIoHandle);
+
+HANDLE
+APIENTRY
+GetConsoleInputWaitHandle(
+ VOID);
+
+typedef struct _CONSOLE_STATE_INFO {
+ /* BEGIN V1 CONSOLE_STATE_INFO */
+ COORD ScreenBufferSize;
+ COORD WindowSize;
+ INT WindowPosX;
+ INT WindowPosY;
+ COORD FontSize;
+ UINT FontFamily;
+ UINT FontWeight;
+ WCHAR FaceName[LF_FACESIZE];
+ UINT CursorSize;
+ UINT FullScreen : 1;
+ UINT QuickEdit : 1;
+ UINT AutoPosition : 1;
+ UINT InsertMode : 1;
+ UINT HistoryNoDup : 1;
+ UINT FullScreenSupported : 1;
+ UINT UpdateValues : 1;
+ UINT Defaults : 1;
+ WORD ScreenAttributes;
+ WORD PopupAttributes;
+ UINT HistoryBufferSize;
+ UINT NumberOfHistoryBuffers;
+ COLORREF ColorTable[16];
+ HWND hWnd;
+ HICON hIcon;
+ LPWSTR OriginalTitle;
+ LPWSTR LinkTitle;
+
+ /*
+ * Starting code page
+ */
+ UINT CodePage;
+
+ /* END V1 CONSOLE_STATE_INFO */
+
+ /* BEGIN V2 CONSOLE_STATE_INFO */
+ BOOL fIsV2Console;
+ BOOL fWrapText;
+ BOOL fFilterOnPaste;
+ BOOL fCtrlKeyShortcutsDisabled;
+ BOOL fLineSelection;
+ BYTE bWindowTransparency;
+ BOOL fWindowMaximized;
+
+ unsigned int CursorType;
+ COLORREF CursorColor;
+
+ BOOL InterceptCopyPaste;
+
+ COLORREF DefaultForeground;
+ COLORREF DefaultBackground;
+ BOOL TerminalScrolling;
+ /* END V2 CONSOLE_STATE_INFO */
+
+} CONSOLE_STATE_INFO, *PCONSOLE_STATE_INFO;
+
+
+#ifdef DEFINE_CONSOLEV2_PROPERTIES
+#define PID_CONSOLE_FORCEV2 1
+#define PID_CONSOLE_WRAPTEXT 2
+#define PID_CONSOLE_FILTERONPASTE 3
+#define PID_CONSOLE_CTRLKEYSDISABLED 4
+#define PID_CONSOLE_LINESELECTION 5
+#define PID_CONSOLE_WINDOWTRANSPARENCY 6
+#define PID_CONSOLE_WINDOWMAXIMIZED 7
+#define PID_CONSOLE_CURSOR_TYPE 8
+#define PID_CONSOLE_CURSOR_COLOR 9
+#define PID_CONSOLE_INTERCEPT_COPY_PASTE 10
+#define PID_CONSOLE_DEFAULTFOREGROUND 11
+#define PID_CONSOLE_DEFAULTBACKGROUND 12
+#define PID_CONSOLE_TERMINALSCROLLING 13
+
+#define CONSOLE_PROPKEY(name, id) \
+DEFINE_PROPERTYKEY(name, 0x0C570607, 0x0396, 0x43DE, 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26, id);
+
+CONSOLE_PROPKEY(PKEY_Console_ForceV2, PID_CONSOLE_FORCEV2);
+CONSOLE_PROPKEY(PKEY_Console_WrapText, PID_CONSOLE_WRAPTEXT);
+CONSOLE_PROPKEY(PKEY_Console_FilterOnPaste, PID_CONSOLE_FILTERONPASTE);
+CONSOLE_PROPKEY(PKEY_Console_CtrlKeyShortcutsDisabled, PID_CONSOLE_CTRLKEYSDISABLED);
+CONSOLE_PROPKEY(PKEY_Console_LineSelection, PID_CONSOLE_LINESELECTION);
+CONSOLE_PROPKEY(PKEY_Console_WindowTransparency, PID_CONSOLE_WINDOWTRANSPARENCY);
+CONSOLE_PROPKEY(PKEY_Console_WindowMaximized, PID_CONSOLE_WINDOWMAXIMIZED);
+CONSOLE_PROPKEY(PKEY_Console_CursorType, PID_CONSOLE_CURSOR_TYPE);
+CONSOLE_PROPKEY(PKEY_Console_CursorColor, PID_CONSOLE_CURSOR_COLOR);
+CONSOLE_PROPKEY(PKEY_Console_InterceptCopyPaste, PID_CONSOLE_INTERCEPT_COPY_PASTE);
+CONSOLE_PROPKEY(PKEY_Console_DefaultForeground, PID_CONSOLE_DEFAULTFOREGROUND);
+CONSOLE_PROPKEY(PKEY_Console_DefaultBackground, PID_CONSOLE_DEFAULTBACKGROUND);
+CONSOLE_PROPKEY(PKEY_Console_TerminalScrolling, PID_CONSOLE_TERMINALSCROLLING);
+#endif
+
+
+//
+// Ensure the alignment is WORD boundary
+//
+
+#include
+
+typedef struct {
+ WORD wMod;
+ WORD wVirKey;
+ WCHAR wUnicodeChar;
+} ExtKeySubst;
+
+typedef struct {
+ ExtKeySubst keys[3]; // 0: Ctrl
+ // 1: Alt
+ // 2: Ctrl+Alt
+} ExtKeyDef;
+
+typedef ExtKeyDef ExtKeyDefTable['Z' - 'A' + 1];
+
+typedef struct {
+ DWORD dwVersion;
+ DWORD dwCheckSum;
+ ExtKeyDefTable table;
+} ExtKeyDefBuf;
+
+//
+// Restore the previous alignment
+//
+
+#include
+
+
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _WINCONP_
diff --git a/dep/NT/ntioapi_x.h b/dep/NT/ntioapi_x.h
new file mode 100644
index 00000000000..d89e0fc888a
--- /dev/null
+++ b/dep/NT/ntioapi_x.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
diff --git a/dep/Win32K/winuserp.h b/dep/Win32K/winuserp.h
new file mode 100644
index 00000000000..faea9854f33
--- /dev/null
+++ b/dep/Win32K/winuserp.h
@@ -0,0 +1,12 @@
+/*
+ * Reserved console space.
+ *
+ * This was moved from the console code so that we can localize it
+ * in one place. This was necessary for dealing with the background
+ * color, which we need to have for the hungapp drawing. These are
+ * stored in the extra-window-bytes of each console.
+ */
+#define GWL_CONSOLE_WNDALLOC (3 * sizeof(DWORD))
+#define GWL_CONSOLE_PID 0
+#define GWL_CONSOLE_TID 4
+#define GWL_CONSOLE_BKCOLOR 8
\ No newline at end of file
diff --git a/dep/WinAppDriver/EULA.rtf b/dep/WinAppDriver/EULA.rtf
new file mode 100644
index 00000000000..59009f02849
--- /dev/null
+++ b/dep/WinAppDriver/EULA.rtf
@@ -0,0 +1,96 @@
+{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\fswiss\fprq2\fcharset0 Arial;}{\f2\fnil\fcharset0 Calibri;}}
+{\colortbl ;\red0\green0\blue255;}
+{\stylesheet{ Normal;}{\s1 heading 1;}{\s2 heading 2;}}
+{\*\generator Riched20 10.0.10586}\viewkind4\uc1
+\pard\widctlpar\sb120\sa120\b\f0\fs28 MICROSOFT SOFTWARE LICENSE TERMS\par
+
+\pard\brdrb\brdrs\brdrw10\brsp20 \widctlpar\sb120\sa120 Pre-Release and Evaluation EULA \endash Windows Application Driver\par
+
+\pard\widctlpar\sb120\sa120\b0\fs20 IF YOU LIVE IN (OR ARE A BUSINESS WITH YOUR PRINCIPAL PLACE OF BUSINESS IN) THE UNITED STATES, PLEASE READ THE \ldblquote BINDING ARBITRATION AND CLASS ACTION WAIVER\rdblquote SECTION BELOW. IT AFFECTS HOW DISPUTES ARE RESOLVED.\lang9\par
+
+\pard\brdrt\brdrs\brdrw10\brsp20 \widctlpar\sb120\sa120 These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or \lang1033 additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft\rquote s rights relating to pre-updated software or services\lang9 ). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.\par
+
+\pard
+{\pntext\f0 1.\tab}{\*\pn\pnlvlbody\pnf0\pnindent360\pnstart1\pndec{\pntxta.}}
+\widctlpar\s1\fi-357\li357\sb120\sa120\b\lang1033 INSTALLATION AND USE RIGHTS.\par
+
+\pard
+{\pntext\f0 a)\tab}{\*\pn\pnlvlbody\pnf0\pnindent0\pnstart1\pnlcltr{\pntxta)}}
+\widctlpar\s2\fi-360\li717\sb120\sa120 General. \b0 You may install and use any number of copies of the software on your devices, solely to i) evaluate for internal business purposes; and ii) design, develop and test your applications. \par
+{\pntext\f0 b)\tab}\b Included Microsoft Applications. \b0 The software may include other Microsoft applications. These license terms apply to those included applications, if any, unless other license terms are provided with the other Microsoft applications.\par
+{\pntext\f0 c)\tab}\b Third Party Applications. \b0 The software may include third party applications that Microsoft, not the third party, licenses to you under this agreement. Any included notices for third party applications are for your information only and are listed in Exhibit A to these license terms.\par
+{\pntext\f0 d)\tab}\b No Distribution Rights. \b0 This agreement does not grant you a license to distribute nor sublicense all or part of the software to any third party.\par
+{\pntext\f0 e)\tab}\b\lang9 Package Managers. \b0\lang1033 The software may include package managers, like NuGet, that give you the option to download other Microsoft and third party software packages to use with your application. Those packages are under their own licenses, and not this agreement. Microsoft does not distribute, license or provide any warranties for any of the third party packages\lang9 .\lang1033\par
+
+\pard\widctlpar\s1\fi-357\li357\sb120\sa120\b 2.\tab TIME-SENSITIVE SOFTWARE.\par
+
+\pard
+{\pntext\f0 a)\tab}{\*\pn\pnlvlbody\pnf0\pnindent0\pnstart1\pnlcltr{\pntxta)}}
+\widctlpar\s2\fi-360\li717\sb120\sa120 Period. \b0 The software is time-sensitive and may stop running on a date that is defined in the software.\par
+{\pntext\f0 b)\tab}\b Notice. \b0 You may receive periodic reminder notices of this date through the software.\par
+{\pntext\f0 c)\tab}\b Access to data. \b0 You may not be able to access data used in the software when it stops running.\par
+
+\pard\widctlpar\s1\fi-357\li357\sb120\sa120\b 3.\tab PRE-RELEASE SOFTWARE.\b0 The software is a pre-release version. It may not operate correctly. It may be different from the commercially released version.\par
+\b 4.\tab FEEDBACK.\b0 If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You will not give feedback that is subject to a license that requires Microsoft to license its software or documentation to third parties because Microsoft includes your feedback in them. These rights survive this agreement.\par
+\b 5.\tab DATA.\b0 The software may collect information about you and your use of the software and send that to Microsoft. Microsoft may use this information to provide services and improve Microsoft\rquote s products and services. Your opt-out rights, if any, are described in\b \b0 the product documentation. Some features in the software may enable collection of data from users of your applications that access or use the software. If you use these features to enable data collection in your applications, you must comply with applicable law, including getting any required user consent, and maintain a prominent privacy policy that accurately informs users about how you use, collect, and share their data. You can learn more about Microsoft\rquote s data collection and use in the product documentation and the Microsoft Privacy Statement at {{\field{\*\fldinst{HYPERLINK http://go.microsoft.com/fwlink/?LinkID=521839 }}{\fldrslt{http://go.microsoft.com/fwlink/?LinkID=521839\ul0\cf0}}}}\f0\fs20 . You agree to comply with all applicable provisions of the Microsoft Privacy Statement.\par
+\b 6.\tab SCOPE OF LICENSE.\b0 The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to):\par
+
+\pard
+{\pntext\f0 a)\tab}{\*\pn\pnlvlbody\pnf0\pnindent0\pnstart1\pnlcltr{\pntxta)}}
+\widctlpar\s2\fi-360\li717\sb120\sa120 work around any technical limitations in the software that only allow you to use it in certain ways;\par
+{\pntext\f0 b)\tab}reverse engineer, decompile or disassemble the software;\par
+{\pntext\f0 c)\tab}remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;\par
+{\pntext\f0 d)\tab}use the software in any way that is against the law or to create or propagate malware; or\par
+{\pntext\f0 e)\tab}share, publish, or lend the software (except for any distributable code, and then subject to the applicable terms above), provide the software as a stand-alone hosted solution for others to use, or transfer the software or this agreement to any third party.\par
+
+\pard\widctlpar\s1\fi-357\li357\sb120\sa120\b 7.\tab EXPORT RESTRICTIONS.\b0 You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit (aka.ms/exporting).\par
+\b 8.\tab SUPPORT SERVICES.\b0 Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is \ldblquote as is\rdblquote , \ldblquote with all faults\rdblquote , and without warranty of any kind.\par
+\b 9.\tab UPDATES.\b0 The software may periodically check for updates, and download and install them for you. You may obtain updates only from Microsoft or authorized sources. Microsoft may need to update your system to provide you with updates. You agree to receive these automatic updates without any additional notice. Updates may not include or support all existing software features, services, or peripheral devices.\par
+\b 10.\tab BINDING ARBITRATION AND CLASS ACTION WAIVER.\b0 This Section applies if you live in (or, if a business, your principal place of business is in) the United States. If you and Microsoft have a dispute, you and Microsoft agree to try for 60 days to resolve it informally. If you and Microsoft can\rquote t, you and Microsoft agree to binding individual arbitration before the American Arbitration Association under the Federal Arbitration Act (\ldblquote FAA\rdblquote ), and not to sue in court in front of a judge or jury. Instead, a neutral arbitrator will decide. Class action lawsuits, class-wide arbitrations, private attorney-general actions, and any other proceeding where someone acts in a representative capacity are not allowed; nor is combining individual proceedings without the consent of all parties. The complete Arbitration Agreement contains more terms and is at aka.ms/arb-agreement-1. You and Microsoft agree to these terms.\par
+\b 11.\tab ENTIRE AGREEMENT.\b0 This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software.\par
+\b 12.\tab APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES.\b0 If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration).\par
+\b 13.\tab CONSUMER RIGHTS; REGIONAL VARIATIONS\b0 . This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state, province, or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state, province, or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you:\par
+
+\pard
+{\pntext\f0 a)\tab}{\*\pn\pnlvlbody\pnf0\pnindent0\pnstart1\pnlcltr{\pntxta)}}
+\widctlpar\s2\fi-360\li717\sb120\sa120\b Australia.\b0 You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.\par
+{\pntext\f0 b)\tab}\b Canada.\b0 If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software.\par
+{\pntext\f0 c)\tab}\b Germany and Austria\b0 .\par
+
+\pard\widctlpar\li717\sb120\sa120\b (i)\b0\tab\b Warranty.\b0 The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software.\par
+\b (ii)\b0\tab\b Limitation of Liability\b0 . In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law.\par
+
+\pard\widctlpar\s1\li717\sb120\sa120 Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence.\par
+
+\pard\widctlpar\s1\fi-357\li357\sb120\sa120\b 14.\tab DISCLAIMER OF WARRANTY.\b0 \b THE SOFTWARE IS LICENSED \ldblquote AS IS.\rdblquote YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.\b0\par
+\b 15.\tab LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.\par
+
+\pard\widctlpar\li357\sb120\sa120\b0 This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law.\par
+It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages.\par
+
+\pard\widctlpar\sb120\sa120\page\par
+
+\pard\widctlpar\sb120\sa120\qc EXHIBIT A\par
+THIRD PARTY NOTICES AND INFORMATION\par
+FOR\par
+MICROSOFT WINDOWS APPLICATION DRIVER\par
+
+\pard\widctlpar\sb120\sa120\par
+THIRD-PARTY SOFTWARE NOTICES AND INFORMATION\line\line Note: While Microsoft is not the author of the files below, Microsoft is offering you a license subject to the terms of the Microsoft Software License Terms for Microsoft Windows Application Driver (the \ldblquote Microsoft Program\rdblquote ). Microsoft reserves all other rights. The notices below are provided for informational purposes only and are not the license terms under which Microsoft distributes these files.\par
+The Microsoft Program includes the following third-party software:\par
+1.\tab Newtonsoft.json version 7.0. ({\b{\field{\*\fldinst{HYPERLINK http://www.newtonsoft.com/json }}{\fldrslt{http://www.newtonsoft.com/json\ul0\cf0}}}}\f0\fs20 )\par
+2.\tab Casablanca ({{\field{\*\fldinst{HYPERLINK http://casablanca.codeplex.com/ }}{\fldrslt{http://casablanca.codeplex.com/\ul0\cf0}}}}\f0\fs20 )\par
+As the recipient of the above third-party software, Microsoft sets forth a copy of the notices and other information below.\par
+1. Newtonsoft.json version 7.0.1 ({{\field{\*\fldinst{HYPERLINK http://www.newtonsoft.com/json }}{\fldrslt{http://www.newtonsoft.com/json\ul0\cf0}}}}\f0\fs20 )\par
+NEWTONSOFT.JSON NOTICES AND INFORMATION BEGIN HERE\line =========================================\par
+The MIT License (MIT)\line\line Copyright (c) 2007 James Newton-King\line\line Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\line\line The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\line\line THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\par
+NEWTONSOFT.JSON NOTICES AND INFORMATION END HERE\line =========================================\par
+2. Casablanca ({{\field{\*\fldinst{HYPERLINK http://casablanca.codeplex.com/ }}{\fldrslt{http://casablanca.codeplex.com/\ul0\cf0}}}}\f0\fs20 )\par
+CASABLANCA NOTICES AND INFORMATION BEGIN HERE\line =========================================\par
+Copyright (c) Microsoft Corporation. All rights reserved. \line Licensed under the Apache License, Version 2.0 (the "License");\line you may not use this file except in compliance with the License.\line You may obtain a copy of the License at\line {{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs20\line\line Unless required by applicable law or agreed to in writing, software\line\f1\fs19 distributed under the License is distributed on an "AS IS" BASIS,\line WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\line See the License for the specific language governing permissions and\line limitations under the License.\fs20\par
+\f0 CASABLANCA NOTICES AND INFORMATION END HERE\line =========================================\par
+\par
+
+\pard\sa200\sl276\slmult1\f2\fs22\lang9\par
+}
+
\ No newline at end of file
diff --git a/dep/WinAppDriver/Microsoft.Win32.Primitives.dll b/dep/WinAppDriver/Microsoft.Win32.Primitives.dll
new file mode 100644
index 00000000000..88ef2df5921
Binary files /dev/null and b/dep/WinAppDriver/Microsoft.Win32.Primitives.dll differ
diff --git a/dep/WinAppDriver/Microsoft.Win32.Registry.dll b/dep/WinAppDriver/Microsoft.Win32.Registry.dll
new file mode 100644
index 00000000000..397e3c6e44c
Binary files /dev/null and b/dep/WinAppDriver/Microsoft.Win32.Registry.dll differ
diff --git a/dep/WinAppDriver/MitaBroker.dll b/dep/WinAppDriver/MitaBroker.dll
new file mode 100644
index 00000000000..3e562b3aa2e
Binary files /dev/null and b/dep/WinAppDriver/MitaBroker.dll differ
diff --git a/dep/WinAppDriver/MitaLite.Foundation.dll b/dep/WinAppDriver/MitaLite.Foundation.dll
new file mode 100644
index 00000000000..ab8ad1589bb
Binary files /dev/null and b/dep/WinAppDriver/MitaLite.Foundation.dll differ
diff --git a/dep/WinAppDriver/MitaLite.Localization.dll b/dep/WinAppDriver/MitaLite.Localization.dll
new file mode 100644
index 00000000000..fac24db21fa
Binary files /dev/null and b/dep/WinAppDriver/MitaLite.Localization.dll differ
diff --git a/dep/WinAppDriver/MitaLite.UIAutomationAdapter.dll b/dep/WinAppDriver/MitaLite.UIAutomationAdapter.dll
new file mode 100644
index 00000000000..bdfaa17ef42
Binary files /dev/null and b/dep/WinAppDriver/MitaLite.UIAutomationAdapter.dll differ
diff --git a/dep/WinAppDriver/MitaLite.UIAutomationClient.dll b/dep/WinAppDriver/MitaLite.UIAutomationClient.dll
new file mode 100644
index 00000000000..7eb56878119
Binary files /dev/null and b/dep/WinAppDriver/MitaLite.UIAutomationClient.dll differ
diff --git a/dep/WinAppDriver/Newtonsoft.Json.dll b/dep/WinAppDriver/Newtonsoft.Json.dll
new file mode 100644
index 00000000000..be6558d2d48
Binary files /dev/null and b/dep/WinAppDriver/Newtonsoft.Json.dll differ
diff --git a/dep/WinAppDriver/Readme.txt b/dep/WinAppDriver/Readme.txt
new file mode 100644
index 00000000000..954b4cbe863
--- /dev/null
+++ b/dep/WinAppDriver/Readme.txt
@@ -0,0 +1,7 @@
+Windows Application Driver (Beta)
+
+For documentation, sample code, and logging issues:
+https://github.com/Microsoft/WinAppDriver
+
+To request new features and upvote requests filed by others:
+https://wpdev.uservoice.com
diff --git a/dep/WinAppDriver/System.Diagnostics.Process.dll b/dep/WinAppDriver/System.Diagnostics.Process.dll
new file mode 100644
index 00000000000..b98ff5369f9
Binary files /dev/null and b/dep/WinAppDriver/System.Diagnostics.Process.dll differ
diff --git a/dep/WinAppDriver/System.Threading.Thread.dll b/dep/WinAppDriver/System.Threading.Thread.dll
new file mode 100644
index 00000000000..6c4083137af
Binary files /dev/null and b/dep/WinAppDriver/System.Threading.Thread.dll differ
diff --git a/dep/WinAppDriver/WinAppDriver.exe b/dep/WinAppDriver/WinAppDriver.exe
new file mode 100644
index 00000000000..03b810a8d39
Binary files /dev/null and b/dep/WinAppDriver/WinAppDriver.exe differ
diff --git a/dep/WinAppDriver/WinAppDriverCore.dll b/dep/WinAppDriver/WinAppDriverCore.dll
new file mode 100644
index 00000000000..29f3b9279c2
Binary files /dev/null and b/dep/WinAppDriver/WinAppDriverCore.dll differ
diff --git a/dep/WinAppDriver/cpprest140_2_8.dll b/dep/WinAppDriver/cpprest140_2_8.dll
new file mode 100644
index 00000000000..e6bf31dec0d
Binary files /dev/null and b/dep/WinAppDriver/cpprest140_2_8.dll differ
diff --git a/dep/gsl b/dep/gsl
new file mode 160000
index 00000000000..b74b286d5e3
--- /dev/null
+++ b/dep/gsl
@@ -0,0 +1 @@
+Subproject commit b74b286d5e333561b0f1ef1abd18de2606624455
diff --git a/dep/nuget/nuget.exe b/dep/nuget/nuget.exe
new file mode 100644
index 00000000000..856263ded82
Binary files /dev/null and b/dep/nuget/nuget.exe differ
diff --git a/dep/packages/README.md b/dep/packages/README.md
new file mode 100644
index 00000000000..c1d56fb5698
--- /dev/null
+++ b/dep/packages/README.md
@@ -0,0 +1,7 @@
+These packages are redistributed inside this folder because they are not yet available on a public NuGet feed.
+
+## Microsoft.UI.XAML
+This package is a custom development build fork to help us light up tab support. It will eventually go onto the same public feed as the existing `Microsoft.UI.XAML` package that's currently available on NuGet.org
+
+## TAEF.Redist.WLK
+This package is vetted for public redistribution and release, but the TAEF team hasn't set up a public feed to consume it yet. If/when they do, we'll move to that.
diff --git a/dep/packages/microsoft.ui.xaml.2.1.190405001-prerelease.nupkg b/dep/packages/microsoft.ui.xaml.2.1.190405001-prerelease.nupkg
new file mode 100644
index 00000000000..dbc54406a5e
Binary files /dev/null and b/dep/packages/microsoft.ui.xaml.2.1.190405001-prerelease.nupkg differ
diff --git a/dep/packages/taef.redist.wlk.10.30.180808002.nupkg b/dep/packages/taef.redist.wlk.10.30.180808002.nupkg
new file mode 100644
index 00000000000..8b863b5d4cb
Binary files /dev/null and b/dep/packages/taef.redist.wlk.10.30.180808002.nupkg differ
diff --git a/dep/telemetry/ProjectTelemetry.h b/dep/telemetry/ProjectTelemetry.h
new file mode 100644
index 00000000000..23c5839f558
--- /dev/null
+++ b/dep/telemetry/ProjectTelemetry.h
@@ -0,0 +1,17 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- ProjectTelemetry.h
+
+Abstract:
+- This module is used for basic definitions for telemetry for the entire project
+--*/
+
+#define TraceLoggingOptionMicrosoftTelemetry() TraceLoggingOptionGroup(0x9aa7a361, 0x583f, 0x4c09, 0xb1, 0xf1, 0xce, 0xa1, 0xef, 0x58, 0x63, 0xb0)
+#define TelemetryPrivacyDataTag(tag) TraceLoggingUInt64((tag), "PartA_PrivTags")
+#define PDT_ProductAndServicePerformance 0x0u
+#define PDT_ProductAndServiceUsage 0x0u
+#define MICROSOFT_KEYWORD_TELEMETRY 0x0
+#define MICROSOFT_KEYWORD_MEASURES 0x0
\ No newline at end of file
diff --git a/dep/wil b/dep/wil
new file mode 160000
index 00000000000..fbcd1d2abb5
--- /dev/null
+++ b/dep/wil
@@ -0,0 +1 @@
+Subproject commit fbcd1d2abb558da4564ce343b688f7a658f51318
diff --git a/dirs b/dirs
new file mode 100644
index 00000000000..1af18876a3a
--- /dev/null
+++ b/dirs
@@ -0,0 +1,3 @@
+DIRS=\
+ src
+
diff --git a/doc/AddASetting.md b/doc/AddASetting.md
new file mode 100644
index 00000000000..64d93399cb0
--- /dev/null
+++ b/doc/AddASetting.md
@@ -0,0 +1,40 @@
+# Adding a Settings Property
+
+1. Add to wincon.w
+ * THIS IS NOT IN OPENCONSOLE. Make sure you update
+ `.../console/published/wincon.w` in the OS repo when you submit the PR.
+ The branch won't build without it.
+ * For now, you can update winconp.h with your consumable changes.
+ * define registry name (ex `CONSOLE_REGISTRY_CURSORCOLOR`)
+ * add the setting to `CONSOLE_STATE_INFO`
+ * define the property key ID and the property key itself
+ - Yes, the large majority of the `DEFINE_PROPERTYKEY` defs are the same, it's only the last byte of the guid that changes
+
+2. Add matching fields to Settings.hpp
+ - add getters, setters, the whole drill.
+
+3. Add to the propsheet.
+ - We need to add it to *reading and writing* the registry from the propsheet, and *reading* the link from the propsheet. Yes, that's weird, but the propsheet is smart enough to re-use ShortcutSerialization::s_SetLinkValues, but not smart enough to do the same with RegistrySerialization.
+ - `src/propsheet/registry.cpp`
+ - `propsheet/registry.cpp@InitRegistryValues` should initialize the default value for the property.
+ - `propsheet/registry.cpp@GetRegistryValues` should make sure to read the property from the registry
+
+4. Add the field to the propslib registry map
+
+5. Add the value to `ShortcutSerialization.cpp`
+ - Read the value in `ShortcutSerialization::s_PopulateV2Properties`
+ - Write the value in `ShortcutSerialization::s_SetLinkValues`
+
+6. Add the setting to `Menu::s_GetConsoleState`, and `Menu::s_PropertiesUpdate`
+Now, your new setting should be stored just like all the other properties.
+
+7. Update the feature test properties to get add the setting as well.
+ - `ft_uia/Common/NativeMethods.cs@WinConP`:
+ - `Wtypes.PROPERTYKEY PKEY_Console_`
+ - `NT_CONSOLE_PROPS`
+
+8. Add the default value for the setting to `win32k-settings.man`
+ - If the setting shouldn't default to 0 or `nullptr`, then you'll need to set the default value of the setting in `win32k-settings.man`.
+
+9. Update `Settings::InitFromStateInfo` and `Settings::CreateConsoleStateInfo` to get/set the value in a CONSOLE_STATE_INFO appropriately.
+
diff --git a/doc/ConsoleCtrlEvent.md b/doc/ConsoleCtrlEvent.md
new file mode 100644
index 00000000000..14dd95e911b
--- /dev/null
+++ b/doc/ConsoleCtrlEvent.md
@@ -0,0 +1,22 @@
+# Console Control Events
+
+## Generation
+
+conhost requests that user32 inject a thread into the attached console application.
+See ntuser's exitwin.c for `CreateCtrlThread`.
+
+## Timeouts
+
+_Sourced from ntuser's **exitwin.c**, **user.h**_
+
+| Event | Circumstances | Timeout |
+|------------------------|---------------------------------|-------------------------------------------------------------|
+| `CTRL_CLOSE_EVENT` | _any_ | system parameter `SPI_GETHUNGAPPTIMEOUT`, 5000ms |
+| `CTRL_LOGOFF_EVENT` | `CONSOLE_QUICK_RESOLVE_FLAG`[1] | registry key `CriticalAppShutdownTimeout` or 500ms |
+| `CTRL_LOGOFF_EVENT` | _none of the above_ | system parameter `SPI_GETWAITTOKILLTIMEOUT`, 5000ms |
+| `CTRL_SHUTDOWN_EVENT` | **service process** | system parameter `SPI_GETWAITTOKILLSERVICETIMEOUT`, 20000ms |
+| `CTRL_SHUTDOWN_EVENT` | `CONSOLE_QUICK_RESOLVE_FLAG`[1] | registry key `CriticalAppShutdownTimeout` or 500ms |
+| `CTRL_SHUTDOWN_EVENT` | _none of the above_ | system parameter `SPI_GETWAITTOKILLTIMEOUT`, 5000ms |
+| `CTRL_C`, `CTRL_BREAK` | _any_ | **no timeout** |
+
+_[1]: nobody sets `CONSOLE_QUICK_RESOLVE_FLAG`._
diff --git a/doc/ConsoleHostSettings.md b/doc/ConsoleHostSettings.md
new file mode 100644
index 00000000000..31b056e7e39
--- /dev/null
+++ b/doc/ConsoleHostSettings.md
@@ -0,0 +1,70 @@
+# Understanding Console Host Settings
+
+Settings in the Windows Console Host can be a bit tricky to understand. This is mostly because the settings system evolved over the course of decades. Before we dig into the details of how settings are persisted, it's probably worth a quick look at what these settings are.
+
+## Settings Description
+
+|Name |Type |Description |
+|---------------------------|-----------------------|--------------------------------------|
+|`FontSize` |Coordinate (REG_DWORD) |Size of font in pixels |
+|`FontFamily` |REG_DWORD |GDI Font family |
+|`ScreenBufferSize` |Coordinate (REG_DWORD) |Size of the screen buffer in WxH characters |
+|`CursorSize` |REG_DWORD |Cursor height as percentage of a single character |
+|`WindowSize` |Coordinate (REG_DWORD) |Initial size of the window in WxH characters |
+|`WindowPosition` |Coordinate (REG_DWORD) |Initial position of the window in WxH pixels (if not set, use auto-positioning) |
+|`WindowAlpha` |REG_DWORD |Opacity of the window (valid range: 0x4D-0xFF) |
+|`ScreenColors` |REG_DWORD |Default foreground and background colors |
+|`PopupColors` |REG_DWORD |FG and BG colors used when displaying a popup window (e.g. when F2 is pressed in CMD.exe) |
+|`QuickEdit` |REG_DWORD |Whether QuickEdit is on by default or not |
+|`FaceName` |REG_SZ |Name of font to use (or "__DefaultTTFont__", which defaults to whichever font is deemed most appropriate for your codepage) |
+|`FontWeight` |REG_DWORD |GDI font weight |
+|`InsertMode` |REG_DWORD |Whether Insert mode is on by default or not |
+|`HistoryBufferSize` |REG_DWORD |Number of history entries to retain |
+|`NumberOfHistoryBuffers` |REG_DWORD |Number of history buffers to retain |
+|`HistoryNoDup` |REG_DWORD |Whether to retain duplicate history entries or not |
+|`ColorTable%%` |REG_DWORD |For each of the 16 colors in the palette, the RGB value of the color to use |
+|`ExtendedEditKey` |REG_DWORD |Whether to allow the use of extended edit keys or not |
+|`WordDelimiters` |REG_SZ |A list of characters that are considered as delimiting words (e.g. `' .-/\=|,()[]{}'`) |
+|`TrimLeadingZeros` |REG_DWORD |Whether to remove zeroes from the beginning of a selected string on copy (e.g. `00000001` becomes `1`) |
+|`EnableColorSelection` |REG_DWORD |Whether to allow selection colorization or not |
+|`ScrollScale` |REG_DWORD |How many lines to scroll when using `SHIFT|Scroll Wheel` |
+|`CodePage` |REG_DWORD |The default codepage to use |
+|`ForceV2` |REG_DWORD |Whether to use the improved version of the Windows Console Host |
+|`LineSelection`* |REG_DWORD |Whether to use wrapped text selection |
+|`FilterOnPaste`* |REG_DWORD |Whether to replace characters on paste (e.g. Word "smart quotes" are replaced with regular quotes) |
+|`LineWrap`* |REG_DWORD |Whether to have the Windows Console Host break long lines into multiple rows |
+|`CtrlKeyShortcutsDisabled`*|REG_DWORD |Disables new control key shortcuts |
+|`AllowAltF4Close`* |REG_DWORD |Allows the user to disable the Alt-F4 hotkey |
+|`VirtualTerminalLevel`* |REG_DWORD |The level of VT support provided by the Windows Console Host |
+
+*: Only applies to the improved version of the Windows Console Host
+
+## The Settings Hierarchy
+
+Settings are persisted to a variety of locations depending on how they are modified and how the Windows Console Host was invoked:
+* Hardcoded settings in conhostv2.dll
+* User's configured defaults (stored as values in `HKCU\Console`)
+* Per-console-application storage (stored as subkeys of `HKCU\Console`). Subkey names:
+ * Console application path (with `\` replaced with `_`)
+ * Console title
+* Windows shortcut (.lnk) files
+
+To modify the defaults, invoke the `Defaults` titlebar menu option on a Windows Console Host window. Any changes made in the resulting dialog will be persisted to the registry location mentioned above.
+
+To modify settings specific to the current application, invoke the `Properties` titlebar menu option on a Windows Console Host window. If the application was launched directly (e.g. via the Windows run dialog), changes made in the dialog will be persisted in the per-application storage location mentioned above. If the application was launched via a Windows shortcut file, changes made in the settings dialog will be persisted directly into the .lnk file. For console applications with a shortcut, you can also right-click on the shortcut file and choose `Properties` to access the settings dialog.
+
+When console applications are launched, the Windows Console Host determines which settings to use by overlaying settings from the above locations.
+
+1. Initialize settings based on hardcoded defaults
+2. Overlay settings specified by the user's configured defaults
+3. Overlay application-specific settings from either the registry or the shortcut file, depending on how the application was launched
+
+Note that the registry settings are "sparse" settings repositories, meaning that if a setting isn't present, then whatever value that is already in use remains unchanged. This allows users to have some settings shared amongst all console applications and other settings be specific. Shortcut files, however, store each setting regardless of whether it was a default setting or not.
+
+## Known Issues
+
+* Modifications to system-created Start Menu and Win-X menu console applications are not kept during upgrade.
+
+## Adding settings
+
+Adding a setting involves a bunch of steps - see [AddASetting.md](AddASetting.md).
diff --git a/doc/Debugging.md b/doc/Debugging.md
new file mode 100644
index 00000000000..e4f84613e2e
--- /dev/null
+++ b/doc/Debugging.md
@@ -0,0 +1,10 @@
+# Debugging Miscellanea
+
+This file contains notes about debugging various items in the repository.
+
+## Setting breakpoints in Visual Studio for Cascadia (packaged) application
+
+If you want to debug code in the Cascadia package via Visual Studio, your breakpoints will not be hit by default. A tweak is required to the *CascadiaPackage* project in order to enable this.
+
+1. Right-click on *CascadiaPackage* in Solution Explorer and select Properties
+2. Change the *Application process* type from *Mixed (Managed and Native)* to *Native Only*.
\ No newline at end of file
diff --git a/doc/EXCEPTIONS.md b/doc/EXCEPTIONS.md
new file mode 100644
index 00000000000..0161451f267
--- /dev/null
+++ b/doc/EXCEPTIONS.md
@@ -0,0 +1,36 @@
+# Using Exceptions
+
+## Philosophy
+Introducing exceptions to an existing non-exception-based codebase can be perilous. The console was originally written
+in C at a time when C++ was relatively unused in the Windows operating system. As part of our project to modernize the
+Windows console, we converted to use C++, but still had an aversion to using exception-based error handling in
+our code for fear that it introduce unexpected failures. However, the STL and other libraries like it are so useful that
+sometimes it's significantly simpler to use them. Given that, we have a set of rules that we follow when considering
+exception use.
+
+## Rules
+1. **DO NOT** allow exceptions to leak out of new code into new code
+1. **DO** use NTSTATUS or HRESULT as return values as appropriate
+1. **DO** Encapsulate all exception behaviors within implementing classes
+1. **DO NOT** introduce modern exception throwing code into old code. Instead, refactor as needed to allow encapsulation or
+ use non-exception based code
+1. **DO** use WIL as an alternative for non-throwing modern facilities (e.g. wil::unique_ptr<>)
+
+## Examples
+
+### Encapsulating exception behaviors in a class
+
+ class ExceptionsDoNotLeak
+ {
+ public:
+ HRESULT SomePublicFunction();
+ int iPublic;
+
+ private:
+ void _SomePrivateFunction();
+ int _iPrivate;
+ };
+
+### Using WIL for non-throwing modern facilities
+
+###
\ No newline at end of file
diff --git a/doc/ORGANIZATION.md b/doc/ORGANIZATION.md
new file mode 100644
index 00000000000..f7780d6d036
--- /dev/null
+++ b/doc/ORGANIZATION.md
@@ -0,0 +1,123 @@
+# Code Organization
+
+## Rules
+
+- **Follow the pattern of what you already see in the code**
+- Try to package new ideas/components into libraries that have nicely defined interfaces
+- Package new ideas into classes or refactor existing ideas into a class as you extend.
+- Each project should have a Unit test in a ut_ folder in its subdirectory (like `ut_host`)
+- Functional tests should be in ft_ subdirectories (like `ft_api`)
+- Build scripts are generally in subdirectories with their type of output (like `/dll` or `/exe`)
+- Try to place interfaces in an `inc` folder in an appropriate location
+- Structure related libraries together (`/terminal/parser` and `/terminal/adapter`)
+
+## Code Overview
+* `/` - root is where solution files, root MD documentation, SD replication artifacts go.
+* `/bin` – not checked in is where binaries will be generated by the MSBuild system
+* `/dep` – dependencies that aren’t a part of the SDK
+ * `/dep/console` – files that are currently in the internal-only private SDK for the console but we’re working on opening
+ * `/dep/DDK` – files lifted wholesale from the public Microsoft DDK so you don’t have to install that. We’re reducing dependencies on these but we still use TAEF (included in here) as our test runner engine
+ * `/dep/NT` – some more structures from the DDK, sometimes internal-only/non-public we’re trying to remove.
+ * `/dep/telemetry` – Private Microsoft telemetry headers
+ * `/dep/wil` – Windows Internal Library – extremely useful for interfacing with Win32/NT/COM APIs. Contains tons of “unique pointer” like syntax for various Win32 APIs and a handful of useful macros to enable cleaner code writing (RETURN_HR_IF, LOG_IF_WIN32_ERROR, etc.)
+ * `/dep/win32k` – private headers from the Windows windowing system that we’re trying to migrate off of
+* `/ipch` – not checked in is where intellisense data will be generated if you use Visual Studio 2015
+* `/obj` – not checked in is where objects will be generated by the MSBuild system
+* `/src` – This is the fun one. In the root is common build system data.
+ * `/src/host` – The meat of the windows console host. This includes buffer, input, output, windowing, server management, clipboard, and most interactions with the console host window that aren’t stated anywhere else. We’re trying to pull things out that are reusable into other libraries, but it’s a work in progress
+ * `/src/host/lib` – Builds the reusable LIB copy of the host
+ * `/src/host/dll` – Packages LIB into conhostv2.dll to be put into the OS C:\windows\system32\
+ * `/src/host/exe` – Packages LIB into OpenConsole.exe currently used for testing without replacing your system32 copy
+ * `/src/host/tools` – Random odds and ends that make testing/debugging/development a bit easier
+ * ...to be doc’d, each of what these are
+ * `/src/host/ut_host` – Contains complete unit test library for everything we’ve managed to get unit tests on. We’d like all new code to contribute appropriate unit tests in here
+ * `/src/host/ft_api` – Feature level tests for anything that changes the way we interact with the outside world via the API. Building these up as we work as well
+ * `/src/host/ft_cjk` – Double-wide/double-byte specific Chinese/Japanese/Korean language tests that previously had to be run in a different environment. To be merged into ft_api one day
+ * `/src/host/ft_resize` – Special test for resizing/reflowing the buffer window
+ * `/src/host/ft_uia` – Currently disabled (for not being very reliable) UI Automation tests that we are looking to re-enable and expand to do UI Automation coverage of various human interactions
+ * `/src/host/...` - The files I’ll list out below
+ * `/src/inc` – Include files that are shared between the host and some of the other libraries. This is only some of them. The include story is kind of a mess right now, but we’d like to clean it up at some point
+ * `/src/propslib` – Library shared between console host and the OS shell “right click a shortcut file and modify console properties” page to read/write user settings to and from the registry and embedded within shortcut LNK data
+ * `/src/renderer` – Refactored extraction of all activities related to rendering the text in the buffers onto the screen
+ * `/src/renderer/base` – Base interface layer providing non-engine-specific rendering things like choosing the data from the console buffer, deciding how to lay out or transform that data, then dispatching commands to a specific final display engine
+ * `/src/renderer/gdi` – The GDI implementation of rendering to the screen. Takes commands to “draw a line” or “fill the background” or “select a region” from the base and turns them into GDI calls to the screen. Extracted from original console host code.
+ * `/src/renderer/inc – Interface definitions for all renderer communication
+ * `/src/terminal` – Virtual terminal support for the console. This is the sequences that are found in-band with other text on STDIN/STDOUT that command the display to do things. This is the *nix way of controlling a console.
+ * `/src/terminal/parser` – This contains a state machine and sorting engine for feeding in individual characters from STDOUT or STDIN and decoding them into the appropriate verbs that should be performed
+ * `/src/terminal/adapter` – This converts the verbs from the interface into calls on the console API. It doesn’t actually call through the API (for performance reasons since it lives inside the same binary), but it tries to remain as close to an API call as possible. There are some private extensions to the API for behaviors that didn’t exist before this was written that we’ve not made public. We don’t know if we will yet or force people to use VT to get at them.
+ * `/src/tsf` – Text Services Foundation. This provides IME input services to the console. This was historically used for only Chinese, Japanese, and Korean IMEs specifically on OS installations with those as the primary language. It was in the summer of 2016 unrestricted to be able to be used on any OS installation with any IME (whether or not it will display correctly is a different story). It also was unrestricted to allow things like Pen and Touch input (which are routed via IME messages) to display properly inside the console from the TabTip window (the little popup that helps you insert pen/touch writing/keyboard candidates into an application)
+
+## Host File Overview
+
+* Generally related to handling input/output data and sometimes intertwined with the actual service calls
+ * `_output.cpp`
+ * `_stream.cpp`
+* Handles copy/paste/etc.
+ * `clipboard.cpp`
+* Handles the command prompt line as you see in CMD.exe (known as the processed input line… most other shells handle this themselves with raw input and don’t use ours. This is a legacy of bad architectural design, putting stuff in conhost not in CMD)
+ * `cmdline.cpp`
+* Handles shunting IME data back and forth to the TSF library and to and from the various buffers
+ * `Conimeinfo.cpp`
+ * `Convarea.cpp`
+* Contains the global state for the entire console application
+ * `consoleInformation.cpp`
+* Stuff related to the low-level server communication over our protocol with the driver
+ * `Csrutil.cpp`
+ * `Srvinit.cpp`
+ * `Handle.cpp`
+* Routines related to startup of the application
+ * `Srvinit.cpp`
+* Routines related to the API calls (and the servicing thereof, muxes a bit with the server protocol)
+ * `Directio.cpp`
+ * `Getset.cpp`
+ * `Srvinit.cpp`
+* Extra stuff strapped onto the buffer to enable CJK languages
+ * `Dbcs.cpp`
+* Attempted class-ification of existing Cursor structures to take them out of Screen Info/Text Info
+ * `Cursor.cpp`
+* Related to searching through the back buffer of the console (the output scroll buffer as defined in screeninfo/textinfo)
+ * `Find.cpp`
+* Contains global state data
+ * `Globals.cpp`
+* Attempted class-ification of existing Icon manipulation to take them out of ConsoleInformation/Settings
+ * `Icon.cpp`
+* Contains all keyboard/mouse input handling, capture of keys, conversion of keys, and some manipulation of the input buffer
+ * `Input.cpp`
+ * `Inputkeyinfo.cpp`
+ * `Inputreadhandledata.cpp`
+* Main entry point used ONLY by the OS to send a pre-configured driver handle to conhostv2.dll
+ * `Main.cpp`
+* Assorted utilities and stuff
+ * `Misc.cpp` (left for us by previous eras of random console devs)
+ * `Util.cpp` (created in our era)
+* Custom zeroing and non-throwing allocator
+ * `Newdelete.cpp`
+* Related to inserting text into the TextInfo buffer
+ * `Output.cpp`
+ * `Stream.cpp`
+* Connects to interfaces in the PropsLib to manipulate persistent settings state
+ * `Registry.cpp`
+* Connects to our relatively recently extracted renderer LIB to give it data about console state and user prefs
+ * `renderData.cpp`
+ * `renderFontDefaults.cpp`
+* Maintains most of the information about what we should present inside the window on the screen (sizes, dimensions, also holds a text buffer instance and a cursor instance and a selection instance)
+ * `screenInfo.cpp`
+* Handles some aspects of scrolling with the mouse and keyboard
+ * `Scrolling.cpp`
+* Handles the click-and-drag highlighting of text on the screen to select (or the keyboard-based Mark mode selection where you can enter the mode and select around). Often calls clipboard when done
+ * `Selection.cpp`
+ * `selectionInput.cpp`
+ * `selectionState.cpp`
+* Handles all user preferences and state. Was extracted from consoleInformation and CI subclasses it still (because it was hard to break the association out)
+ * `Settings.cpp`
+* Good ol’ Windows 10 telemetry pipeline & ETW events as debugging aids (they use the same channel with a different flag)
+ * `Telemetry.cpp`
+ * `Tracing.cpp`
+* Private calls into the Windows Window Manager to perform privileged actions related to the console process (working to eliminate) or for High DPI stuff (also working to eliminate)
+ * `Userprivapi.cpp`
+ * `Windowdpiapi.cpp`
+* New UTF8 state machine in progress to improve Bash (and other apps) support for UTF-8 in console
+ * `Utf8ToWideCharParser.cpp`
+* Window resizing/layout/management/window messaging loops and all that other stuff that has us interact with Windows to create a visual display surface and control the user interaction entry point
+ * `Window.cpp`
+ * `Windowproc.cpp`
diff --git a/doc/STYLE.md b/doc/STYLE.md
new file mode 100644
index 00000000000..5deb15d6b23
--- /dev/null
+++ b/doc/STYLE.md
@@ -0,0 +1,7 @@
+# Coding Style
+
+## Philosophy
+1. If it's inserting something into the existing classes/functions, try to follow the existing style as closely as possible.
+1. If it's brand new code or refactoring a complete class or area of the code, please follow as Modern C++ of a style as you can and reference the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) as much as you possibly can.
+1. When working with any Win32 or NT API, please try to use the [Windows Internal Library](./WIL.md) smart pointers and result handlers.
+1. The use of NTSTATUS as a result code is discouraged, HRESULT or exceptions are preferred. Functions should not return a status code if they would always return a successful status code. Any function that returns a status code should be marked `noexcept` and have the `nodiscard` attribute.
diff --git a/doc/TAEF.md b/doc/TAEF.md
new file mode 100644
index 00000000000..65d06c2f874
--- /dev/null
+++ b/doc/TAEF.md
@@ -0,0 +1,20 @@
+### TAEF ###
+TAEF, the Test Authoring and Execution Framework, is used extensively within the Windows organization to test the operating system code in a unified manner for system, driver, and application code. As the console is a Windows OS Component, we strive to continue using the same system such that tests can be ran in a unified manner both externally to Microsoft as well as inside the official OS Build/Test system.
+
+The [official documentation](https://msdn.microsoft.com/en-us/library/windows/hardware/hh439725\(v=vs.85\).aspx) for TAEF describes the basic architecture, usage, and functionality of the test system. It is similar to Visual Studio test, but a bit more comprehensive and flexible.
+
+For the purposes of the console project, you can run the tests using the *TE.exe* that matches the architecture for which the test was build (x86/x64) in the pattern
+
+ te.exe Console.Unit.Tests.dll
+
+Replacing the binary name with any other test binary name that might need running. Wildcard patterns or multiple binaries can be specified and all found tests will be executed.
+
+Limiting the tests to be run is also useful with:
+
+ te.exe Console.Unit.Tests.dll /name:*BufferTests*
+
+Any pattern of class/method names can be specified after the */name:* flag with wildcard patterns.
+
+For any further details on the functionality of the TAEF test runner, *TE.exe*, please see the documentation above or run the embedded help with
+
+ te.exe /!
diff --git a/doc/UniversalTest.md b/doc/UniversalTest.md
new file mode 100644
index 00000000000..04fa44d8349
--- /dev/null
+++ b/doc/UniversalTest.md
@@ -0,0 +1,117 @@
+# Universal Testing for Console
+
+## Overview
+
+Universal Testing is the Microsoft framework for creating and deploying test packages onto just about any device through just about any process. We use it for packaging up all sorts of test resources and sending it into our automated test labs no matter what the source of the content or the engineering system involved.
+
+It involves several parts:
+- TESTMD
+ - These define a package unit for deployment to the test device. This usually includes the test binaries and any dependent data that it will need to execute.
+ - There can also be a hierarchy where one package can depend on another such that packages can be re-used
+
+- TESTLIST
+ - This defines a batch of TESTMD packages that should be executed together.
+
+- TESTPASSES
+ - This defines a list of tests via a TESTLIST and a lab environment configuration on which the tests should be run
+
+ These files can either include their child element as they're supposed to (TESTMDs included in TESTLISTs) or they can often include themselves to provide chain structuring (one TESTLIST can reference another TESTLIST).
+
+- TREX
+ - This is the legacy configuration system that performed the same job as TESTPASSES, but not in source files.
+
+## Configuration
+
+ This is a record of the current setup (as of Mar-1-2019) of the console's universal tests. This series of steps was created in conjunction with converting the console's testing from the legacy TREX dispatching mode to the new TESTPASSES dispatching mode for the Source Is Truth initiative (define all testing metadata in source next to the code being tested, instead of in a separate database somewhere else).
+
+1. Have some TestMDs.
+ - \onecore\windows\core\console\open\src\host\ut_host\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-Host-UnitTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.Host.UnitTests.testmd
+ 1. Microsoft-Console-Host-UnitTests.cab
+ 1. Microsoft-Console-Host-UnitTests.man.dsm.xml
+ - \onecore\windows\core\console\open\src\host\ft_host\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-Host-FeatureTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.Host.FeatureTests.testmd
+ 1. Microsoft-Console-Host-FeatureTests.cab
+ 1. Microsoft-Console-Host-FeatureTests.man.dsm.xml
+ - \onecore\windows\core\console\open\src\buffer\out\ut_textbuffer\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-TextBuffer-UnitTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.TextBuffer.UnitTests.testmd
+ 1. Microsoft-Console-TextBuffer-UnitTests.cab
+ 1. Microsoft-Console-TextBuffer-UnitTests.man.dsm.xml
+ - \minkernel\console\client\ut_conpty\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-ConPty-UnitTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.ConPty.UnitTests.testmd
+ 1. Microsoft-Console-ConPty-UnitTests.cab
+ 1. Microsoft-Console-ConPty-UnitTests.man.dsm.xml
+ - \onecore\windows\core\console\open\src\terminal\parser\ut_parser\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-VirtualTerminal-Parser-UnitTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.VirtualTerminal.Parser.UnitTests.testmd
+ 1. Microsoft-Console-VirtualTerminal-Parser-UnitTests.cab
+ 1. Microsoft-Console-VirtualTerminal-Parser-UnitTests.man.dsm.xml
+ - \onecore\windows\core\console\open\src\terminal\adapter\ut_adapter\testmd.definition + SOURCES file
+ - Generates “Microsoft-Console-VirtualTerminal-Adapter-UnitTests” TESTMD and package
+ - Binplaces to prebuilt\test\\\
+ 1. Microsoft.Console.VirtualTerminal.Adapter.UnitTests.testmd
+ 1. Microsoft-Console-VirtualTerminal-Adapter-UnitTests.cab
+ 1. Microsoft-Console-VirtualTerminal-Adapter-UnitTests.man.dsm.xml
+1. Have some TESTLISTs that refer to the TESTMDs
+ - \onecore\windows\core\console\open\src\testlist\Microsoft.Console.Tests.testlist + SOURCES file
+ - Includes
+ 1. Microsoft.Console.Host.UnitTests.testmd
+ 1. Microsoft.Console.Host.FeatureTests.testmd
+ 1. Microsoft.Console.TextBuffer.UnitTests.testmd
+ 1. Microsoft.Console.Conpty.UnitTests.testmd
+ 1. Microsoft.Console.VirtualTerminal.Parser.UnitTests.testmd
+ 1. Microsoft.Console.VirtualTerminal.Adapter.UnitTests.testmd
+ - Binplaces to prebuilt\test\\\
+ - Microsoft.Console.Tests.testlist
+ - \onecore\windows\core\console\open\src\testlist\Microsoft.Console.TestLab.Desktop.testlist + SOURCES file
+ - Includes
+ 1. Microsoft.Console.Tests.testlist
+ - Binplaces to prebuilt\test\\\
+ - Microsoft.Console.TestLab.Desktop.testlist
+ - Is currently the subject of TREX IDs
+ 1. 153251 – TESTLIST based AMD64 Desktop VM testpass (to be offboarded when done)
+ 1. 153252 – TESTLIST based X86 Desktop VM testpass (to be offboarded when done)
+ - \onecore\windows\core\console\open\src\testlist\Microsoft.Console.TestLab.OneCoreUap.testlist + SOURCES file
+ - Includes
+ 1. Microsoft.Console.Tests.testlist
+ - Binplaces to prebuilt\test\\\
+ - Microsoft.Console.TestLab.OneCoreUAP.testlist
+ - Is currently the subject of TREX IDs
+ 1. 153253 – TESTLIST based AMD64 OneCoreUAP VM testpass (to be offboarded when done)
+ 1. 153254 – TESTLIST based X86 OneCoreUAP VM testpass (to be offboarded when done)
+1. Create some TESTPASSES
+ - For the existing OneCoreUAP ones…
+ - Create directory \onecoreuap\testpasses\local\console\
+ - Create file console_onecoreuap.testpasses
+ 1. Create AMD64 pass
+ - Name it similarly to the existing name
+ - Use the environment $(TESTPASSES_ONECOREUAP)/standard_testenvs/OneCoreUAP-amd64-VM.testenv
+ - Connect to the testlist $(TESTLIST_SEARCH_PATHS)/Microsoft.Console.TestLab.OneCoreUAP.testlist
+ 1. Create X86 pass
+ - Name it similarly to the existing name
+ - Use the environment $(TESTPASSES_ONECOREUAP)/standard_testenvs/OneCoreUAP-x86-VM.testenv
+ - Connect to the testlist $(TESTLIST_SEARCH_PATHS)/Microsoft.Console.TestLab.OneCoreUAP.testlist
+ - For the Desktop ones…
+ - Create directory \pcshell\testpasses\local\console\
+ - Create file console_desktop.testpasses
+ 1. Create AMD64 pass
+ - Name it similarly to the existing name
+ - Use the environment $(TESTPASSES_PCSHELL)/standard_testenvs/Enterprise-amd64-VM.testenv
+ - Connect to the testlist $(TESTLIST_SEARCH_PATHS)/Microsoft.Console.TestLab.Desktop.testlist
+ 1. Create X86 pass
+ - Name it similarly to the existing name
+ - Use the environment $(TESTPASSES_PCSHELL)/standard_testenvs/Enterprise-x86-VM.testenv
+ - Connect to the testlist $(TESTLIST_SEARCH_PATHS)/Microsoft.Console.TestLab.Desktop.testlist
+1. Hook up the TESTPASSES into the official branch TESTPASSES file
+ - Open up \.branchconfig\official\rs_onecore_dep_acidev\official_build.testpasses
+ 1. Add TestpassReferences item targeting $(TESTPASSES_ONECOREUAP)/local/console/console_onecoreuap.testpasses
+ 1. Add TestpassReferences item targeting $(TESTPASSES_PCSHELL)/local/console/console_desktop.testpasses
diff --git a/doc/WIL.md b/doc/WIL.md
new file mode 100644
index 00000000000..4a73fbb2a0c
--- /dev/null
+++ b/doc/WIL.md
@@ -0,0 +1,27 @@
+# Windows Internal Library
+
+## Overview
+Windows Internal Library, or WIL, is a header-only library created to help make working with the Windows API more predictable and (hopefully) bug free.
+
+A majority of functions are in either the `wil::` or `wistd::` namespace. `wistd::` is used for things that have an equivalent in STL's `std::` namespace but have some special functionality like being exception-free. Everything else is in `wil::` namespace.
+
+The primary usages of WIL in our code so far are...
+
+### Smart Pointers ###
+
+Inside [wil\resource.h](..\dep\wil\resource.h) are smart pointer like classes for many Windows OS resources like file handles, socket handles, process handles, and so on. They're of the form `wil::unique_handle` and call the appropriate/matching OS function (like `CloseHandle()` in this case) when they go out of scope.
+
+Another useful item is `wil::make_unique_nothrow()` which is analogous to `std::make_unique` (except without the exception which might help you integrate with existing exception-free code in the console.) This will return a `wistd::unique_ptr` (vs. a `std::unique_ptr`) which can be used in a similar manner.
+
+### Result Handling ###
+
+To manage the various types of result codes that come back from Windows APIs, the file [wil\result.h](..\dep\wil\result.h) provides a wealth of macros that can help.
+
+As an example, the method `DuplicateHandle()` returns a `BOOL` value that is `FALSE` under failure and would like you to `GetLastError()` from the operating system to find out what the actual result code is. In this circumstance, you could use the macro `RETURN_IF_WIN32_BOOL_FALSE` to wrap the call to `DuplicateHandle()` which would automatically handle this pattern for you and return the `HRESULT` equivalent on failure.
+
+This leads to nice patterns where you can set up all resources in a function as protected by `std::unique_ptr` or the various `wil::` smart pointers and smart handles then `RETURN_IF_*` on every call to a Windows API and be guaranteed that your resources will be cleaned up appropriately under any failure case. Do note that this generally requires you to return an `HRESULT` as your return code and use out pointer parameters for return data. There are exceptions to this... read the header for more details.
+
+The additional advantage to using this pattern is that failures at any point are logged to our global tracing/debugging channels to be viewed under the debugger output with the exact line number and function details for the error.
+
+Additionally, if you just want to make sure that a failure case is logged for debugging purposes, all of these macros have a `LOG_IF_*` equivalent that will simply log a failure and keep rolling.
+
diff --git a/doc/WindowsTestPasses.md b/doc/WindowsTestPasses.md
new file mode 100644
index 00000000000..eee4ec93fb5
--- /dev/null
+++ b/doc/WindowsTestPasses.md
@@ -0,0 +1,42 @@
+# Windows Test Passes for Console
+
+## Overview
+
+Every night, we run a set of automated test passes in the Windows engineering system for the console host code. This process is orchestrated on our working branch, which at the time of this writing is `RS_ONECORE_DEP_ACIDEV` (and will soon switch back to `RS_ONECORE_DEP_ACIOSS` or something of that ilk).
+
+You can find the information about our nightly build, including these test passes, at the website [https://es.microsoft.com], choosing our branch, and then navigating to the `Execution Status` page.
+
+At the bottom of the page will be the test pass runs for our tests that night. You can find out more about how these are set up in the [UniversalTest.md] file.
+
+When a failure occurs in one of these passes, a bug will automatically be generated in the Azure DevOps project for the OS and assigned to our path.
+
+The next step would be investigating one of these failures...
+
+## Investigation
+
+A quick overview of investigation... normally you can just attempt to build and reproduce the failure locally with the `OpenConsole` project and it will happen the same way as it did on the nightly build in the lab. However, sometimes the failure will be exclusive to the lab or won't happen in the same way as it does on your local dev machine. At that point, you need to move into setting up the environment as it was during the testpass and figuring out what went wrong.
+
+You can try to do this all manually by pulling down a VM image from the release share for the nightly build, making a VM, deploying the test binaries and TAEF test runnner executables to the machine, installing the VS Remote Debugging or WinDBG tools on the VM, and then running the test and figuring out what's going wrong with the debuggers.
+
+Or you can use some of the Engineering Systems tools to make this easier. I'll detail how to do that below.
+
+Prerequisites:
+- Visual Studio 2017
+- Install the TDP (Test Development Platform) plug-in (see: [https://osgwiki.com/wiki/Test_Development_Platform_(TDP)]).
+
+1. Open Visual Studio 2017 and use the TDP drop-down menu to open the `Device Manager`
+1. In the pane that opens to the left, choose `Add` and then `Nebula VM Device`. Nebula is a cloud provider for VMs (like Azure but a more private instance for corporate work usage).
+1. Name the machine and choose the build/branch/flavor/SKU from the drop downs at the bottom. It will find the VHD for you from the build shares. Hit `Add Device` to deploy to Nebula
+1. Wait a few minutes. It took 5-10 for it to be deployed.
+1. Right click the machine name in the `Device Manager` list and choose `Launch T-Shell`. You can also use `Connect via Console` to get a "remote desktop"-like session to the KVM port on the VM.
+1. In T-shell, use `testd Microsoft.Console.TestLab.Desktop.testlist` or a command of that format with a different TESTLIST or TESTMD name from our project (see the [UniversalTest.md] documentation). The `testd` utility will automatically resolve the build/branch/flavor information, dig through the build shares for the matching TESTLIST/TESTMD metadata, and attempt to deploy all relevent packages and dependencies on the device. When it's successful, it will move onto running all the tests and giving you the results. On conclusion, the test results should pop up in the web browser or the `Hubble - Log Viewer` tool provided by the Engineering Systems team.
+
+If some of the above things do not work, go to [https://osgwiki.com] and type them into the Search bar. For instance, if T-Shell isn't found or working, you can find out where to get it or download it on `OSGWiki`. The same goes for the other commands besides `testd` to use in T-shell and more information on what `Hubble` or `Nebula` are.
+
+Presumably now you have a failure. Or a success. You can attempt to spelunk the logs in `Hubble` and you might come to a conclusion. Or you can move onto debugging directly.
+
+Now that you've relied on `testd` to get everything deployed and orchestrated and run once on the device, you can use `execd` to run things again or to run a smaller subset of things on the remote device through `T-Shell`.
+
+By default, in the `Universal Test` world, everything will be deployed onto the remote machine at `C:\data\test\bin`. In T-Shell, use `cdd C:\data\test\bin` to change to that directory and then `execd te.exe Microsoft.Console.Host.FeatureTests.dll /name:*TestReadFileEcho*` to run just one specific test. Of course you should substitute the file name and test name parameters as makes sense. And of course you can find out more about `cdd` and `execd` on the `T-shell` page of `OSGWiki`.
+
+Fortunately, running things through `T-shell` in this fashion is exactly the same way that the testlab orchestrates the tests. If you still don't get good data this way, you can use the `Connect via Console` mechanism way above to try to run things under `WinDBG` or the `Visual Studio Remote Debugger` manually on the machine to get them to repro or under the debugger more completely.
diff --git a/doc/building.md b/doc/building.md
new file mode 100644
index 00000000000..53b69c9b786
--- /dev/null
+++ b/doc/building.md
@@ -0,0 +1,32 @@
+
+# How to build Openconsole
+
+Openconsole can be built with Visual Studio or from the command line. There are build scripts for both cmd and powershell in /tools.
+
+## Building with cmd
+
+The cmd scripts are set up to emulate a portion of the OS razzle build environment. razzle.cmd is the first script that should be run. bcz.cmd will build clean and bz.cmd should build incrementally.
+
+There are also scripts for running the tests:
+- runut.cmd - run the unit tests
+- runft.cmd - run the feature tests
+- runuia.cmd - run the UIA tests
+
+## Build with Powershell
+
+Openconsole.psm1 should be loaded with `Import-Module`. From there `Set-MsbuildDevEnvironment` will set up environment variables required to build. There are a few exported functions (look at their documentation for further details):
+
+- Invoke-OpenConsolebuild - builds the solution. Can be passed msbuild arguments.
+- Invoke-OpenConsoleTests - runs the various tests. Will run the unit tests by default.
+- Start-OpenConsole - starts Openconsole.exe from the output directory. x64 is run by default.
+- Debug-OpenConsole - starts Openconsole.exe and attaches it to the default debugger. x64 is run by default.
+
+## Configuration Types
+
+Openconsole has three configuration types:
+
+- Debug
+- Release
+- AuditMode
+
+AuditMode is an experimental mode that enables some additional static analyis from CppCoreCheck.
diff --git a/doc/cascadia/Keybindings-spec.md b/doc/cascadia/Keybindings-spec.md
new file mode 100644
index 00000000000..08da295d837
--- /dev/null
+++ b/doc/cascadia/Keybindings-spec.md
@@ -0,0 +1,108 @@
+# Keymapping spec
+
+* author: Mike Griese __migrie__
+* created on: 2018-Oct-23
+
+## Abstract
+It should be possible to configure the terminal so that it doesn't send certain keystrokes as input to the terminal, and instead triggers certain actions. Examples of these actions could be copy/pasting text, opening a new tab, or changing the font size.
+
+This spec describes a mechanism by which we could provide a common implementation of handling keyboard shortcuts like these. This common implementation could then be leveraged and extended by the UX implementation as to handle certain callbacks in the UX layer. For example, The TerminalCore doesn't have a concept of what a tab is, but the keymap abstraction could raise an event such that a WPF app could implement creating a new tab in it's idomatic way, and UWP could implement them in their own way.
+
+## Terminology
+* **Key Chord**: This is any possible keystroke that a user can input
+ simultaneously, as a combination of a single character and any set of
+ (Ctrl, Alt and Shift).
+ For example, pressing Ctrl and C at the same time is the
+ key chord Ctrl+C. Pressing Ctrl+B, C are two separate
+ key chords. Trying to press them simultaneously (Ctrl+B+C) should
+ generate two separate key chords, with the order determined by the OS.
+
+## User Stories
+1. The User should be able to press certain key-chords to trigger certain
+ actions in the frontend of the application, such as copying text, pasting,
+ opening new tabs, or switching focus between panes.
+2. The user should be able to configure which key chords are bound to which actions.
+3. If a key chord is not mapped to an action, it should be sent to the Terminal just as any other keypress.
+
+## Details
+
+When the UX frontend is created, it should instantiate a `IKeyBindings` object with the keybindings mapped as it would like.
+
+When it's creating it's platform-dependent terminal component, it can pass the `IKeyBindings` object to that component. The component will then be able to pass that object to the terminal instance.
+
+When the terminal component calls `ITerminalInput.SendKeyEvent(uint vkey, KeyModifiers modifiers)`, the terminal will use `IKeyBindings.TryKeyChord` to see if there are any bound actions to that input. If there are, the `IKeyBindings` implementation will either handle the event by interacting with the `ITerminalInput`, or it'll invoke an event that's been registered by the frontend
+
+```csharp
+struct KeyChord
+{
+ KeyModifiers modifiers;
+ int vkey;
+}
+
+interface IKeyBindings {
+ bool TryKeyChord(KeyChord kc);
+}
+```
+
+Each frontend can implement the `IKeyBindings` interface however it so chooses.
+
+The `ITerminalInput` interface will be extended with the following method:
+```csharp
+public interface ITerminalInput
+{
+ ...
+ void SetKeyBindings(IKeyBindings bindings);
+ ...
+}
+```
+This will set the `IKeyBindings` object that the `ITerminalInput` implementation will use to filter key events.
+
+This method will be implemented by the `Terminal` object:
+```csharp
+partial class Terminal
+{
+ public void ITerminalInput.SetKeyBindings(IKeyBindings bindings);
+}
+```
+### Project Cascadia Sample
+
+Below is an example of how the Project Cascadia application might implement it's
+ keybindings.
+
+```csharp
+enum ShortcutAction
+{
+ CopyText,
+ PasteText,
+ NewTab,
+ NewWindow,
+ CloseWindow,
+ CloseTab,
+ SwitchToTab,
+ NextTab,
+ PrevTab,
+ IncreaseFontSize,
+ DecreaseFontSize,
+ ...
+}
+public delegate bool NewTabEvent(object sender);
+public delegate bool CloseTabEvent(object sender);
+public delegate bool NewWindowEvent(object sender);
+public delegate bool CloseWindowEvent(object sender);
+public delegate bool CopyEvent(object sender);
+public delegate bool PasteEvent(object sender);
+
+class KeyBindings : IKeyBindings
+{
+ private Dictionary keyShortcuts;
+
+ public void SetKeyBinding(ShortcutAction action, KeyChord? chord);
+ public bool TryKeyChord(KeyChord chord);
+}
+```
+
+### Copy/Paste
+How does Copy/paste play into this?
+
+When Input is written to the terminal, and it tries the copy keybinding, what happens?
+The Keybindings are global to the frontend, not local to the terminal. Copy/Paste events should also be delegates that get raised, and the frontend can then determine what to do with them. It'll probably query it's active/focused Terminal Component, then Get the `ITerminalInput` from that component, and use that to CopyText / PasteText from the Terminal as needed.
diff --git a/doc/cascadia/TerminalSettings-spec.md b/doc/cascadia/TerminalSettings-spec.md
new file mode 100644
index 00000000000..a1f39f375c4
--- /dev/null
+++ b/doc/cascadia/TerminalSettings-spec.md
@@ -0,0 +1,233 @@
+# Terminal Settings
+
+* author: Mike Griese __migrie__
+* created on: 2018-Oct-23
+
+## Abstract
+
+This spec will outline how various terminal frontends will be able to interact with the settings for the terminal.
+
+## Terminology
+* **Frontend** or **Application Layer**: This is the end-user experience. This
+ could be a Terminal Application (ex. Project Cascadia) or something that's
+ embedding a terminal window inside of it (ex. Visual Studio). These frontends
+ consume the terminal component as an atomic unit.
+* **Component Layer**: This is the UI framework-dependent implementation of the
+ Terminal component. As planned currently, this is either the UWP or WPF
+ Terminal component.
+* **Terminal Layer**: This is the shared core implementation of the terminal.
+ This is the Terminal Connection, Parser/Adapter, Buffer, and Renderer (but not
+ the UX-dependant RenderEngine).
+
+## User Stories
+1. "Project Cascadia" should be able to have both global settings (such as
+ scrollbar styling) and settings that are stored per-profile (such as
+ commandline, color scheme, etc.)
+2. "Project Cascadia" should be able to load these settings at boot, use them to
+ create terminal instances, be able to edit them, and be able to save them
+ back.
+3. "Project Cascadia" should be able to have terminal instances reflect the
+ changes to the settings when the settings are changed.
+4. "Project Cascadia" should be able to host panes/tabs with different profiles
+ set at the same time.
+5. Visual Studio should be able to persist and edit settings globally, without
+ the need for a globals/profiles structure.
+6. The Terminal should be able to read information from a settings structure
+ that's independant of how it's persisted / implemented by the Application
+7. The Component should be able to have it's own settings independent of the
+ application that's embedding it, such as font size and face, scrollbar
+ visibility, etc. These should be settings that are specific to the component,
+ and the Terminal should logically be unaffected by these settings.
+
+## Details
+
+Some settings will need to be Application-specific, some will need to be component-specific, and some are terminal-specific. For example:
+
+Terminal | Component | Frontend
+--------------------|-----------------------|------------------
+Color Table | Font Face, size | Status Line Visibility, contents
+Cursor Color | Scrollbar Visibility | ~~Window Size~~[1]
+History Size | |
+Buffer Size [1] | |
+
+* [1] I believe only the "Default" or "Initial" buffer size should be the one we truly store in the settings. When the app first boots up, it can use that value to with the font size to figure out how big its window should be. When additional tabs/panes are created, they should inherit the size of the existing window. Similarly, VS could first calculate how much space it has available, then override that value when creating the terminal.
+
+Project Cascadia needs to be able to persist settings as a bipartite globals-profiles structure.
+VS needs to be able to persist settings just as a simple set of global settings.
+
+When the application needs to retrieve these settings, they need to use them as a tripartite structure: frontend-component-terminal settings.
+
+Each frontend will have it's own set of settings.
+Each component implementation will also ned to have some settings that control it.
+The terminal also will have some settings specific to the terminal.
+
+### Globals and Profiles
+With \*nix-like terminals, settings are typically structured as two parts:
+ Globals and Profiles.
+
+Globals are settings that affect the entirety of the terminal application. They wouldn't be different from one pane to the next. An example is the Terminal KeyBindings - these should be the same for all tabs/panes that are running as a part of the terminal application.
+
+Profiles are what you might consider per-application settings. These are settings that can be different from one terminal instance to the next. One of the primary differentiators between profiles is the commandline used to start the terminal instance - this enables the user to have both a `cmd` profile and a `powershell` profile, for example. Things like the color table/scheme, font size, history length, these all change per-profile.
+
+Per-Profile | Globals
+------------------------|------------------------
+Color Table | Keybindings
+Cursor Color | Scrollbar Visibility
+History Size | Status Line Visibility, contents
+Font Face, size | Window Size
+Shell Commandline |
+
+### Simple Settings
+
+An application like VS might not even care about settings profiles. They should be able to persist the settings as just a singular entity, and change those as needed, without the additional overhead. Profiles will be something that's more specifc to Project Cascadia.
+
+### Interface Descriptions
+
+```csharp
+public class TerminalSettings
+{
+ Color DefaultForeground;
+ Color DefaultBackground;
+ Color[] ColorTable;
+ Coord? Dimensions;
+ int HistorySize;
+ Color CursorColor;
+ CursorShape CursorShape;
+}
+
+public interface IComponentSettings
+{
+ TerminalSettings TerminalSettings { get; }
+}
+
+public interface IApplicationSettings
+{
+ IComponentSettings ComponentSettings { get; }
+}
+```
+
+The Application can store whatever settings it wants in it's implementation of `IApplicationSettings`. When it instantiates a Terminal Component, it will pass it's `IComponentSettings` to it.
+
+The component will retrieve whatever settings it wants from that object, and then pass the `TerminalSettings` to the Terminal it creates.
+
+
+The frontend will be able to get/set it's settings from the `IApplicationSettings` implementation.
+The frontend will be able to create components using the `IComponentSettings` in it's `IApplicationSettings`.
+The Component will then create the Terminal using the `TerminalSettings`.
+
+#### Project Cascadia Settings Details
+
+The `CascadiaSettings` will store the settings as two parts:
+* A set of global data & settings
+* A list of Profiles, that each have more data
+
+When Cascadia starts up, it'll load all the settings, including the Globals and profiles. The Globals will also tell us which profile is the "Default" profile we should use to instantiate the terminal.
+Using the globals and the Profile, it'll convert those to a `ApplicationSettings : IApplicationSettings`.
+It'll read data from that `ApplicationSettings` to initialize things it needs to know.
+* It'll determine whether or not to display the status line
+* It'll query the Component settings for the default size of the component, so it knows how big of a space it needs to reserve for it
+
+It'll then instantiate a `UWPTerminalComponent` and pass it the `UWPComponentSettings`.
+
+This is a rough draft of what these members might all be like.
+```csharp
+class CascadiaSettings
+{
+ void LoadAll();
+ void SaveAll();
+ GlobalAppSettings Globals;
+ List Profiles;
+ ApplicationSettings ToSettings(GlobalAppSettings globals, Profile profile);
+ void Update(ApplicationSettings appSettings, GUID profileID);
+}
+class Profile
+{
+ GUID ProfileGuid;
+ string Name;
+ string Commandline;
+ TerminalSettings TerminalSettings;
+ string FontFace;
+ int FontSize;
+ float acrylicTransparency;
+ bool useAcrylic;
+}
+class GlobalAppSettings
+{
+ GUID defaultProfile;
+ Keybindings keybindings;
+ bool showScrollbars;
+ bool showStatusline;
+}
+
+class ApplicationSettings : IApplicationSettings
+{
+ UWPComponentSettings ComponentSettings;
+ Keybindings keybindings;
+ bool showStatusline;
+}
+class UWPComponentSettings : IComponentSettings
+{
+ Point GetDefaultComponentSize();
+ TerminalSettings TerminalSettings;
+ string FontFace;
+ int FontSize;
+ bool showScrollbars;
+ float acrylicTransparency;
+ bool useAcrylic;
+}
+```
+
+### Updating Settings
+
+What happens when the user changes the application's settings? The App,
+ Component, and Terminal might all need to update their settings.
+The component will expose a `UpdateSettings()` method that will cause the
+ Component and Terminal to reload the settings from their settings objects.
+
+```csharp
+interface ITerminalComponent
+{
+ void UpdateSettings(IComponentSettings componentSettings);
+}
+partial class UWPTerminalComponent : ITerminalComponent
+{
+ void UpdateSettings(IComponentSettings componentSettings)
+ {
+ // Recalculate GlyphTypeFace
+ // Recalculate rows/cols using current geometry and typeface
+ // Update our terminal instance:
+ terminal.UpdateSettings(componentSettings.TerminalSettings);
+ }
+}
+```
+#### Updating settings in Project Cascadia
+
+However, when Cascadia's settings change, we're going to possibly change some global settings and possibly some profile settings. The profile's that are changed may or may not be currently active.
+
+> Say we have two different panes open with different profiles (A and B).
+> What happens if we change the settings for one profile's font and not the other's?
+> ~~We resize the height of the terminal to account for the change in height of the win~~
+>
+> We should never change the window size in response to a settings change if there is more than one tab/pane open.
+> > never?
+
+Cascadia would have to maintain a mapping of which components have which profiles:
+```csharp
+class CascadiaTerminalInstance
+{
+ GUID ProfileGuid;
+ UWPTerminalComponent component;
+}
+```
+
+Then, when the settings are closed, it'll enumerate all of the components it has loaded, and apply the updated settings to them. It'll do this by looking up the profile GUID of the component, then getting the `ApplicationSettings` for the profile, then calling `UpdateSettings` on the component.
+
+~~We need to have a way so that only the currently foreground component can change the window size.~~
+I don't like that - if we change the font size, we should just recalculate how many characters can fit in the current window size.
+
+## Questions / TODO
+* How does this interplay with setting properties of the terminal component in XAML?
+ * I would think that the component would load the XAML properties first, and if the controlling application calls `UpdateSettings` on the component, then those in-XAML properties would likely get overwritten.
+ * It's not necessary to create the component with a `IComponentSettings`, nor is it necessary to call `UpdateSettings`. If you wanted to create a trivial settings-less terminal component entriely in XAML, go right ahead.
+ * Any settings that *are* exposed through XAML properties *should* also be exposed in the component's settings implementation as well.
+ * Can that be enforced any way? I doubt it.
diff --git a/doc/submitting_code.md b/doc/submitting_code.md
new file mode 100644
index 00000000000..24442bceb97
--- /dev/null
+++ b/doc/submitting_code.md
@@ -0,0 +1,26 @@
+
+# Branches in Openconsole
+
+In Openconsole, `dev/main` is the master branch for the repo.
+
+Any branch that begins with `dev/` is recognized by our CI system and will automatically run x86 and amd64 builds and run our unit and feature tests. For feature branchs the pattern we use is `dev//`. ex. `dev/austdi/SomeCoolUnicodeFeature`. The important parts are the dev prefix and your alias.
+
+`inbox` is a special branch that coordinates Openconsole code to the main OS repo.
+
+The code will be checked into the OS repo at `/onecore/windows/core/console/open`. It would be prudent to make sure that directory builds in razzle with your submitted changes.
+
+# Code Submission Process
+
+Because we build outside of the OS repo, we need a way to get code back into it once it's been merged into `dev/main`. This is done by cherry-picking the PR to the `inbox` branch once it has been merged (and preferably squashed) into `dev/main`. We have a tool called Git2Git that listens for new merges into `inbox` and replicates the commits over to the OS repo. Feel free to approve and complete the `inbox` PR yourself. About a minute after the `inbox` PR is submitted, Git2Git will create a PR in the OS repo under the alias `miniksa`. It will automatically target the OS branch we're using at the time, it just needs you to go approve and complete it. Once that merge is completed it is a good idea to build the OS branch with the new code in it to make sure that the PR won't be the cause of a build break that evening.
+
+## What to do when cherry-picking to inbox fails
+
+Sometimes VSTS doesn't want to allow a cherry pick to the inbox branch. It might have a valid reason or it might just be finicky. You'll need to complete the merge manually on a local machine. The steps are:
+
+1. make sure you have pulled the latest commits for the `dev/main` and `inbox` branches
+2. make a new branch from inbox
+3. cherry-pick the commits from the PR to the newly created branch (this is easier if you squashed your commits when you merged into `dev/main`
+4. fix any merge conficts and commit
+5. push the new branch to the remote
+6. create a new PR of that branch in `inbox`
+7. complete PR and continue on to completing the auto-created PR in the OS repo
diff --git a/doc/virtual-dtors.md b/doc/virtual-dtors.md
new file mode 100644
index 00000000000..1cb70cc1f2a
--- /dev/null
+++ b/doc/virtual-dtors.md
@@ -0,0 +1,35 @@
+# Virtual Destructors for Interfaces
+
+
+* author: Mike Griese __migrie__
+* created on: 2019-Feb-20
+
+As you look through the code, you may come across patterns that look like the following:
+
+``` c++
+
+ class IRenderData
+ {
+ public:
+ virtual ~IRenderData() = 0;
+ // methods
+ };
+
+ inline IRenderData::~IRenderData() {}
+
+```
+
+You may ask yourself, why is the destructor deleted, then later defined to the
+ default destructor? This is a good question, because it seems both unintuitive
+ and unnecessary. However, if you don't define your interfaces exactly like
+ this, then sometimes on object destruction, the interface's dtor will be
+ called instead of the destructor for the base class. There is other
+ strangeness that can occur as well, the details of which escape my memory from
+ when @austdi and I first investigaved this early 2018.
+
+The end result of not defining your interfaces exacly like this will be that
+ occasionally, when destructing objects, you'll get a segfault.
+
+To check that this behavior works, I direct your attention to the VtIoTests.
+ There are a bunch of tests in that module that create objects, then delete
+ them, to make sure that they won't ever crash.
diff --git a/pkg/appx/OpenConsolePackage.wapproj b/pkg/appx/OpenConsolePackage.wapproj
new file mode 100644
index 00000000000..a2fbde89a8a
--- /dev/null
+++ b/pkg/appx/OpenConsolePackage.wapproj
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ 10.0.17763.0
+ 10.0.17134.0
+
+ false
+ false
+
+
+ false
+
+
+ true
+
+
+
+ 2D310963-F3E0-4EE5-8AC6-FBC94DCC3310
+
+ OpenConsole.exe
+ ..\..\src\host\exe\Host.EXE.vcxproj
+
+
+
+ False
+
+
+
+ false
+ Never
+
+
+
+ true
+ False
+ OpenConsolePackage_TemporaryKey.pfx
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TemporaryFilteredWapProjOutput Include="@(_FilteredNonWapProjProjectOutput)" />
+ <_FilteredNonWapProjProjectOutput Remove="@(_FilteredNonWapProjProjectOutput)" />
+ <_FilteredNonWapProjProjectOutput Include="@(_TemporaryFilteredWapProjOutput)">
+
+
+
+
+
diff --git a/pkg/appx/Package.appxmanifest b/pkg/appx/Package.appxmanifest
new file mode 100644
index 00000000000..b738e97f0d7
--- /dev/null
+++ b/pkg/appx/Package.appxmanifest
@@ -0,0 +1,34 @@
+
+
+
+
+ Windows Console (Preview)
+ Microsoft Corporation
+ images\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pkg/appx/images/LockScreenLogo.scale-200.png b/pkg/appx/images/LockScreenLogo.scale-200.png
new file mode 100644
index 00000000000..4796bcb9d64
Binary files /dev/null and b/pkg/appx/images/LockScreenLogo.scale-200.png differ
diff --git a/pkg/appx/images/Square150x150Logo.scale-200.png b/pkg/appx/images/Square150x150Logo.scale-200.png
new file mode 100644
index 00000000000..3d951a40b6f
Binary files /dev/null and b/pkg/appx/images/Square150x150Logo.scale-200.png differ
diff --git a/pkg/appx/images/Square44x44Logo.png b/pkg/appx/images/Square44x44Logo.png
new file mode 100644
index 00000000000..5e907dddc88
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.png differ
diff --git a/pkg/appx/images/Square44x44Logo.scale-200.png b/pkg/appx/images/Square44x44Logo.scale-200.png
new file mode 100644
index 00000000000..2bad534c7c3
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.scale-200.png differ
diff --git a/pkg/appx/images/Square44x44Logo.targetsize-16_altform-unplated.png b/pkg/appx/images/Square44x44Logo.targetsize-16_altform-unplated.png
new file mode 100644
index 00000000000..e997ab77d80
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.targetsize-16_altform-unplated.png differ
diff --git a/pkg/appx/images/Square44x44Logo.targetsize-24_altform-unplated.png b/pkg/appx/images/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 00000000000..bcb2132e46c
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/pkg/appx/images/Square44x44Logo.targetsize-256_altform-unplated.png b/pkg/appx/images/Square44x44Logo.targetsize-256_altform-unplated.png
new file mode 100644
index 00000000000..e640a18ad94
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.targetsize-256_altform-unplated.png differ
diff --git a/pkg/appx/images/Square44x44Logo.targetsize-32_altform-unplated.png b/pkg/appx/images/Square44x44Logo.targetsize-32_altform-unplated.png
new file mode 100644
index 00000000000..a386eb03e45
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.targetsize-32_altform-unplated.png differ
diff --git a/pkg/appx/images/Square44x44Logo.targetsize-48_altform-unplated.png b/pkg/appx/images/Square44x44Logo.targetsize-48_altform-unplated.png
new file mode 100644
index 00000000000..f0cab939d51
Binary files /dev/null and b/pkg/appx/images/Square44x44Logo.targetsize-48_altform-unplated.png differ
diff --git a/pkg/appx/images/StoreLogo.png b/pkg/appx/images/StoreLogo.png
new file mode 100644
index 00000000000..3e0e0567702
Binary files /dev/null and b/pkg/appx/images/StoreLogo.png differ
diff --git a/pkg/appx/images/Wide310x150Logo.scale-200.png b/pkg/appx/images/Wide310x150Logo.scale-200.png
new file mode 100644
index 00000000000..0a51cc975d1
Binary files /dev/null and b/pkg/appx/images/Wide310x150Logo.scale-200.png differ
diff --git a/res/console.ico b/res/console.ico
new file mode 100644
index 00000000000..fc756afc18d
Binary files /dev/null and b/res/console.ico differ
diff --git a/res/truetype.bmp b/res/truetype.bmp
new file mode 100644
index 00000000000..7a4b744065a
Binary files /dev/null and b/res/truetype.bmp differ
diff --git a/src/ConsolePerf.regions.xml b/src/ConsolePerf.regions.xml
new file mode 100644
index 00000000000..f08b8654826
--- /dev/null
+++ b/src/ConsolePerf.regions.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CPU
+ te.processhost.exe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CPU
+
+ conhost.exe;openconsole.exe
+
+
+
+
+ Commit
+ conhost.exe;openconsole.exe
+
+
+
+
+
+
diff --git a/src/ConsolePerf.wprp b/src/ConsolePerf.wprp
new file mode 100644
index 00000000000..1610514ef81
--- /dev/null
+++ b/src/ConsolePerf.wprp
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/StaticAnalysis.ruleset b/src/StaticAnalysis.ruleset
new file mode 100644
index 00000000000..1eea1e89f21
--- /dev/null
+++ b/src/StaticAnalysis.ruleset
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/buffer/dirs b/src/buffer/dirs
new file mode 100644
index 00000000000..72492a46188
--- /dev/null
+++ b/src/buffer/dirs
@@ -0,0 +1,3 @@
+DIRS=out \
+
+
diff --git a/src/buffer/out/AttrRow.cpp b/src/buffer/out/AttrRow.cpp
new file mode 100644
index 00000000000..e25816cf889
--- /dev/null
+++ b/src/buffer/out/AttrRow.cpp
@@ -0,0 +1,583 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "AttrRow.hpp"
+
+ // Routine Description:
+ // - constructor
+ // Arguments:
+ // - cchRowWidth - the length of the default text attribute
+ // - attr - the default text attribute
+ // Return Value:
+ // - constructed object
+ // Note: will throw exception if unable to allocate memory for text attribute storage
+ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr)
+{
+ _list.push_back(TextAttributeRun(cchRowWidth, attr));
+ _cchRowWidth = cchRowWidth;
+}
+
+// Routine Description:
+// - Sets all properties of the ATTR_ROW to default values
+// Arguments:
+// - attr - The default text attributes to use on text in this row.
+void ATTR_ROW::Reset(const TextAttribute attr)
+{
+ _list.clear();
+ _list.push_back(TextAttributeRun(_cchRowWidth, attr));
+}
+
+// Routine Description:
+// - Takes an existing row of attributes, and changes the length so that it fills the NewWidth.
+// If the new size is bigger, then the last attr is extended to fill the NewWidth.
+// If the new size is smaller, the runs are cut off to fit.
+// Arguments:
+// - oldWidth - The original width of the row.
+// - newWidth - The new width of the row.
+// Return Value:
+// - , throws exceptions on failures.
+void ATTR_ROW::Resize(const size_t newWidth)
+{
+ THROW_HR_IF(E_INVALIDARG, 0 == newWidth);
+
+ // Easy case. If the new row is longer, increase the length of the last run by how much new space there is.
+ if (newWidth > _cchRowWidth)
+ {
+ // Get the attribute that covers the final column of old width.
+ const auto runPos = FindAttrIndex(_cchRowWidth - 1, nullptr);
+ auto& run = _list[runPos];
+
+ // Extend its length by the additional columns we're adding.
+ run.SetLength(run.GetLength() + newWidth - _cchRowWidth);
+
+ // Store that the new total width we represent is the new width.
+ _cchRowWidth = newWidth;
+ }
+ // harder case: new row is shorter.
+ else
+ {
+ // Get the attribute that covers the final column of the new width
+ size_t CountOfAttr = 0;
+ const auto runPos = FindAttrIndex(newWidth - 1, &CountOfAttr);
+ auto& run = _list[runPos];
+
+ // CountOfAttr was given to us as "how many columns left from this point forward are covered by the returned run"
+ // So if the original run was B5 covering a 5 size OldWidth and we have a NewWidth of 3
+ // then when we called FindAttrIndex, it returned the B5 as the pIndexedRun and a 2 for how many more segments it covers
+ // after and including the 3rd column.
+ // B5-2 = B3, which is what we desire to cover the new 3 size buffer.
+ run.SetLength(run.GetLength() - CountOfAttr + 1);
+
+ // Store that the new total width we represent is the new width.
+ _cchRowWidth = newWidth;
+
+ // Erase segments after the one we just updated.
+ _list.erase(_list.cbegin() + runPos + 1, _list.cend());
+
+ // NOTE: Under some circumstances here, we have leftover run segments in memory or blank run segments
+ // in memory. We're not going to waste time redimensioning the array in the heap. We're just noting that the useful
+ // portions of it have changed.
+ }
+}
+
+// Routine Description:
+// - returns a copy of the TextAttribute at the specified column
+// Arguments:
+// - column - the column to get the attribute for
+// Return Value:
+// - the text attribute at column
+// Note:
+// - will throw on error
+TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column) const
+{
+ return GetAttrByColumn(column, nullptr);
+}
+
+// Routine Description:
+// - returns a copy of the TextAttribute at the specified column
+// Arguments:
+// - column - the column to get the attribute for
+// - pApplies - if given, fills how long this attribute will apply for
+// Return Value:
+// - the text attribute at column
+// Note:
+// - will throw on error
+TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column,
+ size_t* const pApplies) const
+{
+ THROW_HR_IF(E_INVALIDARG, column >= _cchRowWidth);
+ const auto runPos = FindAttrIndex(column, pApplies);
+ return _list[runPos].GetAttributes();
+}
+
+// Routine Description:
+// - reports how many runs we have stored (to be used for some optimizations
+// Return Value:
+// - Count of runs. 1 means we have 1 color to represent the entire row.
+size_t ATTR_ROW::GetNumberOfRuns() const noexcept
+{
+ return _list.size();
+}
+
+// Routine Description:
+// - This routine finds the nth attribute in this ATTR_ROW.
+// Arguments:
+// - index - which attribute to find
+// - applies - on output, contains corrected length of indexed attr.
+// for example, if the attribute string was { 5, BLUE } and the requested
+// index was 3, CountOfAttr would be 2.
+// Return Value:
+// - const reference to attribute run object
+size_t ATTR_ROW::FindAttrIndex(const size_t index, size_t* const pApplies) const
+{
+ FAIL_FAST_IF(!(index < _cchRowWidth)); // The requested index cannot be longer than the total length described by this set of Attrs.
+
+ size_t cTotalLength = 0;
+
+ FAIL_FAST_IF(!(_list.size() > 0)); // There should be a non-zero and positive number of items in the array.
+
+ // Scan through the internal array from position 0 adding up the lengths that each attribute applies to
+ auto runPos = _list.cbegin();
+ do
+ {
+ cTotalLength += runPos->GetLength();
+
+ if (cTotalLength > index)
+ {
+ // If we've just passed up the requested index with the length we added, break early
+ break;
+ }
+
+ runPos++;
+ } while (runPos < _list.cend());
+
+ // we should have broken before falling out the while case.
+ // if we didn't break, then this ATTR_ROW wasn't filled with enough attributes for the entire row of characters
+ FAIL_FAST_IF(runPos >= _list.cend());
+
+ // The remaining iterator position is the position of the attribute that is applicable at the position requested (index)
+ // Calculate its remaining applicability if requested
+
+ // The length on which the found attribute applies is the total length seen so far minus the index we were searching for.
+ FAIL_FAST_IF(!(cTotalLength > index)); // The length of all attributes we counted up so far should be longer than the index requested or we'll underflow.
+
+ if (nullptr != pApplies)
+ {
+ const auto attrApplies = cTotalLength - index;
+ FAIL_FAST_IF(!(attrApplies > 0)); // An attribute applies for >0 characters
+ // MSFT: 17130145 - will restore this and add a better assert to catch the real issue.
+ //FAIL_FAST_IF(!(attrApplies <= _cchRowWidth)); // An attribute applies for a maximum of the total length available to us
+
+ *pApplies = attrApplies;
+ }
+
+ return runPos - _list.cbegin();
+}
+
+// Routine Description:
+// - Sets the attributes (colors) of all character positions from the given position through the end of the row.
+// Arguments:
+// - iStart - Starting index position within the row
+// - attr - Attribute (color) to fill remaining characters with
+// Return Value:
+// -
+bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
+{
+ size_t const length = _cchRowWidth - iStart;
+
+ const TextAttributeRun run(length, attr);
+ return SUCCEEDED(InsertAttrRuns({ &run, 1 }, iStart, _cchRowWidth - 1, _cchRowWidth));
+}
+
+// Routine Description:
+// - Replaces all runs in the row with the given wToBeReplacedAttr with the new
+// attribute wReplaceWith. This method is used for replacing specifically
+// legacy attributes.
+// Arguments:
+// - wToBeReplacedAttr - the legacy attribute to replace in this row.
+// - wReplaceWith - the new value for the matching runs' attributes.
+// Return Value:
+//
+void ATTR_ROW::ReplaceLegacyAttrs(_In_ WORD wToBeReplacedAttr, _In_ WORD wReplaceWith) noexcept
+{
+ TextAttribute ToBeReplaced;
+ ToBeReplaced.SetFromLegacy(wToBeReplacedAttr);
+
+ TextAttribute ReplaceWith;
+ ReplaceWith.SetFromLegacy(wReplaceWith);
+
+ ReplaceAttrs(ToBeReplaced, ReplaceWith);
+}
+
+
+// Method Description:
+// - Replaces all runs in the row with the given toBeReplacedAttr with the new
+// attribute replaceWith.
+// Arguments:
+// - toBeReplacedAttr - the attribute to replace in this row.
+// - replaceWith - the new value for the matching runs' attributes.
+// Return Value:
+// -
+void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept
+{
+ for (auto& run : _list)
+ {
+ if (run.GetAttributes() == toBeReplacedAttr)
+ {
+ run.SetAttributes(replaceWith);
+ }
+ }
+}
+
+
+// Routine Description:
+// - Takes a array of attribute runs, and inserts them into this row from startIndex to endIndex.
+// - For example, if the current row was was [{4, BLUE}], the merge string
+// was [{ 2, RED }], with (StartIndex, EndIndex) = (1, 2),
+// then the row would modified to be = [{ 1, BLUE}, {2, RED}, {1, BLUE}].
+// Arguments:
+// - rgInsertAttrs - The array of attrRuns to merge into this row.
+// - cInsertAttrs - The number of elements in rgInsertAttrs
+// - iStart - The index in the row to place the array of runs.
+// - iEnd - the final index of the merge runs
+// - BufferWidth - the width of the row.
+// Return Value:
+// - STATUS_NO_MEMORY if there wasn't enough memory to insert the runs
+// otherwise STATUS_SUCCESS if we were successful.
+[[nodiscard]]
+HRESULT ATTR_ROW::InsertAttrRuns(const std::basic_string_view newAttrs,
+ const size_t iStart,
+ const size_t iEnd,
+ const size_t cBufferWidth)
+{
+ // Definitions:
+ // Existing Run = The run length encoded color array we're already storing in memory before this was called.
+ // Insert Run = The run length encoded color array that someone is asking us to inject into our stored memory run.
+ // New Run = The run length encoded color array that we have to allocate and rebuild to store internally
+ // which will replace Existing Run at the end of this function.
+ // Example:
+ // cBufferWidth = 10.
+ // Existing Run: R3 -> G5 -> B2
+ // Insert Run: Y1 -> N1 at iStart = 5 and iEnd = 6
+ // (rgInsertAttrs is a 2 length array with Y1->N1 in it and cInsertAttrs = 2)
+ // Final Run: R3 -> G2 -> Y1 -> N1 -> G1 -> B2
+
+ // We'll need to know what the last valid column is for some calculations versus iEnd
+ // because iEnd is specified to us as an inclusive index value.
+ // Do the -1 math here now so we don't have to have -1s scattered all over this function.
+ const size_t iLastBufferCol = cBufferWidth - 1;
+
+ // If the insertion size is 1, do some pre-processing to
+ // see if we can get this done quickly.
+ if (newAttrs.size() == 1)
+ {
+ // Get the new color attribute we're trying to apply
+ const TextAttribute NewAttr = newAttrs.at(0).GetAttributes();
+
+ // If the existing run was only 1 element...
+ // ...and the new color is the same as the old, we don't have to do anything and can exit quick.
+ if (_list.size() == 1 && _list.at(0).GetAttributes() == NewAttr)
+ {
+ return S_OK;
+ }
+ // .. otherwise if we internally have a list of 2 and we're about to insert a single color
+ // it's probable that we're just walking left-to-right through the row and changing each
+ // cell one at a time.
+ // e.g.
+ // AAAAABBBBBBB
+ // AAAAAABBBBBB
+ // AAAAAAABBBBB
+ // Check for that circumstance by seeing if we're inserting a single run of the
+ // left side color right at the boundary and just adjust the counts in the existing
+ // two elements in our internal list.
+ else if (_list.size() == 2 && newAttrs.at(0).GetLength() == 1)
+ {
+ auto left = _list.begin();
+ if (iStart == left->GetLength() && NewAttr == left->GetAttributes())
+ {
+ auto right = left + 1;
+ left->IncrementLength();
+ right->DecrementLength();
+
+ // If we just reduced the right half to zero, just erase it out of the list.
+ if (right->GetLength() == 0)
+ {
+ _list.erase(right);
+ }
+ return S_OK;
+ }
+ }
+ }
+
+ // If we're about to cover the entire existing run with a new one, we can also make an optimization.
+ if (iStart == 0 && iEnd == iLastBufferCol)
+ {
+ // Just dump what we're given over what we have and call it a day.
+ _list.assign(newAttrs.cbegin(), newAttrs.cend());
+
+ return S_OK;
+ }
+
+ // In the worst case scenario, we will need a new run that is the length of
+ // The existing run in memory + The new run in memory + 1.
+ // This worst case occurs when we inject a new item in the middle of an existing run like so
+ // Existing R3->B5->G2, Insertion Y2 starting at 5 (in the middle of the B5)
+ // becomes R3->B2->Y2->B1->G2.
+ // The original run was 3 long. The insertion run was 1 long. We need 1 more for the
+ // fact that an existing piece of the run was split in half (to hold the latter half).
+ const size_t cNewRun = _list.size() + newAttrs.size() + 1;
+ std::vector newRun;
+ newRun.resize(cNewRun);
+
+ // We will start analyzing from the beginning of our existing run.
+ // Use some pointers to keep track of where we are in walking through our runs.
+
+ // Get the existing run that we'll be updating/manipulating.
+ const auto existingRun = _list.begin();
+ auto pExistingRunPos = existingRun;
+ const auto pExistingRunEnd = existingRun + _list.size();
+ auto pInsertRunPos = newAttrs.begin();
+ size_t cInsertRunRemaining = newAttrs.size();
+ auto pNewRunPos = newRun.begin();
+ size_t iExistingRunCoverage = 0;
+
+ // Copy the existing run into the new buffer up to the "start index" where the new run will be injected.
+ // If the new run starts at 0, we have nothing to copy from the beginning.
+ if (iStart != 0)
+ {
+ // While we're less than the desired insertion position...
+ while (iExistingRunCoverage < iStart)
+ {
+ // Add up how much length we can cover by copying an item from the existing run.
+ iExistingRunCoverage += pExistingRunPos->GetLength();
+
+ // Copy it to the new run buffer and advance both pointers.
+ *pNewRunPos++ = *pExistingRunPos++;
+ }
+
+ // When we get to this point, we've copied full segments from the original existing run
+ // into our new run buffer. We will have 1 or more full segments of color attributes and
+ // we MIGHT have to cut the last copied segment's length back depending on where the inserted
+ // attributes will fall in the final/new run.
+ // Some examples:
+ // - Starting with the original string R3 -> G5 -> B2
+ // - 1. If the insertion is Y5 at start index 3
+ // We are trying to get a result/final/new run of R3 -> Y5 -> B2.
+ // We just copied R3 to the new destination buffer and we cang skip down and start inserting the new attrs.
+ // - 2. If the insertion is Y3 at start index 5
+ // We are trying to get a result/final/new run of R3 -> G2 -> Y3 -> B2.
+ // We just copied R3 -> G5 to the new destination buffer with the code above.
+ // But the insertion is going to cut out some of the length of the G5.
+ // We need to fix this up below so it says G2 instead to leave room for the Y3 to fit in
+ // the new/final run.
+
+ // Copying above advanced the pointer to an empty cell beyond what we copied.
+ // Back up one cell so we can manipulate the final item we copied from the existing run to the new run.
+ pNewRunPos--;
+
+ // Fetch out the length so we can fix it up based on the below conditions.
+ size_t length = pNewRunPos->GetLength();
+
+ // If we've covered more cells already than the start of the attributes to be inserted...
+ if (iExistingRunCoverage > iStart)
+ {
+ // ..then subtract some of the length of the final cell we copied.
+ // We want to take remove the difference in distance between the cells we've covered in the new
+ // run and the insertion point.
+ // (This turns G5 into G2 from Example 2 just above)
+ length -= (iExistingRunCoverage - iStart);
+ }
+
+ // Now we're still on that "last cell copied" into the new run.
+ // If the color of that existing copied cell matches the color of the first segment
+ // of the run we're about to insert, we can just increment the length to extend the coverage.
+ if (pNewRunPos->GetAttributes() == pInsertRunPos->GetAttributes())
+ {
+ length += pInsertRunPos->GetLength();
+
+ // Since the color matched, we have already "used up" part of the insert run
+ // and can skip it in our big "memcopy" step below that will copy the bulk of the insert run.
+ cInsertRunRemaining--;
+ pInsertRunPos++;
+ }
+
+ // We're done manipulating the length. Store it back.
+ pNewRunPos->SetLength(length);
+
+ // Now that we're done adjusting the last copied item, advance the pointer into a fresh/blank
+ // part of the new run array.
+ pNewRunPos++;
+ }
+
+ // Bulk copy the majority (or all, depending on circumstance) of the insert run into the final run buffer.
+ std::copy_n(pInsertRunPos, cInsertRunRemaining, pNewRunPos);
+
+ // Advance the new run pointer into the position just after everything we copied.
+ pNewRunPos += cInsertRunRemaining;
+
+ // We're technically done with the insert run now and have 0 remaining, but won't bother updating its pointers
+ // and counts any further because we won't use them.
+
+ // Now we need to move our pointer for the original existing run forward and update our counts
+ // on how many cells we could have copied from the source before finishing off the new run.
+ while (iExistingRunCoverage <= iEnd)
+ {
+ FAIL_FAST_IF(!(pExistingRunPos != pExistingRunEnd));
+ iExistingRunCoverage += pExistingRunPos->GetLength();
+ pExistingRunPos++;
+ }
+
+ // If we still have original existing run cells remaining, copy them into the final new run.
+ if (pExistingRunPos != pExistingRunEnd || iExistingRunCoverage != (iEnd + 1))
+ {
+ // Back up one cell so we can inspect the most recent item copied into the new run for optimizations.
+ pNewRunPos--;
+
+ // We advanced the existing run pointer and its count to on or past the end of what the insertion run filled in.
+ // If this ended up being past the end of what the insertion run covers, we have to account for the cells after
+ // the insertion run but before the next piece of the original existing run.
+ // The example in this case is if we had...
+ // Existing Run = R3 -> G5 -> B2 -> X5
+ // Insert Run = Y2 @ iStart = 7 and iEnd = 8
+ // ... then at this point in time, our states would look like...
+ // New Run so far = R3 -> G4 -> Y2
+ // Existing Run Pointer is at X5
+ // Existing run coverage count at 3 + 5 + 2 = 10.
+ // However, in order to get the final desired New Run
+ // (which is R3 -> G4 -> Y2 -> B1 -> X5)
+ // we would need to grab a piece of that B2 we already skipped past.
+ // iExistingRunCoverage = 10. iEnd = 8. iEnd+1 = 9. 10 > 9. So we skipped something.
+ if (iExistingRunCoverage > (iEnd + 1))
+ {
+ // Back up the existing run pointer so we can grab the piece we skipped.
+ pExistingRunPos--;
+
+ // If the color matches what's already in our run, just increment the count value.
+ // This case is slightly off from the example above. This case is for if the B2 above was actually Y2.
+ // That Y2 from the existing run is the same color as the Y2 we just filled a few columns left in the final run
+ // so we can just adjust the final run's column count instead of adding another segment here.
+ if (pNewRunPos->GetAttributes() == pExistingRunPos->GetAttributes())
+ {
+ size_t length = pNewRunPos->GetLength();
+ length += (iExistingRunCoverage - (iEnd + 1));
+ pNewRunPos->SetLength(length);
+ }
+ else
+ {
+ // If the color didn't match, then we just need to copy the piece we skipped and adjust
+ // its length for the discrepency in columns not yet covered by the final/new run.
+
+ // Move forward to a blank spot in the new run
+ pNewRunPos++;
+
+ // Copy the existing run's color information to the new run
+ pNewRunPos->SetAttributes(pExistingRunPos->GetAttributes());
+
+ // Adjust the length of that copied color to cover only the reduced number of columns needed
+ // now that some have been replaced by the insert run.
+ pNewRunPos->SetLength(iExistingRunCoverage - (iEnd + 1));
+ }
+
+ // Now that we're done recovering a piece of the existing run we skipped, move the pointer forward again.
+ pExistingRunPos++;
+ }
+
+ // OK. In this case, we didn't skip anything. The end of the insert run fell right at a boundary
+ // in columns that was in the original existing run.
+ // However, the next piece of the original existing run might happen to have the same color attribute
+ // as the final piece of what we just copied.
+ // As an example...
+ // Existing Run = R3 -> G5 -> B2.
+ // Insert Run = B5 @ iStart = 3 and iEnd = 7
+ // New Run so far = R3 -> B5
+ // New Run desired when done = R3 -> B7
+ // Existing run pointer is on B2.
+ // We want to merge the 2 from the B2 into the B5 so we get B7.
+ else if (pNewRunPos->GetAttributes() == pExistingRunPos->GetAttributes())
+ {
+ // Add the value from the existing run into the current new run position.
+ size_t length = pNewRunPos->GetLength();
+ length += pExistingRunPos->GetLength();
+ pNewRunPos->SetLength(length);
+
+ // Advance the existing run position since we consumed its value and merged it in.
+ pExistingRunPos++;
+ }
+
+ // OK. We're done inspecting the most recently copied cell for optimizations.
+ pNewRunPos++;
+
+ // Now bulk copy any segments left in the original existing run
+ if (pExistingRunPos < pExistingRunEnd)
+ {
+ std::copy_n(pExistingRunPos, (pExistingRunEnd - pExistingRunPos), pNewRunPos);
+
+ // Fix up the end pointer so we know where we are for counting how much of the new run's memory space we used.
+ pNewRunPos += (pExistingRunEnd - pExistingRunPos);
+ }
+ }
+
+ // OK, phew. We're done. Now we just need to free the existing run, store the new run in its place,
+ // and update the count for the correct length of the new run now that we've filled it up.
+
+ newRun.erase(pNewRunPos, newRun.end());
+ _list.swap(newRun);
+
+ return S_OK;
+}
+
+// Routine Description:
+// - packs a vector of TextAttribute into a vector of TextAttrbuteRun
+// Arguments:
+// - attrs - text attributes to pack
+// Return Value:
+// - packed text attribute run
+std::vector ATTR_ROW::PackAttrs(const std::vector& attrs)
+{
+ std::vector runs;
+ if (attrs.empty())
+ {
+ return runs;
+ }
+ for (auto attr : attrs)
+ {
+ if (runs.empty() || runs.back().GetAttributes() != attr)
+ {
+ const TextAttributeRun run(1, attr);
+ runs.push_back(run);
+ }
+ else
+ {
+ runs.back().SetLength(runs.back().GetLength() + 1);
+ }
+ }
+ return runs;
+}
+
+ATTR_ROW::const_iterator ATTR_ROW::begin() const noexcept
+{
+ return AttrRowIterator(this);
+}
+
+ATTR_ROW::const_iterator ATTR_ROW::end() const noexcept
+{
+ return AttrRowIterator::CreateEndIterator(this);
+}
+
+ATTR_ROW::const_iterator ATTR_ROW::cbegin() const noexcept
+{
+ return AttrRowIterator(this);
+}
+
+ATTR_ROW::const_iterator ATTR_ROW::cend() const noexcept
+{
+ return AttrRowIterator::CreateEndIterator(this);
+}
+
+bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept
+{
+ return (a._list.size() == b._list.size() &&
+ a._list.data() == b._list.data() &&
+ a._cchRowWidth == b._cchRowWidth);
+}
diff --git a/src/buffer/out/AttrRow.hpp b/src/buffer/out/AttrRow.hpp
new file mode 100644
index 00000000000..a45d814a688
--- /dev/null
+++ b/src/buffer/out/AttrRow.hpp
@@ -0,0 +1,76 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- AttrRow.hpp
+
+Abstract:
+- contains data structure for the attributes of one row of screen buffer
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+--*/
+
+#pragma once
+
+#include "TextAttributeRun.hpp"
+#include "AttrRowIterator.hpp"
+
+class ATTR_ROW final
+{
+public:
+ using const_iterator = typename AttrRowIterator;
+
+ ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr);
+
+ void Reset(const TextAttribute attr);
+
+ TextAttribute GetAttrByColumn(const size_t column) const;
+ TextAttribute GetAttrByColumn(const size_t column,
+ size_t* const pApplies) const;
+
+ size_t GetNumberOfRuns() const noexcept;
+
+ size_t FindAttrIndex(const size_t index,
+ size_t* const pApplies) const;
+
+ bool SetAttrToEnd(const UINT iStart, const TextAttribute attr);
+ void ReplaceLegacyAttrs(const WORD wToBeReplacedAttr, const WORD wReplaceWith) noexcept;
+ void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept;
+
+ void Resize(const size_t newWidth);
+
+ [[nodiscard]]
+ HRESULT InsertAttrRuns(const std::basic_string_view newAttrs,
+ const size_t iStart,
+ const size_t iEnd,
+ const size_t cBufferWidth);
+
+ static std::vector PackAttrs(const std::vector& attrs);
+
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ friend bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept;
+ friend class AttrRowIterator;
+
+private:
+
+ std::vector _list;
+ size_t _cchRowWidth;
+
+#ifdef UNIT_TESTING
+ friend class AttrRowTests;
+#endif
+
+};
diff --git a/src/buffer/out/AttrRowIterator.cpp b/src/buffer/out/AttrRowIterator.cpp
new file mode 100644
index 00000000000..0462afa144c
--- /dev/null
+++ b/src/buffer/out/AttrRowIterator.cpp
@@ -0,0 +1,146 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "AttrRowIterator.hpp"
+#include "AttrRow.hpp"
+
+AttrRowIterator AttrRowIterator::CreateEndIterator(const ATTR_ROW* const attrRow)
+{
+ AttrRowIterator it{ attrRow };
+ it._setToEnd();
+ return it;
+}
+
+AttrRowIterator::AttrRowIterator(const ATTR_ROW* const attrRow) :
+ _pAttrRow{ attrRow },
+ _run{ attrRow->_list.cbegin() },
+ _currentAttributeIndex{ 0 }
+{
+}
+
+AttrRowIterator::operator bool() const noexcept
+{
+ return _run < _pAttrRow->_list.cend();
+}
+
+bool AttrRowIterator::operator==(const AttrRowIterator& it) const
+{
+ return (_pAttrRow == it._pAttrRow &&
+ _run == it._run &&
+ _currentAttributeIndex == it._currentAttributeIndex);
+}
+
+bool AttrRowIterator::operator!=(const AttrRowIterator& it) const
+{
+ return !(*this == it);
+}
+
+AttrRowIterator& AttrRowIterator::operator++()
+{
+ _increment(1);
+ return *this;
+}
+
+AttrRowIterator AttrRowIterator::operator++(int)
+{
+ auto copy = *this;
+ _increment(1);
+ return copy;
+}
+
+AttrRowIterator& AttrRowIterator::operator+=(const ptrdiff_t& movement)
+{
+ if (movement >= 0)
+ {
+ _increment(gsl::narrow(movement));
+ }
+ else
+ {
+ _decrement(gsl::narrow(-movement));
+ }
+
+ return *this;
+}
+
+AttrRowIterator& AttrRowIterator::operator-=(const ptrdiff_t& movement)
+{
+ return this->operator+=(-movement);
+}
+
+AttrRowIterator& AttrRowIterator::operator--()
+{
+ _decrement(1);
+ return *this;
+}
+
+AttrRowIterator AttrRowIterator::operator--(int)
+{
+ auto copy = *this;
+ _decrement(1);
+ return copy;
+}
+
+const TextAttribute* AttrRowIterator::operator->() const
+{
+ return &_run->GetAttributes();
+}
+
+const TextAttribute& AttrRowIterator::operator*() const
+{
+ return _run->GetAttributes();
+}
+
+// Routine Description:
+// - increments the index the iterator points to
+// Arguments:
+// - count - the amount to increment by
+void AttrRowIterator::_increment(size_t count)
+{
+ while (count > 0)
+ {
+ const size_t runLength = _run->GetLength();
+ if (count + _currentAttributeIndex < runLength)
+ {
+ _currentAttributeIndex += count;
+ return;
+ }
+ else
+ {
+ count -= runLength - _currentAttributeIndex;
+ ++_run;
+ _currentAttributeIndex = 0;
+ }
+ }
+}
+
+// Routine Description:
+// - decrements the index the iterator points to
+// Arguments:
+// - count - the amount to decrement by
+void AttrRowIterator::_decrement(size_t count)
+{
+ while (count > 0)
+ {
+ if (count <= _currentAttributeIndex)
+ {
+ _currentAttributeIndex -= count;
+ return;
+ }
+ else
+ {
+ count -= _currentAttributeIndex;
+ --_run;
+ _currentAttributeIndex = _run->GetLength() - 1;
+ }
+ }
+}
+
+// Routine Description:
+// - sets fields on the iterator to describe the end() state of the ATTR_ROW
+void AttrRowIterator::_setToEnd()
+{
+ _run = _pAttrRow->_list.cend();
+ _currentAttributeIndex = 0;
+}
diff --git a/src/buffer/out/AttrRowIterator.hpp b/src/buffer/out/AttrRowIterator.hpp
new file mode 100644
index 00000000000..92aadef59e3
--- /dev/null
+++ b/src/buffer/out/AttrRowIterator.hpp
@@ -0,0 +1,62 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- AttrRowIterator.hpp
+
+Abstract:
+- iterator for ATTR_ROW to walk the TextAttributes of the run
+- read only iterator
+
+Author(s):
+- Austin Diviness (AustDi) 04-Jun-2018
+--*/
+
+
+#pragma once
+
+#include "TextAttribute.hpp"
+#include "TextAttributeRun.hpp"
+
+class ATTR_ROW;
+
+class AttrRowIterator final
+{
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = TextAttribute;
+ using difference_type = std::ptrdiff_t;
+ using pointer = TextAttribute*;
+ using reference = TextAttribute&;
+
+ static AttrRowIterator CreateEndIterator(const ATTR_ROW* const attrRow);
+
+ AttrRowIterator(const ATTR_ROW* const attrRow);
+
+ operator bool() const noexcept;
+
+ bool operator==(const AttrRowIterator& it) const;
+ bool operator!=(const AttrRowIterator& it) const;
+
+ AttrRowIterator& operator++();
+ AttrRowIterator operator++(int);
+
+ AttrRowIterator& operator+=(const ptrdiff_t& movement);
+ AttrRowIterator& operator-=(const ptrdiff_t& movement);
+
+ AttrRowIterator& operator--();
+ AttrRowIterator operator--(int);
+
+ const TextAttribute* operator->() const;
+ const TextAttribute& operator*() const;
+
+private:
+ std::vector::const_iterator _run;
+ const ATTR_ROW* _pAttrRow;
+ size_t _currentAttributeIndex; // index of TextAttribute within the current TextAttributeRun
+
+ void _increment(size_t count);
+ void _decrement(size_t count);
+ void _setToEnd();
+};
diff --git a/src/buffer/out/CharRow.cpp b/src/buffer/out/CharRow.cpp
new file mode 100644
index 00000000000..2e5cf99939e
--- /dev/null
+++ b/src/buffer/out/CharRow.cpp
@@ -0,0 +1,324 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "CharRow.hpp"
+#include "unicode.hpp"
+#include "Row.hpp"
+
+// Routine Description:
+// - constructor
+// Arguments:
+// - rowWidth - the size (in wchar_t) of the char and attribute rows
+// - pParent - the parent ROW
+// Return Value:
+// - instantiated object
+// Note: will through if unable to allocate char/attribute buffers
+CharRow::CharRow(size_t rowWidth, ROW* const pParent) :
+ _wrapForced{ false },
+ _doubleBytePadded{ false },
+ _data(rowWidth, value_type()),
+ _pParent{ FAIL_FAST_IF_NULL(pParent) }
+{
+}
+
+// Routine Description:
+// - Sets the wrap status for the current row
+// Arguments:
+// - wrapForced - True if the row ran out of space and we forced to wrap to the next row. False otherwise.
+// Return Value:
+// -
+void CharRow::SetWrapForced(const bool wrapForced) noexcept
+{
+ _wrapForced = wrapForced;
+}
+
+// Routine Description:
+// - Gets the wrap status for the current row
+// Arguments:
+// -
+// Return Value:
+// - True if the row ran out of space and we were forced to wrap to the next row. False otherwise.
+bool CharRow::WasWrapForced() const noexcept
+{
+ return _wrapForced;
+}
+
+// Routine Description:
+// - Sets the double byte padding for the current row
+// Arguments:
+// - fWrapWasForced - True if the row ran out of space for a double byte character and we padded out the row. False otherwise.
+// Return Value:
+// -
+void CharRow::SetDoubleBytePadded(const bool doubleBytePadded) noexcept
+{
+ _doubleBytePadded = doubleBytePadded;
+}
+
+// Routine Description:
+// - Gets the double byte padding status for the current row.
+// Arguments:
+// -
+// Return Value:
+// - True if the row didn't have space for a double byte character and we were padded out the row. False otherwise.
+bool CharRow::WasDoubleBytePadded() const noexcept
+{
+ return _doubleBytePadded;
+}
+
+// Routine Description:
+// - gets the size of the row, in glyph cells
+// Arguments:
+// -
+// Return Value:
+// - the size of the row
+size_t CharRow::size() const noexcept
+{
+ return _data.size();
+}
+
+// Routine Description:
+// - Sets all properties of the CharRowBase to default values
+// Arguments:
+// - sRowWidth - The width of the row.
+// Return Value:
+// -
+void CharRow::Reset()
+{
+ for (auto& cell : _data)
+ {
+ cell.Reset();
+ }
+
+ _wrapForced = false;
+ _doubleBytePadded = false;
+}
+
+// Routine Description:
+// - resizes the width of the CharRowBase
+// Arguments:
+// - newSize - the new width of the character and attributes rows
+// Return Value:
+// - S_OK on success, otherwise relevant error code
+[[nodiscard]]
+HRESULT CharRow::Resize(const size_t newSize) noexcept
+{
+ try
+ {
+ const value_type insertVals;
+ _data.resize(newSize, insertVals);
+ }
+ CATCH_RETURN();
+
+ return S_OK;
+}
+
+typename CharRow::iterator CharRow::begin() noexcept
+{
+ return _data.begin();
+}
+
+typename CharRow::const_iterator CharRow::cbegin() const noexcept
+{
+ return _data.cbegin();
+}
+
+typename CharRow::iterator CharRow::end() noexcept
+{
+ return _data.end();
+}
+
+typename CharRow::const_iterator CharRow::cend() const noexcept
+{
+ return _data.cend();
+}
+
+// Routine Description:
+// - Inspects the current internal string to find the left edge of it
+// Arguments:
+// -
+// Return Value:
+// - The calculated left boundary of the internal string.
+size_t CharRow::MeasureLeft() const
+{
+ std::vector::const_iterator it = _data.cbegin();
+ while (it != _data.cend() && it->IsSpace())
+ {
+ ++it;
+ }
+ return it - _data.cbegin();
+}
+
+// Routine Description:
+// - Inspects the current internal string to find the right edge of it
+// Arguments:
+// -
+// Return Value:
+// - The calculated right boundary of the internal string.
+size_t CharRow::MeasureRight() const noexcept
+{
+ std::vector::const_reverse_iterator it = _data.crbegin();
+ while (it != _data.crend() && it->IsSpace())
+ {
+ ++it;
+ }
+ return _data.crend() - it;
+}
+
+void CharRow::ClearCell(const size_t column)
+{
+ _data.at(column).Reset();
+}
+
+// Routine Description:
+// - Tells you whether or not this row contains any valid text.
+// Arguments:
+// -
+// Return Value:
+// - True if there is valid text in this row. False otherwise.
+bool CharRow::ContainsText() const noexcept
+{
+ for (const value_type& cell : _data)
+ {
+ if (!cell.IsSpace())
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Routine Description:
+// - gets the attribute at the specified column
+// Arguments:
+// - column - the column to get the attribute for
+// Return Value:
+// - the attribute
+// Note: will throw exception if column is out of bounds
+const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
+{
+ return _data.at(column).DbcsAttr();
+}
+
+// Routine Description:
+// - gets the attribute at the specified column
+// Arguments:
+// - column - the column to get the attribute for
+// Return Value:
+// - the attribute
+// Note: will throw exception if column is out of bounds
+DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
+{
+ return const_cast(static_cast(this)->DbcsAttrAt(column));
+}
+
+// Routine Description:
+// - resets text data at column
+// Arguments:
+// - column - column index to clear text data from
+// Return Value:
+// -
+// Note: will throw exception if column is out of bounds
+void CharRow::ClearGlyph(const size_t column)
+{
+ _data.at(column).EraseChars();
+}
+
+// Routine Description:
+// - returns text data at column as a const reference.
+// Arguments:
+// - column - column to get text data for
+// Return Value:
+// - text data at column
+// - Note: will throw exception if column is out of bounds
+const CharRow::reference CharRow::GlyphAt(const size_t column) const
+{
+ THROW_HR_IF(E_INVALIDARG, column >= _data.size());
+ return { const_cast(*this), column };
+}
+
+// Routine Description:
+// - returns text data at column as a reference.
+// Arguments:
+// - column - column to get text data for
+// Return Value:
+// - text data at column
+// - Note: will throw exception if column is out of bounds
+CharRow::reference CharRow::GlyphAt(const size_t column)
+{
+ THROW_HR_IF(E_INVALIDARG, column >= _data.size());
+ return { *this, column };
+}
+
+// Routine Description:
+// - returns string containing text data exactly how it's stored internally, including doubling of
+// leading/trailing cells.
+// Arguments:
+// - none
+// Return Value:
+// - text stored in char row
+// - Note: will throw exception if out of memory
+std::wstring CharRow::GetTextRaw() const
+{
+ std::wstring wstr;
+ wstr.reserve(_data.size());
+ for (size_t i = 0; i < _data.size(); ++i)
+ {
+ auto glyph = GlyphAt(i);
+ for (auto it = glyph.begin(); it != glyph.end(); ++it)
+ {
+ wstr.push_back(*it);
+ }
+ }
+ return wstr;
+}
+
+std::wstring CharRow::GetText() const
+{
+ std::wstring wstr;
+ wstr.reserve(_data.size());
+
+ for (size_t i = 0; i < _data.size(); ++i)
+ {
+ auto glyph = GlyphAt(i);
+ if (!DbcsAttrAt(i).IsTrailing())
+ {
+ for (auto it = glyph.begin(); it != glyph.end(); ++it)
+ {
+ wstr.push_back(*it);
+ }
+ }
+ }
+ return wstr;
+}
+
+UnicodeStorage& CharRow::GetUnicodeStorage()
+{
+ return _pParent->GetUnicodeStorage();
+}
+
+const UnicodeStorage& CharRow::GetUnicodeStorage() const
+{
+ return _pParent->GetUnicodeStorage();
+}
+
+// Routine Description:
+// - calculates the key used by the given column of the char row to store glyph data in UnicodeStorage
+// Arguments:
+// - column - the column to generate the key for
+// Return Value:
+// - the COORD key for data access from UnicodeStorage for the column
+COORD CharRow::GetStorageKey(const size_t column) const
+{
+ return { gsl::narrow(column), _pParent->GetId() };
+}
+
+// Routine Description:
+// - Updates the pointer to the parent row (which might change if we shuffle the rows around)
+// Arguments:
+// - pParent - Pointer to the parent row
+void CharRow::UpdateParent(ROW* const pParent) noexcept
+{
+ _pParent = FAIL_FAST_IF_NULL(pParent);
+}
diff --git a/src/buffer/out/CharRow.hpp b/src/buffer/out/CharRow.hpp
new file mode 100644
index 00000000000..555dfd6beeb
--- /dev/null
+++ b/src/buffer/out/CharRow.hpp
@@ -0,0 +1,123 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- CharRow.hpp
+
+Abstract:
+- contains data structure for UCS2 encoded character data of a row
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+#include "CharRowCellReference.hpp"
+#include "CharRowCell.hpp"
+#include "UnicodeStorage.hpp"
+
+class ROW;
+
+// the characters of one row of screen buffer
+// we keep the following values so that we don't write
+// more pixels to the screen than we have to:
+// left is initialized to screenbuffer width. right is
+// initialized to zero.
+//
+// [ foo.bar 12-12-61 ]
+// ^ ^ ^ ^
+// | | | |
+// Chars Left Right end of Chars buffer
+class CharRow final
+{
+public:
+ using glyph_type = typename wchar_t;
+ using value_type = typename CharRowCell;
+ using iterator = typename std::vector::iterator;
+ using const_iterator = typename std::vector::const_iterator;
+ using reference = typename CharRowCellReference;
+
+ CharRow(size_t rowWidth, ROW* const pParent);
+
+ void SetWrapForced(const bool wrap) noexcept;
+ bool WasWrapForced() const noexcept;
+ void SetDoubleBytePadded(const bool doubleBytePadded) noexcept;
+ bool WasDoubleBytePadded() const noexcept;
+ size_t size() const noexcept;
+ void Reset();
+ [[nodiscard]]
+ HRESULT Resize(const size_t newSize) noexcept;
+ size_t MeasureLeft() const;
+ size_t MeasureRight() const noexcept;
+ void ClearCell(const size_t column);
+ bool ContainsText() const noexcept;
+ const DbcsAttribute& DbcsAttrAt(const size_t column) const;
+ DbcsAttribute& DbcsAttrAt(const size_t column);
+ void ClearGlyph(const size_t column);
+ std::wstring GetText() const;
+
+ // other functions implemented at the template class level
+ std::wstring GetTextRaw() const;
+
+ // working with glyphs
+ const reference GlyphAt(const size_t column) const;
+ reference GlyphAt(const size_t column);
+
+ // iterators
+ iterator begin() noexcept;
+ const_iterator cbegin() const noexcept;
+
+ iterator end() noexcept;
+ const_iterator cend() const noexcept;
+
+ UnicodeStorage& GetUnicodeStorage();
+ const UnicodeStorage& GetUnicodeStorage() const;
+ COORD GetStorageKey(const size_t column) const;
+
+ void UpdateParent(ROW* const pParent) noexcept;
+
+ friend CharRowCellReference;
+ friend constexpr bool operator==(const CharRow& a, const CharRow& b) noexcept;
+
+protected:
+ // Occurs when the user runs out of text in a given row and we're forced to wrap the cursor to the next line
+ bool _wrapForced;
+
+ // Occurs when the user runs out of text to support a double byte character and we're forced to the next line
+ bool _doubleBytePadded;
+
+ // storage for glyph data and dbcs attributes
+ std::vector _data;
+
+ // ROW that this CharRow belongs to
+ ROW* _pParent;
+};
+
+constexpr bool operator==(const CharRow& a, const CharRow& b) noexcept
+{
+ return (a._wrapForced == b._wrapForced &&
+ a._doubleBytePadded == b._doubleBytePadded &&
+ a._data == b._data);
+}
+
+template
+void OverwriteColumns(InputIt1 startChars, InputIt1 endChars, InputIt2 startAttrs, CharRow::iterator outIt)
+{
+ std::transform(startChars,
+ endChars,
+ startAttrs,
+ outIt,
+ [](const wchar_t wch, const DbcsAttribute attr)
+ {
+ return CharRow::value_type{ wch, attr };
+ });
+}
diff --git a/src/buffer/out/CharRowCell.cpp b/src/buffer/out/CharRowCell.cpp
new file mode 100644
index 00000000000..180c3520ce1
--- /dev/null
+++ b/src/buffer/out/CharRowCell.cpp
@@ -0,0 +1,86 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+#include "precomp.h"
+
+#include "CharRowCell.hpp"
+#include "unicode.hpp"
+
+
+// default glyph value, used for reseting the character data portion of a cell
+static constexpr wchar_t DefaultValue = UNICODE_SPACE;
+
+CharRowCell::CharRowCell() :
+ _wch{ DefaultValue },
+ _attr{}
+{
+}
+
+CharRowCell::CharRowCell(const wchar_t wch, const DbcsAttribute attr) :
+ _wch{ wch },
+ _attr{ attr }
+{
+}
+
+// Routine Description:
+// - "erases" the glyph. really sets it back to the default "empty" value
+void CharRowCell::EraseChars()
+{
+ if (_attr.IsGlyphStored())
+ {
+ _attr.SetGlyphStored(false);
+ }
+ _wch = DefaultValue;
+}
+
+// Routine Description:
+// - resets this object back to the defaults it would have from the default constructor
+void CharRowCell::Reset() noexcept
+{
+ _attr.Reset();
+ _wch = DefaultValue;
+}
+
+// Routine Description:
+// - checks if cell contains a space glyph
+// Return Value:
+// - true if cell contains a space glyph, false otherwise
+bool CharRowCell::IsSpace() const noexcept
+{
+ return !_attr.IsGlyphStored() && _wch == UNICODE_SPACE;
+}
+
+// Routine Description:
+// - Access the DbcsAttribute for the cell
+// Return Value:
+// - ref to the cells' DbcsAttribute
+DbcsAttribute& CharRowCell::DbcsAttr() noexcept
+{
+ return _attr;
+}
+
+// Routine Description:
+// - Access the DbcsAttribute for the cell
+// Return Value:
+// - ref to the cells' DbcsAttribute
+const DbcsAttribute& CharRowCell::DbcsAttr() const noexcept
+{
+ return _attr;
+}
+
+// Routine Description:
+// - Access the cell's wchar field. this does not access any char data through UnicodeStorage.
+// Return Value:
+// - the cell's wchar field
+wchar_t& CharRowCell::Char() noexcept
+{
+ return _wch;
+}
+
+// Routine Description:
+// - Access the cell's wchar field. this does not access any char data through UnicodeStorage.
+// Return Value:
+// - the cell's wchar field
+const wchar_t& CharRowCell::Char() const noexcept
+{
+ return _wch;
+}
diff --git a/src/buffer/out/CharRowCell.hpp b/src/buffer/out/CharRowCell.hpp
new file mode 100644
index 00000000000..cca4ad453d3
--- /dev/null
+++ b/src/buffer/out/CharRowCell.hpp
@@ -0,0 +1,60 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- CharRowCell.hpp
+
+Abstract:
+- data structure for one cell of a char row. contains the char data for one
+ coordinate position in the output buffer (leading/trailing information and
+ the char itself.
+
+Author(s):
+- Austin Diviness (AustDi) 02-May-2018
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+
+
+#if (defined(_M_IX86) || defined(_M_AMD64))
+// currently CharRowCell's fields use 3 bytes of memory, leaving the 4th byte in unused. this leads
+// to a rather large amount of useless memory allocated. so instead, pack CharRowCell by bytes instead of words.
+#pragma pack(push, 1)
+#endif
+
+
+class CharRowCell final
+{
+public:
+ CharRowCell();
+ CharRowCell(const wchar_t wch, const DbcsAttribute attr);
+
+ void EraseChars();
+ void Reset() noexcept;
+
+ bool IsSpace() const noexcept;
+
+ DbcsAttribute& DbcsAttr() noexcept;
+ const DbcsAttribute& DbcsAttr() const noexcept;
+
+ wchar_t& Char() noexcept;
+ const wchar_t& Char() const noexcept;
+
+ friend constexpr bool operator==(const CharRowCell& a, const CharRowCell& b) noexcept;
+private:
+ wchar_t _wch;
+ DbcsAttribute _attr;
+};
+
+#if (defined(_M_IX86) || defined(_M_AMD64))
+#pragma pack(pop)
+#endif
+
+constexpr bool operator==(const CharRowCell& a, const CharRowCell& b) noexcept
+{
+ return (a._wch == b._wch &&
+ a._attr == b._attr);
+}
diff --git a/src/buffer/out/CharRowCellReference.cpp b/src/buffer/out/CharRowCellReference.cpp
new file mode 100644
index 00000000000..b380ae8ee9f
--- /dev/null
+++ b/src/buffer/out/CharRowCellReference.cpp
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "UnicodeStorage.hpp"
+#include "CharRow.hpp"
+
+
+// Routine Description:
+// - assignment operator. will store extended glyph data in a separate storage location
+// Arguments:
+// - chars - the glyph data to store
+void CharRowCellReference::operator=(const std::wstring_view chars)
+{
+ THROW_HR_IF(E_INVALIDARG, chars.empty());
+ if (chars.size() == 1)
+ {
+ _cellData().Char() = chars.front();
+ _cellData().DbcsAttr().SetGlyphStored(false);
+ }
+ else
+ {
+ auto& storage = _parent.GetUnicodeStorage();
+ const auto key = _parent.GetStorageKey(_index);
+ storage.StoreGlyph(key, { chars.cbegin(), chars.cend() });
+ _cellData().DbcsAttr().SetGlyphStored(true);
+ }
+}
+
+// Routine Description:
+// - implicit conversion to vector operator.
+// Return Value:
+// - std::vector of the glyph data in the referenced cell
+CharRowCellReference::operator std::wstring_view() const
+{
+ return _glyphData();
+}
+
+// Routine Description:
+// - The CharRowCell this object "references"
+// Return Value:
+// - ref to the CharRowCell
+CharRowCell& CharRowCellReference::_cellData()
+{
+ return _parent._data.at(_index);
+}
+
+// Routine Description:
+// - The CharRowCell this object "references"
+// Return Value:
+// - ref to the CharRowCell
+const CharRowCell& CharRowCellReference::_cellData() const
+{
+ return _parent._data.at(_index);
+}
+
+// Routine Description:
+// - the glyph data of the referenced cell
+// Return Value:
+// - the glyph data
+std::wstring_view CharRowCellReference::_glyphData() const
+{
+ if (_cellData().DbcsAttr().IsGlyphStored())
+ {
+ const auto& text = _parent.GetUnicodeStorage().GetText(_parent.GetStorageKey(_index));
+
+ return { text.data(), text.size() };
+ }
+ else
+ {
+ return { &_cellData().Char(), 1 };
+ }
+}
+
+// Routine Description:
+// - gets read-only iterator to the beginning of the glyph data
+// Return Value:
+// - iterator of the glyph data
+CharRowCellReference::const_iterator CharRowCellReference::begin() const
+{
+ if (_cellData().DbcsAttr().IsGlyphStored())
+ {
+ return _parent.GetUnicodeStorage().GetText(_parent.GetStorageKey(_index)).data();
+ }
+ else
+ {
+ return &_cellData().Char();
+ }
+}
+
+// Routine Description:
+// - get read-only iterator to the end of the glyph data
+// Return Value:
+// - end iterator of the glyph data
+CharRowCellReference::const_iterator CharRowCellReference::end() const
+{
+ if (_cellData().DbcsAttr().IsGlyphStored())
+ {
+
+ const auto& chars = _parent.GetUnicodeStorage().GetText(_parent.GetStorageKey(_index));
+ return chars.data() + chars.size();
+ }
+ else
+ {
+ return &_cellData().Char() + 1;
+ }
+}
+
+bool operator==(const CharRowCellReference& ref, const std::vector& glyph)
+{
+ const DbcsAttribute& dbcsAttr = ref._cellData().DbcsAttr();
+ if (glyph.size() == 1 && dbcsAttr.IsGlyphStored())
+ {
+ return false;
+ }
+ else if (glyph.size() > 1 && !dbcsAttr.IsGlyphStored())
+ {
+ return false;
+ }
+ else if (glyph.size() == 1 && !dbcsAttr.IsGlyphStored())
+ {
+ return ref._cellData().Char() == glyph.front();
+ }
+ else
+ {
+ const auto& chars = ref._parent.GetUnicodeStorage().GetText(ref._parent.GetStorageKey(ref._index));
+ return chars == glyph;
+ }
+}
+
+bool operator==(const std::vector& glyph, const CharRowCellReference& ref)
+{
+ return ref == glyph;
+}
diff --git a/src/buffer/out/CharRowCellReference.hpp b/src/buffer/out/CharRowCellReference.hpp
new file mode 100644
index 00000000000..d1fb7e80cfb
--- /dev/null
+++ b/src/buffer/out/CharRowCellReference.hpp
@@ -0,0 +1,65 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- CharRowCellReference.hpp
+
+Abstract:
+- reference class for the glyph data of a char row cell
+
+Author(s):
+- Austin Diviness (AustDi) 02-May-2018
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+#include "CharRowCell.hpp"
+#include
+
+class CharRow;
+
+class CharRowCellReference final
+{
+public:
+
+ using const_iterator = const wchar_t*;
+
+ CharRowCellReference(CharRow& parent, const size_t index) :
+ _parent{ parent },
+ _index{ index }
+ {
+ }
+
+ ~CharRowCellReference() = default;
+ CharRowCellReference(const CharRowCellReference&) = default;
+ CharRowCellReference(CharRowCellReference&&) = default;
+
+ void operator=(const CharRowCellReference&) = delete;
+ void operator=(CharRowCellReference&&) = delete;
+
+ void operator=(const std::wstring_view chars);
+ operator std::wstring_view() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+
+ friend bool operator==(const CharRowCellReference& ref, const std::vector& glyph);
+ friend bool operator==(const std::vector& glyph, const CharRowCellReference& ref);
+
+private:
+ // what char row the object belongs to
+ CharRow& _parent;
+ // the index of the cell in the parent char row
+ const size_t _index;
+
+ CharRowCell& _cellData();
+ const CharRowCell& _cellData() const;
+
+ std::wstring_view _glyphData() const;
+};
+
+bool operator==(const CharRowCellReference& ref, const std::vector& glyph);
+bool operator==(const std::vector& glyph, const CharRowCellReference& ref);
diff --git a/src/buffer/out/DbcsAttribute.hpp b/src/buffer/out/DbcsAttribute.hpp
new file mode 100644
index 00000000000..34045efc1b4
--- /dev/null
+++ b/src/buffer/out/DbcsAttribute.hpp
@@ -0,0 +1,143 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- DbcsAttribute.hpp
+
+Abstract:
+- helper class for storing double byte character set information about a cell in the output buffer.
+
+Author(s):
+- Austin Diviness (AustDi) 26-Jan-2018
+
+Revision History:
+--*/
+
+#pragma once
+
+class DbcsAttribute final
+{
+public:
+ enum class Attribute : BYTE
+ {
+ Single = 0x00,
+ Leading = 0x01,
+ Trailing = 0x02
+ };
+
+ DbcsAttribute() noexcept :
+ _attribute{ Attribute::Single },
+ _glyphStored{ false }
+ {
+ }
+
+ DbcsAttribute(const Attribute attribute) noexcept :
+ _attribute{ attribute },
+ _glyphStored{ false }
+ {
+ }
+
+ constexpr bool IsSingle() const noexcept
+ {
+ return _attribute == Attribute::Single;
+ }
+
+ constexpr bool IsLeading() const noexcept
+ {
+ return _attribute == Attribute::Leading;
+ }
+
+ constexpr bool IsTrailing() const noexcept
+ {
+ return _attribute == Attribute::Trailing;
+ }
+
+ constexpr bool IsDbcs() const noexcept
+ {
+ return IsLeading() || IsTrailing();
+ }
+
+ constexpr bool IsGlyphStored() const noexcept
+ {
+ return _glyphStored;
+ }
+
+ void SetGlyphStored(const bool stored)
+ {
+ _glyphStored = stored;
+ }
+
+ void SetSingle() noexcept
+ {
+ _attribute = Attribute::Single;
+ }
+
+ void SetLeading() noexcept
+ {
+ _attribute = Attribute::Leading;
+ }
+
+ void SetTrailing() noexcept
+ {
+ _attribute = Attribute::Trailing;
+ }
+
+ void Reset() noexcept
+ {
+ SetSingle();
+ SetGlyphStored(false);
+ }
+
+ WORD GeneratePublicApiAttributeFormat() const noexcept
+ {
+ WORD publicAttribute = 0;
+ if (IsLeading())
+ {
+ WI_SetFlag(publicAttribute, COMMON_LVB_LEADING_BYTE);
+ }
+ if (IsTrailing())
+ {
+ WI_SetFlag(publicAttribute, COMMON_LVB_TRAILING_BYTE);
+ }
+ return publicAttribute;
+ }
+
+ static DbcsAttribute FromPublicApiAttributeFormat(WORD publicAttribute)
+ {
+ // it's not valid to be both a leading and trailing byte
+ if (WI_AreAllFlagsSet(publicAttribute, COMMON_LVB_LEADING_BYTE | COMMON_LVB_TRAILING_BYTE))
+ {
+ THROW_HR(E_INVALIDARG);
+ }
+
+ DbcsAttribute attr;
+ if (WI_IsFlagSet(publicAttribute, COMMON_LVB_LEADING_BYTE))
+ {
+ attr.SetLeading();
+ }
+ else if (WI_IsFlagSet(publicAttribute, COMMON_LVB_TRAILING_BYTE))
+ {
+ attr.SetTrailing();
+ }
+ return attr;
+ }
+
+ friend constexpr bool operator==(const DbcsAttribute& a, const DbcsAttribute& b) noexcept;
+
+private:
+ Attribute _attribute : 2;
+ bool _glyphStored : 1;
+
+#ifdef UNIT_TESTING
+ friend class TextBufferTests;
+#endif
+};
+
+constexpr bool operator==(const DbcsAttribute& a, const DbcsAttribute& b) noexcept
+{
+ return a._attribute == b._attribute;
+}
+
+static_assert(sizeof(DbcsAttribute) == sizeof(BYTE), "DbcsAttribute should be one byte big. if this changes then it needs"
+ " either an implicit conversion to a BYTE or an update to all places that assume it's a byte big");
diff --git a/src/buffer/out/OutputCell.cpp b/src/buffer/out/OutputCell.cpp
new file mode 100644
index 00000000000..7cc1d36d71b
--- /dev/null
+++ b/src/buffer/out/OutputCell.cpp
@@ -0,0 +1,118 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "OutputCell.hpp"
+
+#include "../../types/inc/GlyphWidth.hpp"
+#include "../../types/inc/convert.hpp"
+#include "../../inc/conattrs.hpp"
+
+static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
+
+OutputCell::OutputCell() :
+ _text{},
+ _dbcsAttribute{},
+ _textAttribute{ InvalidTextAttribute },
+ _behavior{ TextAttributeBehavior::Stored }
+{
+
+}
+
+OutputCell::OutputCell(const std::wstring_view charData,
+ const DbcsAttribute dbcsAttribute,
+ const TextAttributeBehavior behavior) :
+ _text{ UNICODE_INVALID },
+ _dbcsAttribute{ dbcsAttribute },
+ _textAttribute{ InvalidTextAttribute },
+ _behavior{ behavior }
+{
+ THROW_HR_IF(E_INVALIDARG, charData.empty());
+ _setFromStringView(charData);
+ _setFromBehavior(behavior);
+}
+
+OutputCell::OutputCell(const std::wstring_view charData,
+ const DbcsAttribute dbcsAttribute,
+ const TextAttribute textAttribute) :
+ _text{ UNICODE_INVALID },
+ _dbcsAttribute{ dbcsAttribute },
+ _textAttribute{ textAttribute },
+ _behavior{ TextAttributeBehavior::Stored }
+{
+ THROW_HR_IF(E_INVALIDARG, charData.empty());
+ _setFromStringView(charData);
+}
+
+OutputCell::OutputCell(const CHAR_INFO& charInfo) :
+ _text{ UNICODE_INVALID },
+ _dbcsAttribute{},
+ _textAttribute{ InvalidTextAttribute },
+ _behavior{ TextAttributeBehavior::Stored }
+{
+ _setFromCharInfo(charInfo);
+}
+
+OutputCell::OutputCell(const OutputCellView& cell)
+{
+ _setFromOutputCellView(cell);
+}
+
+const std::wstring_view OutputCell::Chars() const noexcept
+{
+ return _text;
+}
+
+void OutputCell::SetChars(const std::wstring_view chars)
+{
+ _setFromStringView(chars);
+}
+
+DbcsAttribute& OutputCell::DbcsAttr() noexcept
+{
+ return _dbcsAttribute;
+}
+
+TextAttribute& OutputCell::TextAttr()
+{
+ THROW_HR_IF(E_INVALIDARG, _behavior == TextAttributeBehavior::Current);
+ return _textAttribute;
+}
+
+void OutputCell::_setFromBehavior(const TextAttributeBehavior behavior)
+{
+ THROW_HR_IF(E_INVALIDARG, behavior == TextAttributeBehavior::Stored);
+}
+
+void OutputCell::_setFromCharInfo(const CHAR_INFO& charInfo)
+{
+ _text = charInfo.Char.UnicodeChar;
+
+ if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_LEADING_BYTE))
+ {
+ _dbcsAttribute.SetLeading();
+ }
+ else if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_TRAILING_BYTE))
+ {
+ _dbcsAttribute.SetTrailing();
+ }
+ _textAttribute.SetFromLegacy(charInfo.Attributes);
+
+ _behavior = TextAttributeBehavior::Stored;
+}
+
+void OutputCell::_setFromStringView(const std::wstring_view view)
+{
+ _text = view;
+}
+
+void OutputCell::_setFromOutputCellView(const OutputCellView& cell)
+{
+ _dbcsAttribute = cell.DbcsAttr();
+ _textAttribute = cell.TextAttr();
+ _behavior = cell.TextAttrBehavior();
+
+ const auto& view = cell.Chars();
+ _text = view;
+}
diff --git a/src/buffer/out/OutputCell.hpp b/src/buffer/out/OutputCell.hpp
new file mode 100644
index 00000000000..5783dfcfc1b
--- /dev/null
+++ b/src/buffer/out/OutputCell.hpp
@@ -0,0 +1,92 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- OutputCell.hpp
+
+Abstract:
+- Representation of all data stored in a cell of the output buffer.
+- RGB color supported.
+
+Author:
+- Austin Diviness (AustDi) 20-Mar-2018
+
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+#include "TextAttribute.hpp"
+#include "OutputCellView.hpp"
+
+#include
+#include
+
+class InvalidCharInfoConversionException : public std::exception
+{
+ const char* what() noexcept
+ {
+ return "Cannot convert to CHAR_INFO without explicit TextAttribute";
+ }
+};
+
+class OutputCell final
+{
+public:
+ OutputCell();
+
+ OutputCell(const std::wstring_view charData,
+ const DbcsAttribute dbcsAttribute,
+ const TextAttributeBehavior behavior);
+
+ OutputCell(const std::wstring_view charData,
+ const DbcsAttribute dbcsAttribute,
+ const TextAttribute textAttribute);
+
+ OutputCell(const CHAR_INFO& charInfo);
+ OutputCell(const OutputCellView& view);
+
+ OutputCell(const OutputCell&) = default;
+ OutputCell(OutputCell&&) = default;
+
+ OutputCell& operator=(const OutputCell&) = default;
+ OutputCell& operator=(OutputCell&&) = default;
+
+ ~OutputCell() = default;
+
+ const std::wstring_view Chars() const noexcept;
+ void SetChars(const std::wstring_view chars);
+
+ DbcsAttribute& DbcsAttr() noexcept;
+ TextAttribute& TextAttr();
+
+ constexpr const DbcsAttribute& DbcsAttr() const
+ {
+ return _dbcsAttribute;
+ }
+
+ const TextAttribute& TextAttr() const
+ {
+ THROW_HR_IF(E_INVALIDARG, _behavior == TextAttributeBehavior::Current);
+ return _textAttribute;
+ }
+
+ constexpr TextAttributeBehavior TextAttrBehavior() const
+ {
+ return _behavior;
+ }
+
+private:
+ // basic_string contains a small storage internally so we don't need
+ // to worry about heap allocation for short strings.
+ std::wstring _text;
+ DbcsAttribute _dbcsAttribute;
+ TextAttribute _textAttribute;
+ TextAttributeBehavior _behavior;
+
+ void _setFromBehavior(const TextAttributeBehavior behavior);
+ void _setFromCharInfo(const CHAR_INFO& charInfo);
+ void _setFromStringView(const std::wstring_view view);
+ void _setFromOutputCellView(const OutputCellView& cell);
+};
diff --git a/src/buffer/out/OutputCellIterator.cpp b/src/buffer/out/OutputCellIterator.cpp
new file mode 100644
index 00000000000..e213c2c4081
--- /dev/null
+++ b/src/buffer/out/OutputCellIterator.cpp
@@ -0,0 +1,560 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "OutputCellIterator.hpp"
+
+#include "../../types/inc/convert.hpp"
+#include "../../types/inc/Utf16Parser.hpp"
+#include "../../types/inc/GlyphWidth.hpp"
+#include "../../inc/conattrs.hpp"
+
+static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
+
+// Routine Description:
+// - This is a fill-mode iterator for one particular wchar. It will repeat forever if fillLimit is 0.
+// Arguments:
+// - wch - The character to use for filling
+// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
+OutputCellIterator::OutputCellIterator(const wchar_t& wch, const size_t fillLimit) :
+ _mode(Mode::Fill),
+ _currentView(s_GenerateView(wch)),
+ _run(),
+ _attr(InvalidTextAttribute),
+ _pos(0),
+ _distance(0),
+ _fillLimit(fillLimit)
+{
+
+}
+
+// Routine Description:
+// - This is a fill-mode iterator for one particular color. It will repeat forever if fillLimit is 0.
+// Arguments:
+// - attr - The color attribute to use for filling
+// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
+OutputCellIterator::OutputCellIterator(const TextAttribute& attr, const size_t fillLimit) :
+ _mode(Mode::Fill),
+ _currentView(s_GenerateView(attr)),
+ _run(),
+ _attr(InvalidTextAttribute),
+ _pos(0),
+ _distance(0),
+ _fillLimit(fillLimit)
+{
+
+}
+
+// Routine Description:
+// - This is a fill-mode iterator for one particular character and color. It will repeat forever if fillLimit is 0.
+// Arguments:
+// - wch - The character to use for filling
+// - attr - The color attribute to use for filling
+// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
+OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit) :
+ _mode(Mode::Fill),
+ _currentView(s_GenerateView(wch, attr)),
+ _run(),
+ _attr(InvalidTextAttribute),
+ _pos(0),
+ _distance(0),
+ _fillLimit(fillLimit)
+{
+
+}
+
+// Routine Description:
+// - This is a fill-mode iterator for one particular CHAR_INFO. It will repeat forever if fillLimit is 0.
+// Arguments:
+// - charInfo - The legacy character and color data to use for fililng (uses Unicode portion of text data)
+// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
+OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit) :
+ _mode(Mode::Fill),
+ _currentView(s_GenerateView(charInfo)),
+ _run(),
+ _attr(InvalidTextAttribute),
+ _pos(0),
+ _distance(0),
+ _fillLimit(fillLimit)
+{
+
+}
+
+// Routine Description:
+// - This is an iterator over a range of text only. No color data will be modified as the text is inserted.
+// Arguments:
+// - utf16Text - UTF-16 text range
+OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text) :
+ _mode(Mode::LooseTextOnly),
+ _currentView(s_GenerateView(utf16Text)),
+ _run(utf16Text),
+ _attr(InvalidTextAttribute),
+ _pos(0),
+ _distance(0),
+ _fillLimit(0)
+{
+
+}
+
+// Routine Description:
+// - This is an iterator over a range text that will apply the same color to every position.
+// Arguments:
+// - utf16Text - UTF-16 text range
+// - attribute - Color to apply over the entire range
+OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute) :
+ _mode(Mode::Loose),
+ _currentView(s_GenerateView(utf16Text, attribute)),
+ _run(utf16Text),
+ _attr(attribute),
+ _distance(0),
+ _pos(0),
+ _fillLimit(0)
+{
+
+}
+
+// Routine Description:
+// - This is an iterator over legacy colors only. The text is not modified.
+// Arguments:
+// - legacyAttrs - One legacy color item per cell
+// - unused - useless bool to change function signature for legacyAttrs constructor because the C++ compiler in
+// razzle cannot distinguish between a std::wstring_view and a std::basic_string_view
+// NOTE: This one internally casts to wchar_t because Razzle sees WORD and wchar_t as the same type
+// despite that Visual Studio build can tell the difference.
+OutputCellIterator::OutputCellIterator(const std::basic_string_view legacyAttrs, const bool /*unused*/) :
+ _mode(Mode::LegacyAttr),
+ _currentView(s_GenerateViewLegacyAttr(legacyAttrs.at(0))),
+ _run(std::wstring_view(reinterpret_cast(legacyAttrs.data()), legacyAttrs.size())),
+ _attr(InvalidTextAttribute),
+ _distance(0),
+ _pos(0),
+ _fillLimit(0)
+{
+
+}
+
+// Routine Description:
+// - This is an iterator over legacy cell data. We will use the unicode text and the legacy color attribute.
+// Arguments:
+// - charInfos - Multiple cell with unicode text and legacy color data.
+OutputCellIterator::OutputCellIterator(const std::basic_string_view charInfos) :
+ _mode(Mode::CharInfo),
+ _currentView(s_GenerateView(charInfos.at(0))),
+ _run(charInfos),
+ _attr(InvalidTextAttribute),
+ _distance(0),
+ _pos(0),
+ _fillLimit(0)
+{
+
+}
+
+// Routine Description:
+// - This is an iterator over existing OutputCells with full text and color data.
+// Arguments:
+// - cells - Multiple cells in a run
+OutputCellIterator::OutputCellIterator(const std::basic_string_view cells) :
+ _mode(Mode::Cell),
+ _currentView(s_GenerateView(cells.at(0))),
+ _run(cells),
+ _attr(InvalidTextAttribute),
+ _distance(0),
+ _pos(0),
+ _fillLimit(0)
+{
+
+}
+
+// Routine Description:
+// - Specifies whether this iterator is valid for dereferencing (still valid underlying data)
+// Return Value:
+// - True if the views on dereference are valid. False if it shouldn't be dereferenced.
+OutputCellIterator::operator bool() const noexcept
+{
+ try
+ {
+ switch (_mode)
+ {
+ case Mode::Loose:
+ case Mode::LooseTextOnly:
+ {
+ // In lieu of using start and end, this custom iterator type simply becomes bool false
+ // when we run out of items to iterate over.
+ return _pos < std::get(_run).length();
+ }
+ case Mode::Fill:
+ {
+ if (_fillLimit > 0)
+ {
+ return _pos < _fillLimit;
+ }
+ return true;
+ }
+ case Mode::Cell:
+ {
+ return _pos < std::get>(_run).length();
+ }
+ case Mode::CharInfo:
+ {
+ return _pos < std::get>(_run).length();
+ }
+ case Mode::LegacyAttr:
+ {
+ return _pos < std::get(_run).length();
+ }
+ default:
+ FAIL_FAST_HR(E_NOTIMPL);
+ }
+ }
+ CATCH_FAIL_FAST();
+}
+
+// Routine Description:
+// - Advances the iterator one position over the underlying data source.
+// Return Value:
+// - Reference to self after advancement.
+OutputCellIterator& OutputCellIterator::operator++()
+{
+ // Keep track of total distance moved (cells filled)
+ _distance++;
+
+ switch (_mode)
+ {
+ case Mode::Loose:
+ {
+ if (!_TryMoveTrailing())
+ {
+ // When walking through a text sequence, we need to move forward by the number of wchar_ts consumed in the previous view
+ // in case we had a surrogate pair (or wider complex sequence) in the previous view.
+ _pos += _currentView.Chars().size();
+ if (operator bool())
+ {
+ _currentView = s_GenerateView(std::get(_run).substr(_pos), _attr);
+ }
+ }
+ break;
+ }
+ case Mode::LooseTextOnly:
+ {
+ if (!_TryMoveTrailing())
+ {
+ // When walking through a text sequence, we need to move forward by the number of wchar_ts consumed in the previous view
+ // in case we had a surrogate pair (or wider complex sequence) in the previous view.
+ _pos += _currentView.Chars().size();
+ if (operator bool())
+ {
+ _currentView = s_GenerateView(std::get(_run).substr(_pos));
+ }
+ }
+ break;
+ }
+ case Mode::Fill:
+ {
+ if (!_TryMoveTrailing())
+ {
+ if (_currentView.DbcsAttr().IsTrailing())
+ {
+ auto dbcsAttr = _currentView.DbcsAttr();
+ dbcsAttr.SetLeading();
+
+ _currentView = OutputCellView(_currentView.Chars(),
+ dbcsAttr,
+ _currentView.TextAttr(),
+ _currentView.TextAttrBehavior());
+ }
+
+ if (_fillLimit > 0)
+ {
+ // We walk forward by one because we fill with the same cell over and over no matter what
+ _pos++;
+ }
+ }
+ break;
+ }
+ case Mode::Cell:
+ {
+ // Walk forward by one because cells are assumed to be in the form they needed to be
+ _pos++;
+ if (operator bool())
+ {
+ _currentView = s_GenerateView(std::get>(_run).at(_pos));
+ }
+ break;
+ }
+ case Mode::CharInfo:
+ {
+ // Walk forward by one because charinfos are just the legacy version of cells and prealigned to columns
+ _pos++;
+ if (operator bool())
+ {
+ _currentView = s_GenerateView(std::get>(_run).at(_pos));
+ }
+ break;
+ }
+ case Mode::LegacyAttr:
+ {
+ // Walk forward by one because color attributes apply cell by cell (no complex text information)
+ _pos++;
+ if (operator bool())
+ {
+ _currentView = s_GenerateViewLegacyAttr(std::get(_run).at(_pos));
+ }
+ break;
+ }
+ default:
+ FAIL_FAST_HR(E_NOTIMPL);
+ }
+
+ return (*this);
+}
+
+// Routine Description:
+// - Advances the iterator one position over the underlying data source.
+// Return Value:
+// - Reference to self after advancement.
+OutputCellIterator OutputCellIterator::operator++(int)
+{
+ auto temp(*this);
+ operator++();
+ return temp;
+}
+
+// Routine Description:
+// - Reference the view to fully-formed output cell data representing the underlying data source.
+// Return Value:
+// - Reference to the view
+const OutputCellView& OutputCellIterator::operator*() const
+{
+ return _currentView;
+}
+
+// Routine Description:
+// - Get pointer to the view to fully-formed output cell data representing the underlying data source.
+// Return Value:
+// - Pointer to the view
+const OutputCellView* OutputCellIterator::operator->() const
+{
+ return &_currentView;
+}
+
+// Routine Description:
+// - Checks the current view. If it is a leading half, it updates the current
+// view to the trailing half of the same glyph.
+// - This helps us to draw glyphs that are two columns wide by "doubling"
+// the view that is returned so it will consume two cells.
+// Return Value:
+// - True if we just turned a lead half into a trailing half (and caller doesn't
+// need to further update the view).
+// - False if this wasn't applicable and the caller should update the view.
+bool OutputCellIterator::_TryMoveTrailing()
+{
+ if (_currentView.DbcsAttr().IsLeading())
+ {
+ auto dbcsAttr = _currentView.DbcsAttr();
+ dbcsAttr.SetTrailing();
+
+ _currentView = OutputCellView(_currentView.Chars(),
+ dbcsAttr,
+ _currentView.TextAttr(),
+ _currentView.TextAttrBehavior());
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and specify that the attributes shouldn't be changed.
+// Arguments:
+// - view - View representing characters corresponding to a single glyph
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view)
+{
+ return s_GenerateView(view, InvalidTextAttribute, TextAttributeBehavior::Current);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - view - View representing characters corresponding to a single glyph
+// - attr - Color attributes to apply to the text
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
+ const TextAttribute attr)
+{
+ return s_GenerateView(view, attr, TextAttributeBehavior::Stored);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - view - View representing characters corresponding to a single glyph
+// - attr - Color attributes to apply to the text
+// - behavior - Behavior of the given text attribute (used when writing)
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
+ const TextAttribute attr,
+ const TextAttributeBehavior behavior)
+{
+ const auto glyph = Utf16Parser::ParseNext(view);
+ DbcsAttribute dbcsAttr;
+ if (!glyph.empty() && IsGlyphFullWidth(glyph))
+ {
+ dbcsAttr.SetLeading();
+ }
+
+ return OutputCellView(glyph, dbcsAttr, attr, behavior);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - wch - View representing a single UTF-16 character (that can be represented without surrogates)
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch)
+{
+ const auto glyph = std::wstring_view(&wch, 1);
+
+ DbcsAttribute dbcsAttr;
+ if (IsGlyphFullWidth(wch))
+ {
+ dbcsAttr.SetLeading();
+ }
+
+ return OutputCellView(glyph, dbcsAttr, InvalidTextAttribute, TextAttributeBehavior::Current);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - attr - View representing a single color
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const TextAttribute& attr)
+{
+ return OutputCellView({}, {}, attr, TextAttributeBehavior::StoredOnly);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - wch - View representing a single UTF-16 character (that can be represented without surrogates)
+// - attr - View representing a single color
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch, const TextAttribute& attr)
+{
+ const auto glyph = std::wstring_view(&wch, 1);
+
+ DbcsAttribute dbcsAttr;
+ if (IsGlyphFullWidth(wch))
+ {
+ dbcsAttr.SetLeading();
+ }
+
+ return OutputCellView(glyph, dbcsAttr, attr, TextAttributeBehavior::Stored);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - legacyAttr - View representing a single legacy color
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateViewLegacyAttr(const WORD& legacyAttr)
+{
+ WORD cleanAttr = legacyAttr;
+ WI_ClearAllFlags(cleanAttr, COMMON_LVB_SBCSDBCS); // don't use legacy lead/trailing byte flags for colors
+
+ TextAttribute attr(cleanAttr);
+ return s_GenerateView(attr);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - charInfo - character and attribute pair representing a single cell
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const CHAR_INFO& charInfo)
+{
+ const auto glyph = std::wstring_view(&charInfo.Char.UnicodeChar, 1);
+
+ DbcsAttribute dbcsAttr;
+ if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_LEADING_BYTE))
+ {
+ dbcsAttr.SetLeading();
+ }
+ else if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_TRAILING_BYTE))
+ {
+ dbcsAttr.SetTrailing();
+ }
+
+ TextAttribute textAttr;
+ textAttr.SetFromLegacy(charInfo.Attributes);
+
+ const auto behavior = TextAttributeBehavior::Stored;
+ return OutputCellView(glyph, dbcsAttr, textAttr, behavior);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// Arguments:
+// - cell - A reference to the cell for which we will make the read-only view
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView OutputCellIterator::s_GenerateView(const OutputCell& cell)
+{
+ return OutputCellView(cell.Chars(), cell.DbcsAttr(), cell.TextAttr(), cell.TextAttrBehavior());
+}
+
+// Routine Description:
+// - Gets the distance between two iterators relative to the input data given in.
+// Return Value:
+// - The number of items of the input run consumed between these two iterators.
+ptrdiff_t OutputCellIterator::GetInputDistance(OutputCellIterator other) const noexcept
+{
+ return _pos - other._pos;
+}
+
+// Routine Description:
+// - Gets the distance between two iterators relative to the number of cells inserted.
+// Return Value:
+// - The number of cells in the backing buffer filled between these two iterators.
+ptrdiff_t OutputCellIterator::GetCellDistance(OutputCellIterator other) const noexcept
+{
+ return _distance - other._distance;
+}
diff --git a/src/buffer/out/OutputCellIterator.hpp b/src/buffer/out/OutputCellIterator.hpp
new file mode 100644
index 00000000000..dc7bdc958ed
--- /dev/null
+++ b/src/buffer/out/OutputCellIterator.hpp
@@ -0,0 +1,124 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- OutputCellIterator.hpp
+
+Abstract:
+- Read-only view into an entire batch of data to be written into the output buffer.
+- This is done for performance reasons (avoid heap allocs and copies).
+
+Author:
+- Michael Niksa (MiNiksa) 06-Oct-2018
+
+Revision History:
+- Based on work from OutputCell.hpp/cpp by Austin Diviness (AustDi)
+
+--*/
+
+#pragma once
+
+#include "TextAttribute.hpp"
+
+#include "OutputCell.hpp"
+#include "OutputCellView.hpp"
+
+class OutputCellIterator final
+{
+public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = OutputCellView;
+ using difference_type = ptrdiff_t;
+ using pointer = OutputCellView*;
+ using reference = OutputCellView&;
+
+ OutputCellIterator(const wchar_t& wch, const size_t fillLimit = 0);
+ OutputCellIterator(const TextAttribute& attr, const size_t fillLimit = 0);
+ OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit = 0);
+ OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0);
+ OutputCellIterator(const std::wstring_view utf16Text);
+ OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute);
+ OutputCellIterator(const std::basic_string_view legacyAttributes, const bool unused);
+ OutputCellIterator(const std::basic_string_view charInfos);
+ OutputCellIterator(const std::basic_string_view cells);
+ ~OutputCellIterator() = default;
+
+ OutputCellIterator& operator=(const OutputCellIterator& it) = default;
+
+ operator bool() const noexcept;
+
+ ptrdiff_t GetCellDistance(OutputCellIterator other) const noexcept;
+ ptrdiff_t GetInputDistance(OutputCellIterator other) const noexcept;
+ friend ptrdiff_t operator-(OutputCellIterator one, OutputCellIterator two) = delete;
+
+ OutputCellIterator& operator++();
+ OutputCellIterator operator++(int);
+
+ const OutputCellView& operator*() const;
+ const OutputCellView* operator->() const;
+
+private:
+
+ enum class Mode
+ {
+ // Loose mode is where we're given text and attributes in a raw sort of form
+ // like while data is being inserted from an API call.
+ Loose,
+
+ // Loose mode with only text is where we're given just text and we want
+ // to use the attribute already in the buffer when writing
+ LooseTextOnly,
+
+ // Fill mode is where we were given one thing and we just need to keep giving
+ // that back over and over for eternity.
+ Fill,
+
+ // Given a run of legacy attributes, convert each of them and insert only attribute data.
+ LegacyAttr,
+
+ // CharInfo mode is where we've been given a pair of text and attribute for each
+ // cell in the legacy format from an API call.
+ CharInfo,
+
+ // Cell mode is where we have an already fully structured cell data usually
+ // from accessing/copying data already put into the OutputBuffer.
+ Cell,
+ };
+ Mode _mode;
+
+ std::basic_string_view _legacyAttrs;
+
+ std::variant<
+ std::wstring_view,
+ std::basic_string_view,
+ std::basic_string_view,
+ std::monostate> _run;
+
+ TextAttribute _attr;
+
+ bool _TryMoveTrailing();
+
+ static OutputCellView s_GenerateView(const std::wstring_view view);
+
+ static OutputCellView s_GenerateView(const std::wstring_view view,
+ const TextAttribute attr);
+
+ static OutputCellView s_GenerateView(const std::wstring_view view,
+ const TextAttribute attr,
+ const TextAttributeBehavior behavior);
+
+ static OutputCellView s_GenerateView(const wchar_t& wch);
+ static OutputCellView s_GenerateViewLegacyAttr(const WORD& legacyAttr);
+ static OutputCellView s_GenerateView(const TextAttribute& attr);
+ static OutputCellView s_GenerateView(const wchar_t& wch, const TextAttribute& attr);
+ static OutputCellView s_GenerateView(const CHAR_INFO& charInfo);
+
+ static OutputCellView s_GenerateView(const OutputCell& cell);
+
+ OutputCellView _currentView;
+
+ size_t _pos;
+ size_t _distance;
+ size_t _fillLimit;
+};
diff --git a/src/buffer/out/OutputCellRect.cpp b/src/buffer/out/OutputCellRect.cpp
new file mode 100644
index 00000000000..444e394798b
--- /dev/null
+++ b/src/buffer/out/OutputCellRect.cpp
@@ -0,0 +1,99 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "OutputCellRect.hpp"
+
+// Routine Description:
+// - Constucts an empty in-memory region for holding output buffer cell data.
+OutputCellRect::OutputCellRect() :
+ _rows(0),
+ _cols(0)
+{
+
+}
+
+// Routine Description:
+// - Constructs an in-memory region for holding a copy of output buffer cell data.
+// - NOTE: This creatively skips the constructors for every cell. You must fill
+// every single cell in this rectangle before iterating/reading for it to be valid.
+// - NOTE: This is designed for perf-sensitive paths ONLY. Take care.
+// Arguments:
+// - rows - Rows in the rectangle (height)
+// - cols - Columns in the rectangle (width)
+OutputCellRect::OutputCellRect(const size_t rows, const size_t cols) :
+ _rows(rows),
+ _cols(cols)
+{
+ size_t totalCells;
+ THROW_IF_FAILED(SizeTMult(rows, cols, &totalCells));
+
+ _storage.resize(totalCells);
+}
+
+// Routine Description:
+// - Gets a read/write span over a single row inside the rectangle.
+// Arguments:
+// - row - The Y position or row index in the buffer.
+// Return Value:
+// - Read/write span of OutputCells
+gsl::span OutputCellRect::GetRow(const size_t row)
+{
+ return gsl::span(_FindRowOffset(row), _cols);
+}
+
+// Routine Description:
+// - Gets a read-only iterator view over a single row of the rectangle.
+// Arguments:
+// - row - The Y position or row index in the buffer.
+// Return Value:
+// - Read-only iterator of OutputCells
+OutputCellIterator OutputCellRect::GetRowIter(const size_t row) const
+{
+ const std::basic_string_view view(_FindRowOffset(row), _cols);
+
+ return OutputCellIterator(view);
+}
+
+// Routine Description:
+// - Internal helper to find the pointer to the specific row offset in the giant
+// contiguous block of memory allocated for this rectangle.
+// Arguments:
+// - row - The Y position or row index in the buffer.
+// Return Value:
+// - Pointer to the location in the rectangle that represents the start of the requested row.
+OutputCell* OutputCellRect::_FindRowOffset(const size_t row)
+{
+ return (_storage.data() + (row * _cols));
+}
+
+// Routine Description:
+// - Internal helper to find the pointer to the specific row offset in the giant
+// contiguous block of memory allocated for this rectangle.
+// Arguments:
+// - row - The Y position or row index in the buffer.
+// Return Value:
+// - Pointer to the location in the rectangle that represents the start of the requested row.
+const OutputCell* OutputCellRect::_FindRowOffset(const size_t row) const
+{
+ return (_storage.data() + (row * _cols));
+}
+
+// Routine Description:
+// - Gets the height of the rectangle
+// Return Value:
+// - Height
+size_t OutputCellRect::Height() const noexcept
+{
+ return _rows;
+}
+
+// Routine Description:
+// - Gets the width of the rectangle
+// Return Value:
+// - Width
+size_t OutputCellRect::Width() const noexcept
+{
+ return _cols;
+}
diff --git a/src/buffer/out/OutputCellRect.hpp b/src/buffer/out/OutputCellRect.hpp
new file mode 100644
index 00000000000..9d6b05b6cd2
--- /dev/null
+++ b/src/buffer/out/OutputCellRect.hpp
@@ -0,0 +1,49 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- OutputCellRect.hpp
+
+Abstract:
+- Designed to hold a rectangular area of OutputCells where the column/row count is known ahead of time.
+- This is done for performance reasons (one big heap allocation block with appropriate views instead of tiny allocations.)
+- NOTE: For cases where the internal buffer will not change during your call, use Iterators and Views to completely
+ avoid any copy or allocate at all. Only use this when a copy of your content or the buffer is needed.
+
+Author:
+- Michael Niksa (MiNiksa) 12-Oct-2018
+
+Revision History:
+- Based on work from OutputCell.hpp/cpp by Austin Diviness (AustDi)
+
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+#include "TextAttribute.hpp"
+#include "OutputCell.hpp"
+#include "OutputCellIterator.hpp"
+
+class OutputCellRect final
+{
+public:
+ OutputCellRect();
+ OutputCellRect(const size_t rows, const size_t cols);
+
+ gsl::span GetRow(const size_t row);
+ OutputCellIterator GetRowIter(const size_t row) const;
+
+ size_t Height() const noexcept;
+ size_t Width() const noexcept;
+
+private:
+ std::vector _storage;
+
+ OutputCell* _FindRowOffset(const size_t row);
+ const OutputCell* _FindRowOffset(const size_t row) const;
+
+ size_t _cols;
+ size_t _rows;
+};
diff --git a/src/buffer/out/OutputCellView.cpp b/src/buffer/out/OutputCellView.cpp
new file mode 100644
index 00000000000..b5de8a823d1
--- /dev/null
+++ b/src/buffer/out/OutputCellView.cpp
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "OutputCellView.hpp"
+
+// Routine Description:
+// - Constructs a read-only view of data formatted as a single output buffer cell
+// Arguments:
+// - view - String data for the text displayed on screen
+// - dbcsAttr - Describes column width information (double byte character data)
+// - textAttr - Describes color and formatting data
+// - behavior - Describes where to retrieve color/format data. From this view? From defaults? etc.
+OutputCellView::OutputCellView(const std::wstring_view view,
+ const DbcsAttribute dbcsAttr,
+ const TextAttribute textAttr,
+ const TextAttributeBehavior behavior) :
+ _view(view),
+ _dbcsAttr(dbcsAttr),
+ _textAttr(textAttr),
+ _behavior(behavior)
+{
+
+}
+
+// Routine Description:
+// - Returns reference to view over text data
+// Return Value:
+// - Reference to UTF-16 character data
+const std::wstring_view& OutputCellView::Chars() const noexcept
+{
+ return _view;
+}
+
+// Routine Description:
+// - Reports how many columns we expect the Chars() text data to consume
+// Return Value:
+// - Count of column cells on the screen
+size_t OutputCellView::Columns() const noexcept
+{
+ if (DbcsAttr().IsSingle())
+ {
+ return 1;
+ }
+ else if (DbcsAttr().IsLeading())
+ {
+ return 2;
+ }
+ else if (DbcsAttr().IsTrailing())
+ {
+ return 1;
+ }
+
+ return 1;
+}
+
+// Routine Description:
+// - Retrieves character cell width data
+// Return Value:
+// - DbcsAttribute data
+DbcsAttribute OutputCellView::DbcsAttr() const noexcept
+{
+ return _dbcsAttr;
+}
+
+// Routine Description:
+// - Retrieves text color/formatting information
+// Return Value:
+// - TextAttribute with encoded formatting data
+TextAttribute OutputCellView::TextAttr() const noexcept
+{
+ return _textAttr;
+}
+
+// Routine Description:
+// - Retrieves behavior for inserting this cell into the buffer. See enum for details.
+// Return Value:
+// - TextAttributeBehavior enum value
+TextAttributeBehavior OutputCellView::TextAttrBehavior() const noexcept
+{
+ return _behavior;
+}
+
+// Routine Description:
+// - Compares two views
+// Arguments:
+// - it - Other view to compare to this one
+// Return Value:
+// - True if all contents/references are equal. False otherwise.
+bool OutputCellView::operator==(const OutputCellView& it) const noexcept
+{
+ return _view == it._view &&
+ _dbcsAttr == it._dbcsAttr &&
+ _textAttr == it._textAttr &&
+ _behavior == it._behavior;
+}
+
+// Routine Description:
+// - Compares two views for inequality
+// Arguments:
+// - it - Other view to compare tot his one.
+// Return Value:
+// - True if any contents or references are inequal. False if they're all equal.
+bool OutputCellView::operator!=(const OutputCellView& it) const noexcept
+{
+ return !(*this == it);
+}
diff --git a/src/buffer/out/OutputCellView.hpp b/src/buffer/out/OutputCellView.hpp
new file mode 100644
index 00000000000..470222a0c2a
--- /dev/null
+++ b/src/buffer/out/OutputCellView.hpp
@@ -0,0 +1,48 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- OutputCellView.hpp
+
+Abstract:
+- Read-only view into a single cell of data that someone is attempting to write into the output buffer.
+- This is done for performance reasons (avoid heap allocs and copies).
+
+Author:
+- Michael Niksa (MiNiksa) 06-Oct-2018
+
+Revision History:
+- Based on work from OutputCell.hpp/cpp by Austin Diviness (AustDi)
+
+--*/
+
+#pragma once
+
+#include "DbcsAttribute.hpp"
+#include "TextAttribute.hpp"
+
+class OutputCellView
+{
+public:
+
+ OutputCellView(const std::wstring_view view,
+ const DbcsAttribute dbcsAttr,
+ const TextAttribute textAttr,
+ const TextAttributeBehavior behavior);
+
+ const std::wstring_view& Chars() const noexcept;
+ size_t Columns() const noexcept;
+ DbcsAttribute DbcsAttr() const noexcept;
+ TextAttribute TextAttr() const noexcept;
+ TextAttributeBehavior TextAttrBehavior() const noexcept;
+
+ bool operator==(const OutputCellView& view) const noexcept;
+ bool operator!=(const OutputCellView& view) const noexcept;
+
+private:
+ std::wstring_view _view;
+ DbcsAttribute _dbcsAttr;
+ TextAttribute _textAttr;
+ TextAttributeBehavior _behavior;
+};
diff --git a/src/buffer/out/Row.cpp b/src/buffer/out/Row.cpp
new file mode 100644
index 00000000000..e3a32f35961
--- /dev/null
+++ b/src/buffer/out/Row.cpp
@@ -0,0 +1,222 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "Row.hpp"
+#include "CharRow.hpp"
+#include "textBuffer.hpp"
+#include "../types/inc/convert.hpp"
+
+// Routine Description:
+// - constructor
+// Arguments:
+// - rowId - the row index in the text buffer
+// - rowWidth - the width of the row, cell elements
+// - fillAttribute - the default text attribute
+// - pParent - the text buffer that this row belongs to
+// Return Value:
+// - constructed object
+ROW::ROW(const SHORT rowId, const short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) :
+ _id{ rowId },
+ _rowWidth{ gsl::narrow(rowWidth) },
+ _charRow{ gsl::narrow(rowWidth), this },
+ _attrRow{ gsl::narrow(rowWidth), fillAttribute },
+ _pParent{ pParent }
+{
+}
+
+size_t ROW::size() const noexcept
+{
+ return _rowWidth;
+}
+
+const CharRow& ROW::GetCharRow() const
+{
+ return _charRow;
+}
+
+CharRow& ROW::GetCharRow()
+{
+ return const_cast(static_cast(this)->GetCharRow());
+}
+
+const ATTR_ROW& ROW::GetAttrRow() const noexcept
+{
+ return _attrRow;
+}
+
+ATTR_ROW& ROW::GetAttrRow() noexcept
+{
+ return const_cast(static_cast(this)->GetAttrRow());
+}
+
+SHORT ROW::GetId() const noexcept
+{
+ return _id;
+}
+
+void ROW::SetId(const SHORT id) noexcept
+{
+ _id = id;
+}
+
+// Routine Description:
+// - Sets all properties of the ROW to default values
+// Arguments:
+// - Attr - The default attribute (color) to fill
+// Return Value:
+// -
+bool ROW::Reset(const TextAttribute Attr)
+{
+ _charRow.Reset();
+ try
+ {
+ _attrRow.Reset(Attr);
+ }
+ catch (...)
+ {
+ LOG_CAUGHT_EXCEPTION();
+ return false;
+ }
+ return true;
+}
+
+// Routine Description:
+// - resizes ROW to new width
+// Arguments:
+// - width - the new width, in cells
+// Return Value:
+// - S_OK if successful, otherwise relevant error
+[[nodiscard]]
+HRESULT ROW::Resize(const size_t width)
+{
+ RETURN_IF_FAILED(_charRow.Resize(width));
+ try
+ {
+ _attrRow.Resize(width);
+ }
+ CATCH_RETURN();
+
+ _rowWidth = width;
+
+ return S_OK;
+}
+
+// Routine Description:
+// - clears char data in column in row
+// Arguments:
+// - column - 0-indexed column index
+// Return Value:
+// -
+void ROW::ClearColumn(const size_t column)
+{
+ THROW_HR_IF(E_INVALIDARG, column >= _charRow.size());
+ _charRow.ClearCell(column);
+}
+
+// Routine Description:
+// - gets the text of the row as it would be shown on the screen
+// Return Value:
+// - wstring containing text for the row
+std::wstring ROW::GetText() const
+{
+ return _charRow.GetText();
+}
+
+RowCellIterator ROW::AsCellIter(const size_t startIndex) const
+{
+ return AsCellIter(startIndex, size() - startIndex);
+}
+
+RowCellIterator ROW::AsCellIter(const size_t startIndex, const size_t count) const
+{
+ return RowCellIterator(*this, startIndex, count);
+}
+
+UnicodeStorage& ROW::GetUnicodeStorage()
+{
+ return _pParent->GetUnicodeStorage();
+}
+
+const UnicodeStorage& ROW::GetUnicodeStorage() const
+{
+ return _pParent->GetUnicodeStorage();
+}
+
+// Routine Description:
+// - writes cell data to the row
+// Arguments:
+// - it - custom console iterator to use for seeking input data. bool() false when it becomes invalid while seeking.
+// - index - column in row to start writing at
+// - setWrap - set the wrap flags if we hit the end of the row while writing and there's still more data in the iterator.
+// - limitRight - right inclusive column ID for the last write in this row. (optional, will just write to the end of row if nullopt)
+// Return Value:
+// - iterator to first cell that was not written to this row.
+OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const bool setWrap, std::optional limitRight)
+{
+ THROW_HR_IF(E_INVALIDARG, index >= _charRow.size());
+ THROW_HR_IF(E_INVALIDARG, limitRight.value_or(0) >= _charRow.size());
+ size_t currentIndex = index;
+
+ // If we're given a right-side column limit, use it. Otherwise, the write limit is the final column index available in the char row.
+ const auto finalColumnInRow = limitRight.value_or(_charRow.size() - 1);
+
+ while (it && currentIndex <= finalColumnInRow)
+ {
+ // Fill the color if the behavior isn't set to keeping the current color.
+ if (it->TextAttrBehavior() != TextAttributeBehavior::Current)
+ {
+ const TextAttributeRun attrRun{ 1, it->TextAttr() };
+ LOG_IF_FAILED(_attrRow.InsertAttrRuns({ &attrRun, 1 },
+ currentIndex,
+ currentIndex,
+ _charRow.size()));
+ }
+
+ // Fill the text if the behavior isn't set to saying there's only a color stored in this iterator.
+ if (it->TextAttrBehavior() != TextAttributeBehavior::StoredOnly)
+ {
+ const bool fillingLastColumn = currentIndex == finalColumnInRow;
+
+ // TODO: MSFT: 19452170 - We need to ensure when writing any trailing byte that the one to the left
+ // is a matching leading byte. Likewise, if we're writing a leading byte, we need to make sure we still have space in this loop
+ // for the trailing byte coming up before writing it.
+
+ // If we're trying to fill the first cell with a trailing byte, pad it out instead by clearing it.
+ // Don't increment iterator. We'll advance the index and try again with this value on the next round through the loop.
+ if (currentIndex == 0 && it->DbcsAttr().IsTrailing())
+ {
+ _charRow.ClearCell(currentIndex);
+ }
+ // If we're trying to fill the last cell with a leading byte, pad it out instead by clearing it.
+ // Don't increment iterator. We'll exit because we couldn't write a lead at the end of a line.
+ else if (fillingLastColumn && it->DbcsAttr().IsLeading())
+ {
+ _charRow.ClearCell(currentIndex);
+ _charRow.SetDoubleBytePadded(true);
+ }
+ // Otherwise, copy the data given and increment the iterator.
+ else
+ {
+ _charRow.DbcsAttrAt(currentIndex) = it->DbcsAttr();
+ _charRow.GlyphAt(currentIndex) = it->Chars();
+ ++it;
+ }
+
+ // If we're asked to set the wrap status and we just filled the last column with some text, set wrap status on the row.
+ if (setWrap && fillingLastColumn)
+ {
+ _charRow.SetWrapForced(true);
+ }
+ }
+ else
+ {
+ ++it;
+ }
+
+ // Move to the next cell for the next time through the loop.
+ ++currentIndex;
+ }
+
+ return it;
+}
diff --git a/src/buffer/out/Row.hpp b/src/buffer/out/Row.hpp
new file mode 100644
index 00000000000..697fad812db
--- /dev/null
+++ b/src/buffer/out/Row.hpp
@@ -0,0 +1,84 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- Row.hpp
+
+Abstract:
+- data structure for information associated with one row of screen buffer
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+--*/
+
+#pragma once
+
+#include "AttrRow.hpp"
+#include "OutputCell.hpp"
+#include "OutputCellIterator.hpp"
+#include "CharRow.hpp"
+#include "RowCellIterator.hpp"
+#include "UnicodeStorage.hpp"
+
+class TextBuffer;
+
+class ROW final
+{
+public:
+ ROW(const SHORT rowId, const short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent);
+
+ size_t size() const noexcept;
+
+ const CharRow& GetCharRow() const;
+ CharRow& GetCharRow();
+
+ const ATTR_ROW& GetAttrRow() const noexcept;
+ ATTR_ROW& GetAttrRow() noexcept;
+
+ SHORT GetId() const noexcept;
+ void SetId(const SHORT id) noexcept;
+
+ bool Reset(const TextAttribute Attr);
+ [[nodiscard]]
+ HRESULT Resize(const size_t width);
+
+ void ClearColumn(const size_t column);
+ std::wstring GetText() const;
+
+ RowCellIterator AsCellIter(const size_t startIndex) const;
+ RowCellIterator AsCellIter(const size_t startIndex, const size_t count) const;
+
+ UnicodeStorage& GetUnicodeStorage();
+ const UnicodeStorage& GetUnicodeStorage() const;
+
+ OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const bool setWrap, std::optional limitRight = std::nullopt);
+
+ friend bool operator==(const ROW& a, const ROW& b) noexcept;
+
+#ifdef UNIT_TESTING
+ friend class RowTests;
+#endif
+
+private:
+ CharRow _charRow;
+ ATTR_ROW _attrRow;
+ SHORT _id;
+ size_t _rowWidth;
+ TextBuffer* _pParent; // non ownership pointer
+};
+
+inline bool operator==(const ROW& a, const ROW& b) noexcept
+{
+ return (a._charRow == b._charRow &&
+ a._attrRow == b._attrRow &&
+ a._rowWidth == b._rowWidth &&
+ a._pParent == b._pParent &&
+ a._id == b._id);
+}
diff --git a/src/buffer/out/RowCellIterator.cpp b/src/buffer/out/RowCellIterator.cpp
new file mode 100644
index 00000000000..2a681e1cf9c
--- /dev/null
+++ b/src/buffer/out/RowCellIterator.cpp
@@ -0,0 +1,111 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "RowCellIterator.hpp"
+#include "Row.hpp"
+
+#include "../../types/inc/convert.hpp"
+#include "../../types/inc/Utf16Parser.hpp"
+
+RowCellIterator::RowCellIterator(const ROW& row, const size_t start, const size_t length) :
+ _row(row),
+ _start(start),
+ _length(length),
+ _pos(start),
+ _view(s_GenerateView(row, start))
+{
+
+}
+
+RowCellIterator::operator bool() const noexcept
+{
+ // In lieu of using start and end, this custom iterator type simply becomes bool false
+ // when we run out of items to iterate over.
+ return _pos < (_start + _length);
+}
+
+bool RowCellIterator::operator==(const RowCellIterator& it) const noexcept
+{
+ return _row == it._row &&
+ _start == it._start &&
+ _length == it._length &&
+ _pos == it._pos;
+}
+bool RowCellIterator::operator!=(const RowCellIterator& it) const noexcept
+{
+ return !(*this == it);
+}
+
+RowCellIterator& RowCellIterator::operator+=(const ptrdiff_t& movement)
+{
+ _pos += movement;
+
+ return (*this);
+}
+
+RowCellIterator& RowCellIterator::operator++()
+{
+ return this->operator+=(1);
+}
+
+RowCellIterator RowCellIterator::operator++(int)
+{
+ auto temp(*this);
+ operator++();
+ return temp;
+}
+
+RowCellIterator RowCellIterator::operator+(const ptrdiff_t& movement)
+{
+ auto temp(*this);
+ temp += movement;
+ return temp;
+}
+
+const OutputCellView& RowCellIterator::operator*() const
+{
+ return _view;
+}
+
+const OutputCellView* RowCellIterator::operator->() const
+{
+ return &_view;
+}
+
+// Routine Description:
+// - Member function to update the view to the current position in the buffer with
+// the data held on this object.
+// Arguments:
+// -
+// Return Value:
+// -
+void RowCellIterator::_RefreshView()
+{
+ _view = s_GenerateView(_row, _pos);
+}
+
+// Routine Description:
+// - Static function to create a view.
+// - It's pulled out statically so it can be used during construction with just the given
+// variables (so OutputCellView doesn't need an empty default constructor)
+// - This will infer the width of the glyph and apply the appropriate attributes to the view.
+// Arguments:
+// - view - View representing characters corresponding to a single glyph
+// - attr - Color attributes to apply to the text
+// Return Value:
+// - Object representing the view into this cell
+OutputCellView RowCellIterator::s_GenerateView(const ROW& row,
+ const size_t pos)
+{
+ const auto& charRow = row.GetCharRow();
+
+ const auto glyph = charRow.GlyphAt(pos);
+ const auto dbcsAttr = charRow.DbcsAttrAt(pos);
+
+ const auto textAttr = row.GetAttrRow().GetAttrByColumn(pos);
+ const auto behavior = TextAttributeBehavior::Stored;
+
+ return OutputCellView(glyph, dbcsAttr, textAttr, behavior);
+}
diff --git a/src/buffer/out/RowCellIterator.hpp b/src/buffer/out/RowCellIterator.hpp
new file mode 100644
index 00000000000..c386bb6afa1
--- /dev/null
+++ b/src/buffer/out/RowCellIterator.hpp
@@ -0,0 +1,59 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- RowCellIterator.hpp
+
+Abstract:
+- Read-only view into cells already in the input buffer.
+- This is done for performance reasons (avoid heap allocs and copies).
+
+Author:
+- Michael Niksa (MiNiksa) 12-Oct-2018
+
+--*/
+
+#pragma once
+
+#include "OutputCellView.hpp"
+class ROW;
+
+class RowCellIterator final
+{
+public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = OutputCellView;
+ using difference_type = ptrdiff_t;
+ using pointer = OutputCellView*;
+ using reference = OutputCellView&;
+
+ RowCellIterator(const ROW& row, const size_t start, const size_t length);
+ ~RowCellIterator() = default;
+
+ RowCellIterator& operator=(const RowCellIterator& it) = default;
+
+ operator bool() const noexcept;
+
+ bool operator==(const RowCellIterator& it) const noexcept;
+ bool operator!=(const RowCellIterator& it) const noexcept;
+
+ RowCellIterator& operator+=(const ptrdiff_t& movement);
+ RowCellIterator& operator++();
+ RowCellIterator operator++(int);
+ RowCellIterator operator+(const ptrdiff_t& movement);
+
+ const OutputCellView& operator*() const;
+ const OutputCellView* operator->() const;
+
+private:
+ const ROW& _row;
+ const size_t _start;
+ const size_t _length;
+
+ size_t _pos;
+ OutputCellView _view;
+
+ void _RefreshView();
+ static OutputCellView s_GenerateView(const ROW& row, const size_t pos);
+};
diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp
new file mode 100644
index 00000000000..4e0003eece2
--- /dev/null
+++ b/src/buffer/out/TextAttribute.cpp
@@ -0,0 +1,268 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "TextAttribute.hpp"
+#include "../../inc/conattrs.hpp"
+
+bool TextAttribute::IsLegacy() const noexcept
+{
+ return _foreground.IsLegacy() && _background.IsLegacy();
+}
+
+// Arguments:
+// - None
+// Return Value:
+// - color that should be displayed as the foreground color
+COLORREF TextAttribute::CalculateRgbForeground(std::basic_string_view colorTable,
+ COLORREF defaultFgColor,
+ COLORREF defaultBgColor) const
+{
+ return _IsReverseVideo() ? _GetRgbBackground(colorTable, defaultBgColor) : _GetRgbForeground(colorTable, defaultFgColor);
+}
+
+// Routine Description:
+// - Calculates rgb background color based off of current color table and active modification attributes
+// Arguments:
+// - None
+// Return Value:
+// - color that should be displayed as the background color
+COLORREF TextAttribute::CalculateRgbBackground(std::basic_string_view colorTable,
+ COLORREF defaultFgColor,
+ COLORREF defaultBgColor) const
+{
+ return _IsReverseVideo() ? _GetRgbForeground(colorTable, defaultFgColor) : _GetRgbBackground(colorTable, defaultBgColor);
+}
+
+// Routine Description:
+// - gets rgb foreground color, possibly based off of current color table. Does not take active modification
+// attributes into account
+// Arguments:
+// - None
+// Return Value:
+// - color that is stored as the foreground color
+COLORREF TextAttribute::_GetRgbForeground(std::basic_string_view colorTable,
+ COLORREF defaultColor) const
+{
+ return _foreground.GetColor(colorTable, defaultColor, _isBold);
+}
+
+// Routine Description:
+// - gets rgb background color, possibly based off of current color table. Does not take active modification
+// attributes into account
+// Arguments:
+// - None
+// Return Value:
+// - color that is stored as the background color
+COLORREF TextAttribute::_GetRgbBackground(std::basic_string_view colorTable,
+ COLORREF defaultColor) const
+{
+ return _background.GetColor(colorTable, defaultColor, false);
+}
+
+void TextAttribute::SetMetaAttributes(const WORD wMeta) noexcept
+{
+ WI_UpdateFlagsInMask(_wAttrLegacy, META_ATTRS, wMeta);
+ WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
+}
+
+WORD TextAttribute::GetMetaAttributes() const noexcept
+{
+ WORD wMeta = _wAttrLegacy;
+ WI_ClearAllFlags(wMeta, FG_ATTRS);
+ WI_ClearAllFlags(wMeta, BG_ATTRS);
+ WI_ClearAllFlags(wMeta, COMMON_LVB_SBCSDBCS);
+ return wMeta;
+}
+
+void TextAttribute::SetForeground(const COLORREF rgbForeground)
+{
+ _foreground = TextColor(rgbForeground);
+}
+
+void TextAttribute::SetBackground(const COLORREF rgbBackground)
+{
+ _background = TextColor(rgbBackground);
+}
+
+void TextAttribute::SetFromLegacy(const WORD wLegacy) noexcept
+{
+ _wAttrLegacy = static_cast(wLegacy & META_ATTRS);
+ WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
+ BYTE fgIndex = static_cast(wLegacy & FG_ATTRS);
+ BYTE bgIndex = static_cast(wLegacy & BG_ATTRS) >> 4;
+ _foreground = TextColor(fgIndex);
+ _background = TextColor(bgIndex);
+}
+
+void TextAttribute::SetLegacyAttributes(const WORD attrs,
+ const bool setForeground,
+ const bool setBackground,
+ const bool setMeta)
+{
+ if (setForeground)
+ {
+ BYTE fgIndex = (BYTE)(attrs & FG_ATTRS);
+ _foreground = TextColor(fgIndex);
+ }
+ if (setBackground)
+ {
+ BYTE bgIndex = (BYTE)(attrs & BG_ATTRS) >> 4;
+ _background = TextColor(bgIndex);
+ }
+ if (setMeta)
+ {
+ SetMetaAttributes(attrs);
+ }
+}
+
+// Method Description:
+// - Sets the foreground and/or background to a particular index in the 256color
+// table. If either parameter is nullptr, it's ignored.
+// This method can be used to set the colors to indexes in the range [0, 255],
+// as opposed to SetLegacyAttributes, which clamps them to [0,15]
+// Arguments:
+// - foreground: nullptr if we should ignore this attr, else a pointer to a byte
+// value to use as an index into the 256-color table.
+// - background: nullptr if we should ignore this attr, else a pointer to a byte
+// value to use as an index into the 256-color table.
+// Return Value:
+// -
+void TextAttribute::SetIndexedAttributes(const std::optional foreground,
+ const std::optional background) noexcept
+{
+ if (foreground)
+ {
+ BYTE fgIndex = (*foreground) & 0xFF;
+ _foreground = TextColor(fgIndex);
+ }
+ if (background)
+ {
+ BYTE bgIndex = (*background) & 0xFF;
+ _background = TextColor(bgIndex);
+ }
+}
+
+void TextAttribute::SetColor(const COLORREF rgbColor, const bool fIsForeground)
+{
+ if (fIsForeground)
+ {
+ SetForeground(rgbColor);
+ }
+ else
+ {
+ SetBackground(rgbColor);
+ }
+}
+
+bool TextAttribute::IsBold() const noexcept
+{
+ return _isBold;
+}
+
+bool TextAttribute::_IsReverseVideo() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO);
+}
+
+bool TextAttribute::IsLeadingByte() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_LEADING_BYTE);
+}
+
+bool TextAttribute::IsTrailingByte() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_LEADING_BYTE);
+}
+
+bool TextAttribute::IsTopHorizontalDisplayed() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL);
+}
+
+bool TextAttribute::IsBottomHorizontalDisplayed() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_UNDERSCORE);
+}
+
+bool TextAttribute::IsLeftVerticalDisplayed() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_LVERTICAL);
+}
+
+bool TextAttribute::IsRightVerticalDisplayed() const noexcept
+{
+ return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_RVERTICAL);
+}
+
+void TextAttribute::SetLeftVerticalDisplayed(const bool isDisplayed) noexcept
+{
+ WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_LVERTICAL, isDisplayed);
+}
+
+void TextAttribute::SetRightVerticalDisplayed(const bool isDisplayed) noexcept
+{
+ WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_RVERTICAL, isDisplayed);
+}
+
+void TextAttribute::Embolden() noexcept
+{
+ _SetBoldness(true);
+}
+
+void TextAttribute::Debolden() noexcept
+{
+ _SetBoldness(false);
+}
+
+// Routine Description:
+// - swaps foreground and background color
+void TextAttribute::Invert() noexcept
+{
+ WI_ToggleFlag(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO);
+}
+
+void TextAttribute::_SetBoldness(const bool isBold) noexcept
+{
+ _isBold = isBold;
+}
+
+void TextAttribute::SetDefaultForeground() noexcept
+{
+ _foreground = TextColor();
+}
+
+void TextAttribute::SetDefaultBackground() noexcept
+{
+ _background = TextColor();
+}
+
+// Method Description:
+// - Returns true if this attribute indicates it's foreground is the "default"
+// foreground. It's _rgbForeground will contain the actual value of the
+// default foreground. If the default colors are ever changed, this method
+// should be used to identify attributes with the default fg value, and
+// update them accordingly.
+// Arguments:
+// -
+// Return Value:
+// - true iff this attribute indicates it's the "default" foreground color.
+bool TextAttribute::ForegroundIsDefault() const noexcept
+{
+ return _foreground.IsDefault();
+}
+
+// Method Description:
+// - Returns true if this attribute indicates it's background is the "default"
+// background. It's _rgbBackground will contain the actual value of the
+// default background. If the default colors are ever changed, this method
+// should be used to identify attributes with the default bg value, and
+// update them accordingly.
+// Arguments:
+// -
+// Return Value:
+// - true iff this attribute indicates it's the "default" background color.
+bool TextAttribute::BackgroundIsDefault() const noexcept
+{
+ return _background.IsDefault();
+}
diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp
new file mode 100644
index 00000000000..5d5485b6d1b
--- /dev/null
+++ b/src/buffer/out/TextAttribute.hpp
@@ -0,0 +1,235 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- TextAttribute.hpp
+
+Abstract:
+- contains data structure for run-length-encoding of text attribute data
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+- Pulled each of the fg/bg colors into their own abstraction (migrie, Nov 2018)
+--*/
+
+#pragma once
+#include "TextColor.h"
+#include "../../inc/conattrs.hpp"
+
+#ifdef UNIT_TESTING
+#include "WexTestClass.h"
+#endif
+
+class TextAttribute final
+{
+public:
+ constexpr TextAttribute() noexcept :
+ _wAttrLegacy{ 0 },
+ _foreground{},
+ _background{},
+ _isBold{ false }
+ {
+ }
+
+ constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
+ _wAttrLegacy{ static_cast(wLegacyAttr & META_ATTRS) },
+ _foreground{ static_cast(wLegacyAttr & FG_ATTRS) },
+ _background{ static_cast((wLegacyAttr & BG_ATTRS) >> 4) },
+ _isBold{ false }
+ {
+ // If we're given lead/trailing byte information with the legacy color, strip it.
+ WI_ClearAllFlags(_wAttrLegacy, COMMON_LVB_SBCSDBCS);
+ }
+
+ constexpr TextAttribute(const COLORREF rgbForeground,
+ const COLORREF rgbBackground) noexcept :
+ _wAttrLegacy{ 0 },
+ _foreground{ rgbForeground },
+ _background{ rgbBackground },
+ _isBold{ false }
+ {
+ }
+
+ constexpr WORD GetLegacyAttributes() const noexcept
+ {
+ BYTE fg = (_foreground.GetIndex() & FG_ATTRS);
+ BYTE bg = (_background.GetIndex() << 4) & BG_ATTRS;
+ WORD meta = (_wAttrLegacy & META_ATTRS);
+ return (fg | bg | meta) | (_isBold ? FOREGROUND_INTENSITY : 0);
+ }
+
+ // Method Description:
+ // - Returns a WORD with legacy-style attributes for this textattribute.
+ // If either the foreground or background of this textattribute is not
+ // a legacy attribute, then instead use the provided default index as
+ // the value for that component.
+ // Arguments:
+ // - defaultFgIndex: the BYTE to use as the index for the foreground, should
+ // the foreground not be a legacy style attribute.
+ // - defaultBgIndex: the BYTE to use as the index for the backgound, should
+ // the background not be a legacy style attribute.
+ // Return Value:
+ // - a WORD with legacy-style attributes for this textattribute.
+ constexpr WORD GetLegacyAttributes(const BYTE defaultFgIndex,
+ const BYTE defaultBgIndex) const noexcept
+ {
+ BYTE fgIndex = _foreground.IsLegacy() ? _foreground.GetIndex() : defaultFgIndex;
+ BYTE bgIndex = _background.IsLegacy() ? _background.GetIndex() : defaultBgIndex;
+ BYTE fg = (fgIndex & FG_ATTRS);
+ BYTE bg = (bgIndex << 4) & BG_ATTRS;
+ WORD meta = (_wAttrLegacy & META_ATTRS);
+ return (fg | bg | meta) | (_isBold ? FOREGROUND_INTENSITY : 0);
+ }
+
+ COLORREF CalculateRgbForeground(std::basic_string_view colorTable,
+ COLORREF defaultFgColor,
+ COLORREF defaultBgColor) const;
+ COLORREF CalculateRgbBackground(std::basic_string_view colorTable,
+ COLORREF defaultFgColor,
+ COLORREF defaultBgColor) const;
+
+ bool IsLeadingByte() const noexcept;
+ bool IsTrailingByte() const noexcept;
+ bool IsTopHorizontalDisplayed() const noexcept;
+ bool IsBottomHorizontalDisplayed() const noexcept;
+ bool IsLeftVerticalDisplayed() const noexcept;
+ bool IsRightVerticalDisplayed() const noexcept;
+
+ void SetLeftVerticalDisplayed(const bool isDisplayed) noexcept;
+ void SetRightVerticalDisplayed(const bool isDisplayed) noexcept;
+
+ void SetFromLegacy(const WORD wLegacy) noexcept;
+
+ void SetLegacyAttributes(const WORD attrs,
+ const bool setForeground,
+ const bool setBackground,
+ const bool setMeta);
+
+ void SetIndexedAttributes(const std::optional foreground,
+ const std::optional background) noexcept;
+
+ void SetMetaAttributes(const WORD wMeta) noexcept;
+ WORD GetMetaAttributes() const noexcept;
+
+ void Embolden() noexcept;
+ void Debolden() noexcept;
+
+ void Invert() noexcept;
+
+ friend constexpr bool operator==(const TextAttribute& a, const TextAttribute& b) noexcept;
+ friend constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexcept;
+ friend constexpr bool operator==(const TextAttribute& attr, const WORD& legacyAttr) noexcept;
+ friend constexpr bool operator!=(const TextAttribute& attr, const WORD& legacyAttr) noexcept;
+ friend constexpr bool operator==(const WORD& legacyAttr, const TextAttribute& attr) noexcept;
+ friend constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept;
+
+ bool IsLegacy() const noexcept;
+ bool IsBold() const noexcept;
+
+ void SetForeground(const COLORREF rgbForeground);
+ void SetBackground(const COLORREF rgbBackground);
+ void SetColor(const COLORREF rgbColor, const bool fIsForeground);
+
+ void SetDefaultForeground() noexcept;
+ void SetDefaultBackground() noexcept;
+
+ bool ForegroundIsDefault() const noexcept;
+ bool BackgroundIsDefault() const noexcept;
+
+ constexpr bool IsRgb() const noexcept
+ {
+ return _foreground.IsRgb() || _background.IsRgb();
+ }
+
+private:
+ COLORREF _GetRgbForeground(std::basic_string_view colorTable,
+ COLORREF defaultColor) const;
+ COLORREF _GetRgbBackground(std::basic_string_view colorTable,
+ COLORREF defaultColor) const;
+ bool _IsReverseVideo() const noexcept;
+ void _SetBoldness(const bool isBold) noexcept;
+
+ WORD _wAttrLegacy;
+ TextColor _foreground;
+ TextColor _background;
+ bool _isBold;
+
+#ifdef UNIT_TESTING
+ friend class TextBufferTests;
+ friend class TextAttributeTests;
+ template friend class WEX::TestExecution::VerifyOutputTraits;
+#endif
+};
+
+enum class TextAttributeBehavior
+{
+ Stored, // use contained text attribute
+ Current, // use text attribute of cell being written to
+ StoredOnly, // only use the contained text attribute and skip the insertion of anything else
+};
+
+constexpr bool operator==(const TextAttribute& a, const TextAttribute& b) noexcept
+{
+ return a._wAttrLegacy == b._wAttrLegacy &&
+ a._foreground == b._foreground &&
+ a._background == b._background &&
+ a._isBold == b._isBold;
+}
+
+constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexcept
+{
+ return !(a == b);
+}
+
+constexpr bool operator==(const TextAttribute& attr, const WORD& legacyAttr) noexcept
+{
+ return attr.GetLegacyAttributes() == legacyAttr;
+}
+
+constexpr bool operator!=(const TextAttribute& attr, const WORD& legacyAttr) noexcept
+{
+ return !(attr == legacyAttr);
+}
+
+constexpr bool operator==(const WORD& legacyAttr, const TextAttribute& attr) noexcept
+{
+ return attr == legacyAttr;
+}
+
+constexpr bool operator!=(const WORD& legacyAttr, const TextAttribute& attr) noexcept
+{
+ return !(attr == legacyAttr);
+}
+
+#ifdef UNIT_TESTING
+
+#define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format(\
+ L#attr L"=%s", VerifyOutputTraits::ToString(attr).GetBuffer())))
+
+namespace WEX {
+ namespace TestExecution {
+ template<>
+ class VerifyOutputTraits < TextAttribute >
+ {
+ public:
+ static WEX::Common::NoThrowString ToString(const TextAttribute& attr)
+ {
+ return WEX::Common::NoThrowString().Format(
+ L"{FG:%s,BG:%s,bold:%d,wLegacy:(0x%04x)}",
+ VerifyOutputTraits::ToString(attr._foreground).GetBuffer(),
+ VerifyOutputTraits::ToString(attr._background).GetBuffer(),
+ attr.IsBold(),
+ attr._wAttrLegacy
+ );
+ }
+ };
+ }
+}
+#endif
diff --git a/src/buffer/out/TextAttributeRun.cpp b/src/buffer/out/TextAttributeRun.cpp
new file mode 100644
index 00000000000..a2045eaaea1
--- /dev/null
+++ b/src/buffer/out/TextAttributeRun.cpp
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "TextAttributeRun.hpp"
+
+TextAttributeRun::TextAttributeRun() noexcept :
+ _cchLength(0)
+{
+ SetAttributes(TextAttribute(0));
+}
+
+TextAttributeRun::TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept :
+ _cchLength(cchLength)
+{
+ SetAttributes(attr);
+}
+
+size_t TextAttributeRun::GetLength() const noexcept
+{
+ return _cchLength;
+}
+
+void TextAttributeRun::SetLength(const size_t cchLength) noexcept
+{
+ _cchLength = cchLength;
+}
+
+void TextAttributeRun::IncrementLength() noexcept
+{
+ _cchLength++;
+}
+
+void TextAttributeRun::DecrementLength() noexcept
+{
+ _cchLength--;
+}
+
+const TextAttribute& TextAttributeRun::GetAttributes() const noexcept
+{
+ return _attributes;
+}
+
+void TextAttributeRun::SetAttributes(const TextAttribute textAttribute) noexcept
+{
+ _attributes = textAttribute;
+}
+
+// Routine Description:
+// - Sets the attributes of this run to the given legacy attributes
+// Arguments:
+// - wNew - the new value for this run's attributes
+// Return Value:
+//
+void TextAttributeRun::SetAttributesFromLegacy(const WORD wNew) noexcept
+{
+ _attributes.SetFromLegacy(wNew);
+}
diff --git a/src/buffer/out/TextAttributeRun.hpp b/src/buffer/out/TextAttributeRun.hpp
new file mode 100644
index 00000000000..ff0c9179949
--- /dev/null
+++ b/src/buffer/out/TextAttributeRun.hpp
@@ -0,0 +1,47 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- TextAttributeRun.hpp
+
+Abstract:
+- contains data structure for run-length-encoding of text attribute data
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+--*/
+
+#pragma once
+
+#include "TextAttribute.hpp"
+
+class TextAttributeRun final
+{
+public:
+ TextAttributeRun() noexcept;
+ TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept;
+
+ size_t GetLength() const noexcept;
+ void SetLength(const size_t cchLength) noexcept;
+ void IncrementLength() noexcept;
+ void DecrementLength() noexcept;
+
+ const TextAttribute& GetAttributes() const noexcept;
+ void SetAttributes(const TextAttribute textAttribute) noexcept;
+ void SetAttributesFromLegacy(const WORD wNew) noexcept;
+
+private:
+ size_t _cchLength;
+ TextAttribute _attributes;
+
+#ifdef UNIT_TESTING
+ friend class AttrRowTests;
+#endif
+};
diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp
new file mode 100644
index 00000000000..90c6323dd67
--- /dev/null
+++ b/src/buffer/out/TextColor.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "TextColor.h"
+
+// Method Description:
+// - Sets the color value of this attribute, and sets this color to be an RGB
+// attribute.
+// Arguments:
+// - rgbColor: the COLORREF containing the color information for this TextColor
+// Return Value:
+// -
+void TextColor::SetColor(const COLORREF rgbColor)
+{
+ _meta = ColorType::IsRgb;
+ _red = GetRValue(rgbColor);
+ _green = GetGValue(rgbColor);
+ _blue = GetBValue(rgbColor);
+}
+
+// Method Description:
+// - Sets this TextColor to be a legacy-style index into the color table.
+// Arguments:
+// - index: the index of the colortable we should use for this TextColor.
+// Return Value:
+// -
+void TextColor::SetIndex(const BYTE index)
+{
+ _meta = ColorType::IsIndex;
+ _index = index;
+}
+
+// Method Description:
+// - Sets this TextColor to be a default text color, who's appearance is
+// controlled by the terminal's implementation of what a default color is.
+// Arguments:
+// -
+// Return Value:
+// -
+void TextColor::SetDefault()
+{
+ _meta = ColorType::IsDefault;
+}
+
+// Method Description:
+// - Retrieve the real color value for this TextColor.
+// * If we're an RGB color, we'll use that value.
+// * If we're an indexed color table value, we'll use that index to look up
+// our value in the provided color table.
+// - If brighten is true, and the index is in the "dark" portion of the
+// color table (indicies [0,7]), then we'll look up the bright version of
+// this color (from indicies [8,15]). This should be true for
+// TextAttributes that are "Bold" and we're treating bold as bright
+// (which is the default behavior of most terminals.)
+// * If we're a default color, we'll return the default color provided.
+// Arguments:
+// - colorTable: The table of colors we should use to look up the value of a
+// legacy attribute from
+// - 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(std::basic_string_view colorTable,
+ const COLORREF defaultColor,
+ bool brighten) const
+{
+ if (IsDefault())
+ {
+ if (brighten)
+ {
+ FAIL_FAST_IF(colorTable.size() < 16);
+ // See MSFT:20266024 for context on this fix.
+ // Additionally todo MSFT:20271956 to fix this better for 19H2+
+ // If we're a default color, check to see if the defaultColor exists
+ // in the dark section of the color table. If it does, then chances
+ // are we're not a separate default color, instead we're an index
+ // color being used as the default color
+ // (Settings::_DefaultForeground==INVALID_COLOR, and the index
+ // from _wFillAttribute is being used instead.)
+ // If we find a match, return instead the bright version of this color
+ for (size_t i = 0; i < 8; i++)
+ {
+ if (colorTable[i] == defaultColor)
+ {
+ return colorTable[i + 8];
+ }
+ }
+
+ }
+
+ return defaultColor;
+ }
+ else if (IsRgb())
+ {
+ return _GetRGB();
+ }
+ else
+ {
+ FAIL_FAST_IF(colorTable.size() < _index);
+ // If the color is already bright (it's in index [8,15] or it's a
+ // 256color value [16,255], then boldness does nothing.
+ if (brighten && _index < 8)
+ {
+ FAIL_FAST_IF(colorTable.size() < 16);
+ FAIL_FAST_IF((size_t)(_index + 8) > (size_t)(colorTable.size()));
+ return colorTable[_index + 8];
+ }
+ else
+ {
+ return colorTable[_index];
+ }
+ }
+}
+
+// Method Description:
+// - Return a COLORREF containing our stored value. Will return garbage if this
+//attribute is not a RGB attribute.
+// Arguments:
+// -
+// Return Value:
+// - a COLORREF containing our stored value
+COLORREF TextColor::_GetRGB() const
+{
+ return RGB(_red, _green, _blue);
+}
diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h
new file mode 100644
index 00000000000..52885b02db0
--- /dev/null
+++ b/src/buffer/out/TextColor.h
@@ -0,0 +1,169 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- TextColor.h
+
+Abstract:
+- contains data for a single color of the text. Text Attributes are composed of
+ two of these - one for the foreground and one for the background.
+ The color can be in one of three states:
+ * Default Colors - The terminal should use the terminal's notion of whatever
+ the default color should be for this component.
+ It's up to the terminal that's consuming this buffer to control the
+ behavior of default attributes.
+ Terminals typically have a pair of Default colors that are separate from
+ their color table. This component should use that value.
+ Consoles also can have a legacy table index as their default colors.
+ * Indexed Color - The terminal should use our value as an index into the
+ color table to retrieve the real value of the color.
+ This is the type of color that "legacy" 16-color attributes have.
+ * RGB color - We'll store a real color value in this attribute
+
+Author(s):
+- Mike Griese (migrie) Nov 2018
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
+- Moved the colors into their own seperate abstraction. (migrie Nov 2018)
+--*/
+
+#pragma once
+
+#ifdef UNIT_TESTING
+#include "WexTestClass.h"
+#endif
+
+#pragma pack(push, 1)
+
+enum class ColorType : BYTE
+{
+ IsIndex = 0x0,
+ IsDefault = 0x1,
+ IsRgb = 0x2
+};
+
+struct TextColor
+{
+public:
+
+ constexpr TextColor() noexcept :
+ _meta{ ColorType::IsDefault },
+ _red{ 0 },
+ _green{ 0 },
+ _blue{ 0 }
+ {
+ }
+
+ constexpr TextColor(const BYTE wLegacyAttr) noexcept :
+ _meta{ ColorType::IsIndex },
+ _index{ wLegacyAttr },
+ _green{ 0 },
+ _blue{ 0 }
+ {
+ }
+
+ constexpr TextColor(const COLORREF rgb) noexcept :
+ _meta{ ColorType::IsRgb },
+ _red{ GetRValue(rgb) },
+ _green{ GetGValue(rgb) },
+ _blue{ GetBValue(rgb) }
+ {
+ }
+
+ friend constexpr bool operator==(const TextColor& a, const TextColor& b) noexcept;
+ friend constexpr bool operator!=(const TextColor& a, const TextColor& b) noexcept;
+
+ constexpr bool IsLegacy() const noexcept
+ {
+ return !(IsDefault() || IsRgb());
+ }
+
+ constexpr bool IsDefault() const noexcept
+ {
+ return _meta == ColorType::IsDefault;
+ }
+
+ constexpr bool IsRgb() const noexcept
+ {
+ return _meta == ColorType::IsRgb;
+ }
+
+ void SetColor(const COLORREF rgbColor);
+ void SetIndex(const BYTE index);
+ void SetDefault();
+
+ COLORREF GetColor(std::basic_string_view colorTable,
+ const COLORREF defaultColor,
+ const bool brighten) const;
+
+ constexpr BYTE GetIndex() const noexcept
+ {
+ return _index;
+ }
+
+
+private:
+ ColorType _meta : 2;
+ union
+ {
+ BYTE _red, _index;
+ };
+ BYTE _green;
+ BYTE _blue;
+
+ COLORREF _GetRGB() const;
+
+#ifdef UNIT_TESTING
+ friend class TextBufferTests;
+ template friend class WEX::TestExecution::VerifyOutputTraits;
+#endif
+};
+
+#pragma pack(pop)
+
+bool constexpr operator==(const TextColor& a, const TextColor& b) noexcept
+{
+ return a._meta == b._meta &&
+ a._red == b._red &&
+ a._green == b._green &&
+ a._blue == b._blue;
+}
+
+bool constexpr operator!=(const TextColor& a, const TextColor& b) noexcept
+{
+ return !(a == b);
+}
+
+#ifdef UNIT_TESTING
+
+namespace WEX {
+ namespace TestExecution {
+ template<>
+ class VerifyOutputTraits < TextColor >
+ {
+ public:
+ static WEX::Common::NoThrowString ToString(const TextColor& color)
+ {
+ if (color.IsDefault())
+ {
+ return L"{default}";
+ }
+ else if (color.IsRgb())
+ {
+ return WEX::Common::NoThrowString().Format(L"{RGB:0x%06x}", color._GetRGB());
+ }
+ else
+ {
+ return WEX::Common::NoThrowString().Format(L"{index:0x%04x}", color._red);
+ }
+ }
+ };
+ }
+}
+#endif
+
+static_assert(sizeof(TextColor) <= 4*sizeof(BYTE), "We should only need 4B for an entire TextColor. Any more than that is just waste");
diff --git a/src/buffer/out/UnicodeStorage.cpp b/src/buffer/out/UnicodeStorage.cpp
new file mode 100644
index 00000000000..813cf3fd490
--- /dev/null
+++ b/src/buffer/out/UnicodeStorage.cpp
@@ -0,0 +1,98 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "UnicodeStorage.hpp"
+
+UnicodeStorage::UnicodeStorage() :
+ _map{}
+{
+}
+
+// Routine Description:
+// - fetches the text associated with key
+// Arguments:
+// - key - the key into the storage
+// Return Value:
+// - the glyph data associated with key
+// Note: will throw exception if key is not stored yet
+const UnicodeStorage::mapped_type& UnicodeStorage::GetText(const key_type key) const
+{
+ return _map.at(key);
+}
+
+// Routine Description:
+// - stores glyph data associated with key.
+// Arguments:
+// - key - the key into the storage
+// - glyph - the glyph data to store
+void UnicodeStorage::StoreGlyph(const key_type key, const mapped_type& glyph)
+{
+ _map.insert_or_assign(key, glyph);
+}
+
+// Routine Description:
+// - erases key and it's associated data from the storage
+// Arguments:
+// - key - the key to remove
+void UnicodeStorage::Erase(const key_type key) noexcept
+{
+ _map.erase(key);
+}
+
+// Routine Description:
+// - Remaps all of the stored items to new coordinate positions
+// based on a bulk rearrangement of row IDs and potential row width resize.
+// Arguments:
+// - rowMap - A map of the old row IDs to the new row IDs.
+// - width - The width of the new row. Remove any items that are beyond the row width.
+// - Use nullopt if we're not resizing the width of the row, just renumbering the rows.
+void UnicodeStorage::Remap(const std::map& rowMap, const std::optional width)
+{
+ // Make a temporary map to hold all the new row positioning
+ std::unordered_map newMap;
+
+ // Walk through every stored item.
+ for (const auto& pair : _map)
+ {
+ // Extract the old coordinate position
+ const auto oldCoord = pair.first;
+
+ // Only try to short-circuit based on width if we were told it changed
+ // by being given a new width value.
+ if (width.has_value())
+ {
+ // Get the column ID
+ const auto oldColId = oldCoord.X;
+
+ // If the column index is at/beyond the row width, don't bother copying it to the new map.
+ if (oldColId >= width.value())
+ {
+ continue;
+ }
+ }
+
+ // Get the row ID from the position as that's what we need to remap
+ const auto oldRowId = oldCoord.Y;
+
+ // Use the mapping given to convert the old row ID to the new row ID
+ const auto mapIter = rowMap.find(oldRowId);
+
+ // If there's no mapping to a new row, don't bother copying it to the new map. The row is gone.
+ if (mapIter == rowMap.end())
+ {
+ continue;
+ }
+
+ const auto newRowId = mapIter->second;
+
+ // Generate a new coordinate with the same X as the old one, but a new Y value.
+ const auto newCoord = COORD{ oldCoord.X, newRowId };
+
+ // Put the adjusted coordinate into the map with the original value.
+ newMap.emplace(newCoord, pair.second);
+ }
+
+ // Swap into the stored map, free the temporary when we exit.
+ _map.swap(newMap);
+}
diff --git a/src/buffer/out/UnicodeStorage.hpp b/src/buffer/out/UnicodeStorage.hpp
new file mode 100644
index 00000000000..0df3e7eb3a7
--- /dev/null
+++ b/src/buffer/out/UnicodeStorage.hpp
@@ -0,0 +1,68 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- UnicodeStorage.hpp
+
+Abstract:
+- dynamic storage location for glyphs that can't normally fit in the output buffer
+
+Author(s):
+- Austin Diviness (AustDi) 02-May-2018
+--*/
+
+#pragma once
+
+#include
+#include
+#include
+
+// std::unordered_map needs help to know how to hash a COORD
+namespace std
+{
+ template <>
+ struct hash
+ {
+
+ // Routine Description:
+ // - hashes a coord. coord will be hashed by storing the x and y values consecutively in the lower
+ // bits of a size_t.
+ // Arguments:
+ // - coord - the coord to hash
+ // Return Value:
+ // - the hashed coord
+ constexpr size_t operator()(const COORD& coord) const noexcept
+ {
+ size_t retVal = coord.Y;
+ const size_t xCoord = coord.X;
+ retVal |= xCoord << (sizeof(coord.Y) * CHAR_BIT);
+ return retVal;
+ }
+ };
+}
+
+class UnicodeStorage final
+{
+public:
+ using key_type = typename COORD;
+ using mapped_type = typename std::vector;
+
+ UnicodeStorage();
+
+ const mapped_type& GetText(const key_type key) const;
+
+ void StoreGlyph(const key_type key, const mapped_type& glyph);
+
+ void Erase(const key_type key) noexcept;
+
+ void Remap(const std::map& rowMap, const std::optional width);
+
+private:
+ std::unordered_map _map;
+
+#ifdef UNIT_TESTING
+ friend class UnicodeStorageTests;
+ friend class TextBufferTests;
+#endif
+};
diff --git a/src/buffer/out/cursor.cpp b/src/buffer/out/cursor.cpp
new file mode 100644
index 00000000000..e95e7eef267
--- /dev/null
+++ b/src/buffer/out/cursor.cpp
@@ -0,0 +1,351 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "cursor.h"
+#include "TextBuffer.hpp"
+
+#pragma hdrstop
+
+// Routine Description:
+// - Constructor to set default properties for Cursor
+// Arguments:
+// - ulSize - The height of the cursor within this buffer
+Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) :
+ _parentBuffer{ parentBuffer },
+ _cPosition{ 0 },
+ _fHasMoved(false),
+ _fIsVisible(true),
+ _fIsOn(true),
+ _fIsDouble(false),
+ _fBlinkingAllowed(true),
+ _fDelay(false),
+ _fIsConversionArea(false),
+ _fIsPopupShown(false),
+ _fDelayedEolWrap(false),
+ _coordDelayedAt{ 0 },
+ _fDeferCursorRedraw(false),
+ _fHaveDeferredCursorRedraw(false),
+ _ulSize(ulSize),
+ _cursorType(CursorType::Legacy),
+ _fUseColor(false),
+ _color(s_InvertCursorColor)
+{
+}
+
+Cursor::~Cursor()
+{
+}
+
+COORD Cursor::GetPosition() const noexcept
+{
+ return _cPosition;
+}
+
+bool Cursor::HasMoved() const noexcept
+{
+ return _fHasMoved;
+}
+
+bool Cursor::IsVisible() const noexcept
+{
+ return _fIsVisible;
+}
+
+bool Cursor::IsOn() const noexcept
+{
+ return _fIsOn;
+}
+
+bool Cursor::IsBlinkingAllowed() const noexcept
+{
+ return _fBlinkingAllowed;
+}
+
+bool Cursor::IsDouble() const noexcept
+{
+ return _fIsDouble;
+}
+
+bool Cursor::IsConversionArea() const noexcept
+{
+ return _fIsConversionArea;
+}
+
+bool Cursor::IsPopupShown() const noexcept
+{
+ return _fIsPopupShown;
+}
+
+bool Cursor::GetDelay() const noexcept
+{
+ return _fDelay;
+}
+
+ULONG Cursor::GetSize() const noexcept
+{
+ return _ulSize;
+}
+
+void Cursor::SetHasMoved(const bool fHasMoved)
+{
+ _fHasMoved = fHasMoved;
+}
+
+void Cursor::SetIsVisible(const bool fIsVisible)
+{
+ _fIsVisible = fIsVisible;
+ _RedrawCursor();
+}
+
+void Cursor::SetIsOn(const bool fIsOn)
+{
+ _fIsOn = fIsOn;
+ _RedrawCursorAlways();
+}
+
+void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed)
+{
+ _fBlinkingAllowed = fBlinkingAllowed;
+ _RedrawCursorAlways();
+}
+
+void Cursor::SetIsDouble(const bool fIsDouble)
+{
+ _fIsDouble = fIsDouble;
+ _RedrawCursor();
+}
+
+void Cursor::SetIsConversionArea(const bool fIsConversionArea)
+{
+ // Functionally the same as "Hide cursor"
+ // Never called with TRUE, it's only used in the creation of a
+ // ConversionAreaInfo, and never changed after that.
+ _fIsConversionArea = fIsConversionArea;
+ _RedrawCursorAlways();
+}
+
+void Cursor::SetIsPopupShown(const bool fIsPopupShown)
+{
+ // Functionally the same as "Hide cursor"
+ _fIsPopupShown = fIsPopupShown;
+ _RedrawCursorAlways();
+}
+
+void Cursor::SetDelay(const bool fDelay)
+{
+ _fDelay = fDelay;
+}
+
+void Cursor::SetSize(const ULONG ulSize)
+{
+ _ulSize = ulSize;
+ _RedrawCursor();
+}
+
+void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
+{
+ _ulSize = ulSize;
+ _color = color;
+ _cursorType = type;
+
+ _RedrawCursor();
+}
+
+// Routine Description:
+// - Sends a redraw message to the renderer only if the cursor is currently on.
+// - NOTE: For use with most methods in this class.
+// Arguments:
+// -
+// Return Value:
+// -
+void Cursor::_RedrawCursor() noexcept
+{
+ // Only trigger the redraw if we're on.
+ // Don't draw the cursor if this was triggered from a conversion area.
+ // (Conversion areas have cursors to mark the insertion point internally, but the user's actual cursor is the one on the primary screen buffer.)
+ if (IsOn() && !IsConversionArea())
+ {
+ if (_fDeferCursorRedraw)
+ {
+ _fHaveDeferredCursorRedraw = true;
+ }
+ else
+ {
+ _RedrawCursorAlways();
+ }
+ }
+}
+
+// Routine Description:
+// - Sends a redraw message to the renderer no matter what.
+// - NOTE: For use with the method that turns the cursor on and off to force a refresh
+// and clear the ON cursor from the screen. Not for use with other methods.
+// They should use the other method so refreshes are suppressed while the cursor is off.
+// Arguments:
+// -
+// Return Value:
+// -
+void Cursor::_RedrawCursorAlways() noexcept
+{
+ try
+ {
+ _parentBuffer.GetRenderTarget().TriggerRedrawCursor(&_cPosition);
+ }
+ CATCH_LOG();
+}
+
+void Cursor::SetPosition(const COORD cPosition)
+{
+ _RedrawCursor();
+ _cPosition.X = cPosition.X;
+ _cPosition.Y = cPosition.Y;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::SetXPosition(const int NewX)
+{
+ _RedrawCursor();
+ _cPosition.X = (SHORT)NewX;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::SetYPosition(const int NewY)
+{
+ _RedrawCursor();
+ _cPosition.Y = (SHORT)NewY;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::IncrementXPosition(const int DeltaX)
+{
+ _RedrawCursor();
+ _cPosition.X += (SHORT)DeltaX;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::IncrementYPosition(const int DeltaY)
+{
+ _RedrawCursor();
+ _cPosition.Y += (SHORT)DeltaY;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::DecrementXPosition(const int DeltaX)
+{
+ _RedrawCursor();
+ _cPosition.X -= (SHORT)DeltaX;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+void Cursor::DecrementYPosition(const int DeltaY)
+{
+ _RedrawCursor();
+ _cPosition.Y -= (SHORT)DeltaY;
+ _RedrawCursor();
+ ResetDelayEOLWrap();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Routine Description:
+// - Copies properties from another cursor into this one.
+// - This is primarily to copy properties that would otherwise not be specified during CreateInstance
+// - NOTE: As of now, this function is specifically used to handle the ResizeWithReflow operation.
+// It will need modification for other future users.
+// Arguments:
+// - OtherCursor - The cursor to copy properties from
+// Return Value:
+// -
+void Cursor::CopyProperties(const Cursor& OtherCursor)
+{
+ // We shouldn't copy the position as it will be already rearranged by the resize operation.
+ //_cPosition = pOtherCursor->_cPosition;
+
+ _fHasMoved = OtherCursor._fHasMoved;
+ _fIsVisible = OtherCursor._fIsVisible;
+ _fIsOn = OtherCursor._fIsOn;
+ _fIsDouble = OtherCursor._fIsDouble;
+ _fBlinkingAllowed = OtherCursor._fBlinkingAllowed;
+ _fDelay = OtherCursor._fDelay;
+ _fIsConversionArea = OtherCursor._fIsConversionArea;
+
+ // A resize operation should invalidate the delayed end of line status, so do not copy.
+ //_fDelayedEolWrap = OtherCursor._fDelayedEolWrap;
+ //_coordDelayedAt = OtherCursor._coordDelayedAt;
+
+ _fDeferCursorRedraw = OtherCursor._fDeferCursorRedraw;
+ _fHaveDeferredCursorRedraw = OtherCursor._fHaveDeferredCursorRedraw;
+
+ // Size will be handled seperately in the resize operation.
+ //_ulSize = OtherCursor._ulSize;
+ _cursorType = OtherCursor._cursorType;
+ _color = OtherCursor._color;
+}
+
+void Cursor::DelayEOLWrap(const COORD coordDelayedAt)
+{
+ _coordDelayedAt = coordDelayedAt;
+ _fDelayedEolWrap = true;
+}
+
+void Cursor::ResetDelayEOLWrap()
+{
+ _coordDelayedAt = {0};
+ _fDelayedEolWrap = false;
+}
+
+COORD Cursor::GetDelayedAtPosition() const
+{
+ return _coordDelayedAt;
+}
+
+bool Cursor::IsDelayedEOLWrap() const
+{
+ return _fDelayedEolWrap;
+}
+
+void Cursor::StartDeferDrawing()
+{
+ _fDeferCursorRedraw = true;
+}
+
+void Cursor::EndDeferDrawing()
+{
+ if (_fHaveDeferredCursorRedraw)
+ {
+ _RedrawCursorAlways();
+ }
+
+ _fDeferCursorRedraw = FALSE;
+}
+
+const CursorType Cursor::GetType() const
+{
+ return _cursorType;
+}
+
+const bool Cursor::IsUsingColor() const
+{
+ return GetColor() != INVALID_COLOR;
+}
+
+const COLORREF Cursor::GetColor() const
+{
+ return _color;
+}
+
+void Cursor::SetColor(const unsigned int color)
+{
+ _color = (COLORREF)color;
+}
+
+void Cursor::SetType(const CursorType type)
+{
+ _cursorType = type;
+}
diff --git a/src/buffer/out/cursor.h b/src/buffer/out/cursor.h
new file mode 100644
index 00000000000..027d9f08db4
--- /dev/null
+++ b/src/buffer/out/cursor.h
@@ -0,0 +1,122 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- cursor.h
+
+Abstract:
+- This file implements the NT console server cursor routines.
+
+Author:
+- Therese Stowell (ThereseS) 5-Dec-1990
+
+Revision History:
+- Grouped into class and items made private. (MiNiksa, 2014)
+--*/
+
+#pragma once
+
+#include "../inc/conattrs.hpp"
+
+// the following values are used to create the textmode cursor.
+#define CURSOR_SMALL_SIZE 25 // large enough to be one pixel on a six pixel font
+class TextBuffer;
+
+class Cursor final
+{
+public:
+
+ static const unsigned int s_InvertCursorColor = INVALID_COLOR;
+
+ Cursor(const ULONG ulSize, TextBuffer& parentBuffer);
+
+ ~Cursor();
+
+ // No Copy. It will copy the timer handle. Bad news.
+ Cursor(const Cursor&) = delete;
+ Cursor& operator=(const Cursor&) & = delete;
+
+ Cursor(Cursor&&) = default;
+ Cursor& operator=(Cursor&&) & = default;
+
+ bool HasMoved() const noexcept;
+ bool IsVisible() const noexcept;
+ bool IsOn() const noexcept;
+ bool IsBlinkingAllowed() const noexcept;
+ bool IsDouble() const noexcept;
+ bool IsConversionArea() const noexcept;
+ bool IsPopupShown() const noexcept;
+ bool GetDelay() const noexcept;
+ ULONG GetSize() const noexcept;
+ COORD GetPosition() const noexcept;
+
+ const CursorType GetType() const;
+ const bool IsUsingColor() const;
+ const COLORREF GetColor() const;
+
+ void StartDeferDrawing();
+ void EndDeferDrawing();
+
+ void SetHasMoved(const bool fHasMoved);
+ void SetIsVisible(const bool fIsVisible);
+ void SetIsOn(const bool fIsOn);
+ void SetBlinkingAllowed(const bool fIsOn);
+ void SetIsDouble(const bool fIsDouble);
+ void SetIsConversionArea(const bool fIsConversionArea);
+ void SetIsPopupShown(const bool fIsPopupShown);
+ void SetDelay(const bool fDelay);
+ void SetSize(const ULONG ulSize);
+ void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
+
+ void SetPosition(const COORD cPosition);
+ void SetXPosition(const int NewX);
+ void SetYPosition(const int NewY);
+ void IncrementXPosition(const int DeltaX);
+ void IncrementYPosition(const int DeltaY);
+ void DecrementXPosition(const int DeltaX);
+ void DecrementYPosition(const int DeltaY);
+
+ void CopyProperties(const Cursor& OtherCursor);
+
+ void DelayEOLWrap(const COORD coordDelayedAt);
+ void ResetDelayEOLWrap();
+ COORD GetDelayedAtPosition() const;
+ bool IsDelayedEOLWrap() const;
+
+ void SetColor(const unsigned int color);
+ void SetType(const CursorType type);
+
+private:
+ TextBuffer& _parentBuffer;
+
+ //TODO: seperate the rendering and text placement
+
+ // NOTE: If you are adding a property here, go add it to CopyProperties.
+
+ COORD _cPosition; // current position on screen (in screen buffer coords).
+
+ bool _fHasMoved;
+ bool _fIsVisible; // whether cursor is visible (set only through the API)
+ bool _fIsOn; // whether blinking cursor is on or not
+ bool _fIsDouble; // whether the cursor size should be doubled
+ bool _fBlinkingAllowed; //Whether or not the cursor is allowed to blink at all. only set through VT (^[[?12h/l)
+ bool _fDelay; // don't blink scursor on next timer message
+ bool _fIsConversionArea; // is attached to a conversion area so it doesn't actually need to display the cursor.
+ bool _fIsPopupShown; // if a popup is being shown, turn off, stop blinking.
+
+ bool _fDelayedEolWrap; // don't wrap at EOL till the next char comes in.
+ COORD _coordDelayedAt; // coordinate the EOL wrap was delayed at.
+
+ bool _fDeferCursorRedraw; // whether we should defer redrawing the cursor or not
+ bool _fHaveDeferredCursorRedraw; // have we been asked to redraw the cursor while it was being deferred?
+
+ ULONG _ulSize;
+
+ void _RedrawCursor() noexcept;
+ void _RedrawCursorAlways() noexcept;
+
+ CursorType _cursorType;
+ bool _fUseColor;
+ COLORREF _color;
+};
diff --git a/src/buffer/out/dirs b/src/buffer/out/dirs
new file mode 100644
index 00000000000..d52eeb64fe6
--- /dev/null
+++ b/src/buffer/out/dirs
@@ -0,0 +1,4 @@
+DIRS=lib \
+ ut_textbuffer \
+
+
diff --git a/src/buffer/out/lib/bufferout.vcxproj b/src/buffer/out/lib/bufferout.vcxproj
new file mode 100644
index 00000000000..c38c4118c9f
--- /dev/null
+++ b/src/buffer/out/lib/bufferout.vcxproj
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
+ Win32Proj
+ bufferout
+ BufferOut
+ ConBufferOut
+
+
+
+ $(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\Win32K;$(SolutionDir)\dep\AppModel;$(SolutionDir)\dep\MinCore;%(AdditionalIncludeDirectories)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/buffer/out/lib/sources b/src/buffer/out/lib/sources
new file mode 100644
index 00000000000..52a8b0c277e
--- /dev/null
+++ b/src/buffer/out/lib/sources
@@ -0,0 +1,8 @@
+!include ..\sources.inc
+
+# -------------------------------------
+# Program Information
+# -------------------------------------
+
+TARGETNAME = ConBufferOut
+TARGETTYPE = LIBRARY
diff --git a/src/buffer/out/precomp.cpp b/src/buffer/out/precomp.cpp
new file mode 100644
index 00000000000..c51e9b31b2f
--- /dev/null
+++ b/src/buffer/out/precomp.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
diff --git a/src/buffer/out/precomp.h b/src/buffer/out/precomp.h
new file mode 100644
index 00000000000..4c6505cc1d3
--- /dev/null
+++ b/src/buffer/out/precomp.h
@@ -0,0 +1,36 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- precomp.h
+
+Abstract:
+- Contains external headers to include in the precompile phase of console build process.
+- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
+--*/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+// This includes support libraries from the CRT, STL, WIL, and GSL
+#include "LibraryIncludes.h"
+
+#pragma warning(push)
+#pragma warning(disable: ALL_CPPCORECHECK_WARNINGS)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+// Windows Header Files:
+#include
+#include
+
+// private dependencies
+#include "..\inc\operators.hpp"
+#include "..\inc\unicode.hpp"
+#pragma warning(pop)
diff --git a/src/buffer/out/sources.inc b/src/buffer/out/sources.inc
new file mode 100644
index 00000000000..660c473d139
--- /dev/null
+++ b/src/buffer/out/sources.inc
@@ -0,0 +1,54 @@
+!include ..\..\..\project.inc
+
+# -------------------------------------
+# Windows Console
+# - Console Output Buffer
+# -------------------------------------
+
+# This module encapsulates the objects used to manage
+# the output buffer of the console
+
+# -------------------------------------
+# Compiler Settings
+# -------------------------------------
+
+# Warning 4201: nonstandard extension used: nameless struct/union
+MSC_WARNING_LEVEL = $(MSC_WARNING_LEVEL) /wd4201
+
+# -------------------------------------
+# Build System Settings
+# -------------------------------------
+
+# Code in the OneCore depot automatically excludes default Win32 libraries.
+
+# -------------------------------------
+# Sources, Headers, and Libraries
+# -------------------------------------
+
+PRECOMPILED_CXX = 1
+PRECOMPILED_INCLUDE = ..\precomp.h
+
+SOURCES= \
+ ..\AttrRow.cpp \
+ ..\AttrRowIterator.cpp \
+ ..\cursor.cpp \
+ ..\OutputCell.cpp \
+ ..\OutputCellIterator.cpp \
+ ..\OutputCellRect.cpp \
+ ..\OutputCellView.cpp \
+ ..\Row.cpp \
+ ..\RowCellIterator.cpp \
+ ..\TextColor.cpp \
+ ..\TextAttribute.cpp \
+ ..\TextAttributeRun.cpp \
+ ..\textBuffer.cpp \
+ ..\textBufferCellIterator.cpp \
+ ..\textBufferTextIterator.cpp \
+ ..\CharRow.cpp \
+ ..\CharRowCell.cpp \
+ ..\CharRowCellReference.cpp \
+ ..\UnicodeStorage.cpp \
+
+INCLUDES= \
+ $(INCLUDES); \
+ ..; \
diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp
new file mode 100644
index 00000000000..3cb52eacfe8
--- /dev/null
+++ b/src/buffer/out/textBuffer.cpp
@@ -0,0 +1,1033 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "textBuffer.hpp"
+#include "CharRow.hpp"
+
+#include "../types/inc/convert.hpp"
+
+#pragma hdrstop
+
+using namespace Microsoft::Console::Types;
+
+// Routine Description:
+// - Creates a new instance of TextBuffer
+// Arguments:
+// - fontInfo - The font to use for this text buffer as specified in the global font cache
+// - screenBufferSize - The X by Y dimensions of the new screen buffer
+// - fill - Uses the .Attributes property to decide which default color to apply to all text in this buffer
+// - cursorSize - The height of the cursor within this buffer
+// Return Value:
+// - constructed object
+// Note: may throw exception
+TextBuffer::TextBuffer(const COORD screenBufferSize,
+ const TextAttribute defaultAttributes,
+ const UINT cursorSize,
+ Microsoft::Console::Render::IRenderTarget& renderTarget) :
+ _firstRow{ 0 },
+ _currentAttributes{ defaultAttributes },
+ _cursor{ cursorSize, *this },
+ _storage{},
+ _unicodeStorage{},
+ _renderTarget{ renderTarget }
+{
+ // initialize ROWs
+ for (size_t i = 0; i < static_cast(screenBufferSize.Y); ++i)
+ {
+ _storage.emplace_back(static_cast(i), screenBufferSize.X, _currentAttributes, this);
+ }
+}
+
+// Routine Description:
+// - Copies properties from another text buffer into this one.
+// - This is primarily to copy properties that would otherwise not be specified during CreateInstance
+// Arguments:
+// - OtherBuffer - The text buffer to copy properties from
+// Return Value:
+// -
+void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer)
+{
+ GetCursor().CopyProperties(OtherBuffer.GetCursor());
+}
+
+// Routine Description:
+// - Gets the number of rows in the buffer
+// Arguments:
+// -
+// Return Value:
+// - Total number of rows in the buffer
+UINT TextBuffer::TotalRowCount() const
+{
+ return static_cast(_storage.size());
+}
+
+// Routine Description:
+// - Retrieves a row from the buffer by its offset from the first row of the text buffer (what corresponds to
+// the top row of the screen buffer)
+// Arguments:
+// - Number of rows down from the first row of the buffer.
+// Return Value:
+// - const reference to the requested row. Asserts if out of bounds.
+const ROW& TextBuffer::GetRowByOffset(const size_t index) const
+{
+ const size_t totalRows = TotalRowCount();
+
+ // Rows are stored circularly, so the index you ask for is offset by the start position and mod the total of rows.
+ const size_t offsetIndex = (_firstRow + index) % totalRows;
+ return _storage[offsetIndex];
+}
+
+// Routine Description:
+// - Retrieves a row from the buffer by its offset from the first row of the text buffer (what corresponds to
+// the top row of the screen buffer)
+// Arguments:
+// - Number of rows down from the first row of the buffer.
+// Return Value:
+// - reference to the requested row. Asserts if out of bounds.
+ROW& TextBuffer::GetRowByOffset(const size_t index)
+{
+ return const_cast(static_cast(this)->GetRowByOffset(index));
+}
+
+// Routine Description:
+// - Retrieves read-only text iterator at the given buffer location
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// Return Value:
+// - Read-only iterator of text data only.
+TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at) const
+{
+ return TextBufferTextIterator(GetCellDataAt(at));
+}
+
+// Routine Description:
+// - Retrieves read-only cell iterator at the given buffer location
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// Return Value:
+// - Read-only iterator of cell data.
+TextBufferCellIterator TextBuffer::GetCellDataAt(const COORD at) const
+{
+ return TextBufferCellIterator(*this, at);
+}
+
+// Routine Description:
+// - Retrieves read-only text iterator at the given buffer location
+// but restricted to only the specific line (Y coordinate).
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// Return Value:
+// - Read-only iterator of text data only.
+TextBufferTextIterator TextBuffer::GetTextLineDataAt(const COORD at) const
+{
+ return TextBufferTextIterator(GetCellLineDataAt(at));
+}
+
+// Routine Description:
+// - Retrieves read-only cell iterator at the given buffer location
+// but restricted to only the specific line (Y coordinate).
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// Return Value:
+// - Read-only iterator of cell data.
+TextBufferCellIterator TextBuffer::GetCellLineDataAt(const COORD at) const
+{
+ SMALL_RECT limit;
+ limit.Top = at.Y;
+ limit.Bottom = at.Y;
+ limit.Left = 0;
+ limit.Right = GetSize().RightInclusive();
+
+ return TextBufferCellIterator(*this, at, Viewport::FromInclusive(limit));
+}
+
+// Routine Description:
+// - Retrieves read-only text iterator at the given buffer location
+// but restricted to operate only inside the given viewport.
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// - limit - boundaries for the iterator to operate within
+// Return Value:
+// - Read-only iterator of text data only.
+TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at, const Viewport limit) const
+{
+ return TextBufferTextIterator(GetCellDataAt(at, limit));
+}
+
+// Routine Description:
+// - Retrieves read-only cell iterator at the given buffer location
+// but restricted to operate only inside the given viewport.
+// Arguments:
+// - at - X,Y position in buffer for iterator start position
+// - limit - boundaries for the iterator to operate within
+// Return Value:
+// - Read-only iterator of cell data.
+TextBufferCellIterator TextBuffer::GetCellDataAt(const COORD at, const Viewport limit) const
+{
+ return TextBufferCellIterator(*this, at, limit);
+}
+
+//Routine Description:
+// - Corrects and enforces consistent double byte character state (KAttrs line) within a row of the text buffer.
+// - This will take the given double byte information and check that it will be consistent when inserted into the buffer
+// at the current cursor position.
+// - It will correct the buffer (by erasing the character prior to the cursor) if necessary to make a consistent state.
+//Arguments:
+// - dbcsAttribute - Double byte information associated with the character about to be inserted into the buffer
+//Return Value:
+// - True if it is valid to insert a character with the given double byte attributes. False otherwise.
+bool TextBuffer::_AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribute)
+{
+ // To figure out if the sequence is valid, we have to look at the character that comes before the current one
+ const COORD coordPrevPosition = _GetPreviousFromCursor();
+ ROW& prevRow = GetRowByOffset(coordPrevPosition.Y);
+ DbcsAttribute prevDbcsAttr;
+ try
+ {
+ prevDbcsAttr = prevRow.GetCharRow().DbcsAttrAt(coordPrevPosition.X);
+ }
+ catch (...)
+ {
+ LOG_HR(wil::ResultFromCaughtException());
+ return false;
+ }
+
+ bool fValidSequence = true; // Valid until proven otherwise
+ bool fCorrectableByErase = false; // Can't be corrected until proven otherwise
+
+ // Here's the matrix of valid items:
+ // N = None (single byte)
+ // L = Lead (leading byte of double byte sequence
+ // T = Trail (trailing byte of double byte sequence
+ // Prev Curr Result
+ // N N OK.
+ // N L OK.
+ // N T Fail, uncorrectable. Trailing byte must have had leading before it.
+ // L N Fail, OK with erase. Lead needs trailing pair. Can erase lead to correct.
+ // L L Fail, OK with erase. Lead needs trailing pair. Can erase prev lead to correct.
+ // L T OK.
+ // T N OK.
+ // T L OK.
+ // T T Fail, uncorrectable. New trailing byte must have had leading before it.
+
+ // Check for only failing portions of the matrix:
+ if (prevDbcsAttr.IsSingle() && dbcsAttribute.IsTrailing())
+ {
+ // N, T failing case (uncorrectable)
+ fValidSequence = false;
+ }
+ else if (prevDbcsAttr.IsLeading())
+ {
+ if (dbcsAttribute.IsSingle() || dbcsAttribute.IsLeading())
+ {
+ // L, N and L, L failing cases (correctable)
+ fValidSequence = false;
+ fCorrectableByErase = true;
+ }
+ }
+ else if (prevDbcsAttr.IsTrailing() && dbcsAttribute.IsTrailing())
+ {
+ // T, T failing case (uncorrectable)
+ fValidSequence = false;
+ }
+
+ // If it's correctable by erase, erase the previous character
+ if (fCorrectableByErase)
+ {
+ // Erase previous character into an N type.
+ try
+ {
+ prevRow.GetCharRow().ClearCell(coordPrevPosition.X);
+ }
+ catch (...)
+ {
+ LOG_HR(wil::ResultFromCaughtException());
+ return false;
+ }
+
+ // Sequence is now N N or N L, which are both okay. Set sequence back to valid.
+ fValidSequence = true;
+ }
+
+ return fValidSequence;
+}
+
+//Routine Description:
+// - Call before inserting a character into the buffer.
+// - This will ensure a consistent double byte state (KAttrs line) within the text buffer
+// - It will attempt to correct the buffer if we're inserting an unexpected double byte character type
+// and it will pad out the buffer if we're going to split a double byte sequence across two rows.
+//Arguments:
+// - dbcsAttribute - Double byte information associated with the character about to be inserted into the buffer
+//Return Value:
+// - true if we successfully prepared the buffer and moved the cursor
+// - false otherwise (out of memory)
+bool TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute)
+{
+ // Assert the buffer state is ready for this character
+ // This function corrects most errors. If this is false, we had an uncorrectable one.
+ FAIL_FAST_IF(!(_AssertValidDoubleByteSequence(dbcsAttribute))); // Shouldn't be uncorrectable sequences unless something is very wrong.
+
+ bool fSuccess = true;
+ // Now compensate if we don't have enough space for the upcoming double byte sequence
+ // We only need to compensate for leading bytes
+ if (dbcsAttribute.IsLeading())
+ {
+ short const sBufferWidth = GetSize().Width();
+
+ // If we're about to lead on the last column in the row, we need to add a padding space
+ if (GetCursor().GetPosition().X == sBufferWidth - 1)
+ {
+ // set that we're wrapping for double byte reasons
+ CharRow& charRow = GetRowByOffset(GetCursor().GetPosition().Y).GetCharRow();
+ charRow.SetDoubleBytePadded(true);
+
+ // then move the cursor forward and onto the next row
+ fSuccess = IncrementCursor();
+ }
+ }
+ return fSuccess;
+}
+
+// Routine Description:
+// - Writes cells to the output buffer. Writes at the cursor.
+// Arguments:
+// - givenIt - Iterator representing output cell data to write
+// Return Value:
+// - The final position of the iterator
+OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt)
+{
+ const auto& cursor = GetCursor();
+ const auto target = cursor.GetPosition();
+
+ const auto finalIt = Write(givenIt, target);
+
+ return finalIt;
+}
+
+// Routine Description:
+// - Writes cells to the output buffer.
+// Arguments:
+// - givenIt - Iterator representing output cell data to write
+// - target - the row/column to start writing the text to
+// Return Value:
+// - The final position of the iterator
+OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
+ const COORD target)
+{
+ // Make mutable copy so we can walk.
+ auto it = givenIt;
+
+ // Make mutable target so we can walk down lines.
+ auto lineTarget = target;
+
+ // Get size of the text buffer so we can stay in bounds.
+ const auto size = GetSize();
+
+ // While there's still data in the iterator and we're still targeting in bounds...
+ while (it && size.IsInBounds(lineTarget))
+ {
+ // Attempt to write as much data as possible onto this line.
+ it = WriteLine(it, lineTarget, true);
+
+ // Move to the next line down.
+ lineTarget.X = 0;
+ ++lineTarget.Y;
+ }
+
+ return it;
+}
+
+// Routine Description:
+// - Writes one line of text to the output buffer.
+// Arguments:
+// - givenIt - The iterator that will dereference into cell data to insert
+// - target - Coordinate targeted within output buffer
+// - setWrap - Whether we should try to set the wrap flag if we write up to the end of the line and have more data
+// - limitRight - Optionally restrict the right boundary for writing (e.g. stop writing earlier than the end of line)
+// Return Value:
+// - The iterator, but advanced to where we stopped writing. Use to find input consumed length or cells written length.
+OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
+ const COORD target,
+ const bool setWrap,
+ std::optional limitRight)
+{
+ // If we're not in bounds, exit early.
+ if (!GetSize().IsInBounds(target))
+ {
+ return givenIt;
+ }
+
+ // Get the row and write the cells
+ ROW& row = GetRowByOffset(target.Y);
+ const auto newIt = row.WriteCells(givenIt, target.X, setWrap, limitRight);
+
+ // Take the cell distance written and notify that it needs to be repainted.
+ const auto written = newIt.GetCellDistance(givenIt);
+ const Viewport paint = Viewport::FromDimensions(target, { gsl::narrow(written), 1 });
+ _NotifyPaint(paint);
+
+ return newIt;
+}
+
+//Routine Description:
+// - Inserts one codepoint into the buffer at the current cursor position and advances the cursor as appropriate.
+//Arguments:
+// - chars - The codepoint to insert
+// - dbcsAttribute - Double byte information associated with the codepoint
+// - bAttr - Color data associated with the character
+//Return Value:
+// - true if we successfully inserted the character
+// - false otherwise (out of memory)
+bool TextBuffer::InsertCharacter(const std::wstring_view chars,
+ const DbcsAttribute dbcsAttribute,
+ const TextAttribute attr)
+{
+ // Ensure consistent buffer state for double byte characters based on the character type we're about to insert
+ bool fSuccess = _PrepareForDoubleByteSequence(dbcsAttribute);
+
+ if (fSuccess)
+ {
+ // Get the current cursor position
+ short const iRow = GetCursor().GetPosition().Y; // row stored as logical position, not array position
+ short const iCol = GetCursor().GetPosition().X; // column logical and array positions are equal.
+
+ // Get the row associated with the given logical position
+ ROW& Row = GetRowByOffset(iRow);
+
+ // Store character and double byte data
+ CharRow& charRow = Row.GetCharRow();
+ short const cBufferWidth = GetSize().Width();
+
+ try
+ {
+ charRow.GlyphAt(iCol) = chars;
+ charRow.DbcsAttrAt(iCol) = dbcsAttribute;
+ }
+ catch (...)
+ {
+ LOG_HR(wil::ResultFromCaughtException());
+ return false;
+ }
+
+ // Store color data
+ fSuccess = Row.GetAttrRow().SetAttrToEnd(iCol, attr);
+ if (fSuccess)
+ {
+ // Advance the cursor
+ fSuccess = IncrementCursor();
+ }
+ }
+ return fSuccess;
+}
+
+//Routine Description:
+// - Inserts one ucs2 codepoint into the buffer at the current cursor position and advances the cursor as appropriate.
+//Arguments:
+// - wch - The codepoint to insert
+// - dbcsAttribute - Double byte information associated with the codepoint
+// - bAttr - Color data associated with the character
+//Return Value:
+// - true if we successfully inserted the character
+// - false otherwise (out of memory)
+bool TextBuffer::InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr)
+{
+ return InsertCharacter({ &wch, 1 }, dbcsAttribute, attr);
+}
+
+//Routine Description:
+// - Finds the current row in the buffer (as indicated by the cursor position)
+// and specifies that we have forced a line wrap on that row
+//Arguments:
+// - - Always sets to wrap
+//Return Value:
+// -
+void TextBuffer::_SetWrapOnCurrentRow()
+{
+ _AdjustWrapOnCurrentRow(true);
+}
+
+//Routine Description:
+// - Finds the current row in the buffer (as indicated by the cursor position)
+// and specifies whether or not it should have a line wrap flag.
+//Arguments:
+// - fSet - True if this row has a wrap. False otherwise.
+//Return Value:
+// -
+void TextBuffer::_AdjustWrapOnCurrentRow(const bool fSet)
+{
+ // The vertical position of the cursor represents the current row we're manipulating.
+ const UINT uiCurrentRowOffset = GetCursor().GetPosition().Y;
+
+ // Set the wrap status as appropriate
+ GetRowByOffset(uiCurrentRowOffset).GetCharRow().SetWrapForced(fSet);
+}
+
+//Routine Description:
+// - Increments the cursor one position in the buffer as if text is being typed into the buffer.
+// - NOTE: Will introduce a wrap marker if we run off the end of the current row
+//Arguments:
+// -
+//Return Value:
+// - true if we successfully moved the cursor.
+// - false otherwise (out of memory)
+bool TextBuffer::IncrementCursor()
+{
+ // Cursor position is stored as logical array indices (starts at 0) for the window
+ // Buffer Size is specified as the "length" of the array. It would say 80 for valid values of 0-79.
+ // So subtract 1 from buffer size in each direction to find the index of the final column in the buffer
+ const short iFinalColumnIndex = GetSize().RightInclusive();
+
+ // Move the cursor one position to the right
+ GetCursor().IncrementXPosition(1);
+
+ bool fSuccess = true;
+ // If we've passed the final valid column...
+ if (GetCursor().GetPosition().X > iFinalColumnIndex)
+ {
+ // Then mark that we've been forced to wrap
+ _SetWrapOnCurrentRow();
+
+ // Then move the cursor to a new line
+ fSuccess = NewlineCursor();
+ }
+ return fSuccess;
+}
+
+//Routine Description:
+// - Increments the cursor one line down in the buffer and to the beginning of the line
+//Arguments:
+// -
+//Return Value:
+// - true if we successfully moved the cursor.
+bool TextBuffer::NewlineCursor()
+{
+ bool fSuccess = false;
+ short const iFinalRowIndex = GetSize().BottomInclusive();
+
+ // Reset the cursor position to 0 and move down one line
+ GetCursor().SetXPosition(0);
+ GetCursor().IncrementYPosition(1);
+
+ // If we've passed the final valid row...
+ if (GetCursor().GetPosition().Y > iFinalRowIndex)
+ {
+ // Stay on the final logical/offset row of the buffer.
+ GetCursor().SetYPosition(iFinalRowIndex);
+
+ // Instead increment the circular buffer to move us into the "oldest" row of the backing buffer
+ fSuccess = IncrementCircularBuffer();
+ }
+ else
+ {
+ fSuccess = true;
+ }
+ return fSuccess;
+}
+
+//Routine Description:
+// - Increments the circular buffer by one. Circular buffer is represented by FirstRow variable.
+//Arguments:
+// -
+//Return Value:
+// - true if we successfully incremented the buffer.
+bool TextBuffer::IncrementCircularBuffer()
+{
+ // FirstRow is at any given point in time the array index in the circular buffer that corresponds
+ // to the logical position 0 in the window (cursor coordinates and all other coordinates).
+ _renderTarget.TriggerCircling();
+
+ // First, clean out the old "first row" as it will become the "last row" of the buffer after the circle is performed.
+ bool fSuccess = _storage.at(_firstRow).Reset(_currentAttributes);
+ if (fSuccess)
+ {
+ // Now proceed to increment.
+ // Incrementing it will cause the next line down to become the new "top" of the window (the new "0" in logical coordinates)
+ _firstRow++;
+
+ // If we pass up the height of the buffer, loop back to 0.
+ if (_firstRow >= GetSize().Height())
+ {
+ _firstRow = 0;
+ }
+ }
+ return fSuccess;
+}
+
+//Routine Description:
+// - Retrieves the position of the last non-space character on the final line of the text buffer.
+//Arguments:
+// -
+//Return Value:
+// - Coordinate position in screen coordinates (offset coordinates, not array index coordinates).
+COORD TextBuffer::GetLastNonSpaceCharacter() const
+{
+ COORD coordEndOfText;
+ // Always search the whole buffer, by starting at the bottom.
+ coordEndOfText.Y = GetSize().BottomInclusive();
+
+ const ROW* pCurrRow = &GetRowByOffset(coordEndOfText.Y);
+ // The X position of the end of the valid text is the Right draw boundary (which is one beyond the final valid character)
+ coordEndOfText.X = static_cast(pCurrRow->GetCharRow().MeasureRight()) - 1;
+
+ // If the X coordinate turns out to be -1, the row was empty, we need to search backwards for the real end of text.
+ bool fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > 0); // this row is empty, and we're not at the top
+ while (fDoBackUp)
+ {
+ coordEndOfText.Y--;
+ pCurrRow = &GetRowByOffset(coordEndOfText.Y);
+ // We need to back up to the previous row if this line is empty, AND there are more rows
+
+ coordEndOfText.X = static_cast(pCurrRow->GetCharRow().MeasureRight()) - 1;
+ fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > 0);
+ }
+
+ // don't allow negative results
+ coordEndOfText.Y = std::max(coordEndOfText.Y, 0i16);
+ coordEndOfText.X = std::max(coordEndOfText.X, 0i16);
+
+ return coordEndOfText;
+}
+
+// Routine Description:
+// - Retrieves the position of the previous character relative to the current cursor position
+// Arguments:
+// -
+// Return Value:
+// - Coordinate position in screen coordinates of the character just before the cursor.
+// - NOTE: Will return 0,0 if already in the top left corner
+COORD TextBuffer::_GetPreviousFromCursor() const
+{
+ COORD coordPosition = GetCursor().GetPosition();
+
+ // If we're not at the left edge, simply move the cursor to the left by one
+ if (coordPosition.X > 0)
+ {
+ coordPosition.X--;
+ }
+ else
+ {
+ // Otherwise, only if we're not on the top row (e.g. we don't move anywhere in the top left corner. there is no previous)
+ if (coordPosition.Y > 0)
+ {
+ // move the cursor to the right edge
+ coordPosition.X = GetSize().RightInclusive();
+
+ // and up one line
+ coordPosition.Y--;
+ }
+ }
+
+ return coordPosition;
+}
+
+const SHORT TextBuffer::GetFirstRowIndex() const
+{
+ return _firstRow;
+}
+const Viewport TextBuffer::GetSize() const
+{
+ return Viewport::FromDimensions({ 0, 0 }, { gsl::narrow(_storage.at(0).size()), gsl::narrow(_storage.size()) });
+}
+
+void TextBuffer::_SetFirstRowIndex(const SHORT FirstRowIndex)
+{
+ _firstRow = FirstRowIndex;
+}
+
+void TextBuffer::ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta)
+{
+ // If we don't have to move anything, leave early.
+ if (delta == 0)
+ {
+ return;
+ }
+
+ // OK. We're about to play games by moving rows around within the deque to
+ // scroll a massive region in a faster way than copying things.
+ // To make this easier, first correct the circular buffer to have the first row be 0 again.
+ if (_firstRow != 0)
+ {
+ // Rotate the buffer to put the first row at the front.
+ std::rotate(_storage.begin(), _storage.begin() + _firstRow, _storage.end());
+
+ // The first row is now at the top.
+ _firstRow = 0;
+ }
+
+ // Rotate just the subsection specified
+ if (delta < 0)
+ {
+ // The layout is like this:
+ // delta is -2, size is 3, firstRow is 5
+ // We want 3 rows from 5 (5, 6, and 7) to move up 2 spots.
+ // --- (storage) ----
+ // | 0 begin
+ // | 1
+ // | 2
+ // | 3 A. begin + firstRow + delta (because delta is negative)
+ // | 4
+ // | 5 B. begin + firstRow
+ // | 6
+ // | 7
+ // | 8 C. begin + firstRow + size
+ // | 9
+ // | 10
+ // | 11
+ // - end
+ // We want B to slide up to A (the negative delta) and everything from [B,C) to slide up with it.
+ // So the final layout will be
+ // --- (storage) ----
+ // | 0 begin
+ // | 1
+ // | 2
+ // | 5
+ // | 6
+ // | 7
+ // | 3
+ // | 4
+ // | 8
+ // | 9
+ // | 10
+ // | 11
+ // - end
+ std::rotate(_storage.begin() + firstRow + delta, _storage.begin() + firstRow, _storage.begin() + firstRow + size);
+ }
+ else
+ {
+ // The layout is like this:
+ // delta is 2, size is 3, firstRow is 5
+ // We want 3 rows from 5 (5, 6, and 7) to move down 2 spots.
+ // --- (storage) ----
+ // | 0 begin
+ // | 1
+ // | 2
+ // | 3
+ // | 4
+ // | 5 A. begin + firstRow
+ // | 6
+ // | 7
+ // | 8 B. begin + firstRow + size
+ // | 9
+ // | 10 C. begin + firstRow + size + delta
+ // | 11
+ // - end
+ // We want B-1 to slide down to C-1 (the positive delta) and everything from [A, B) to slide down with it.
+ // So the final layout will be
+ // --- (storage) ----
+ // | 0 begin
+ // | 1
+ // | 2
+ // | 3
+ // | 4
+ // | 8
+ // | 9
+ // | 5
+ // | 6
+ // | 7
+ // | 10
+ // | 11
+ // - end
+ std::rotate(_storage.begin() + firstRow, _storage.begin() + firstRow + size, _storage.begin() + firstRow + size + delta);
+ }
+
+ // Renumber the IDs now that we've rearranged where the rows sit within the buffer.
+ // Refreshing should also delegate to the UnicodeStorage to re-key all the stored unicode sequences (where applicable).
+ _RefreshRowIDs(std::nullopt);
+}
+
+Cursor& TextBuffer::GetCursor()
+{
+ return _cursor;
+}
+
+const Cursor& TextBuffer::GetCursor() const
+{
+ return _cursor;
+}
+
+[[nodiscard]]
+TextAttribute TextBuffer::GetCurrentAttributes() const noexcept
+{
+ return _currentAttributes;
+}
+
+void TextBuffer::SetCurrentAttributes(const TextAttribute currentAttributes) noexcept
+{
+ _currentAttributes = currentAttributes;
+}
+
+// Routine Description:
+// - Resets the text contents of this buffer with the default character
+// and the default current color attributes
+void TextBuffer::Reset()
+{
+ const auto attr = GetCurrentAttributes();
+
+ for (auto& row : _storage)
+ {
+ row.GetCharRow().Reset();
+ row.GetAttrRow().Reset(attr);
+ }
+}
+
+// Routine Description:
+// - This is the legacy screen resize with minimal changes
+// Arguments:
+// - newSize - new size of screen.
+// Return Value:
+// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
+[[nodiscard]]
+NTSTATUS TextBuffer::ResizeTraditional(const COORD newSize) noexcept
+{
+ RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
+
+ const auto currentSize = GetSize().Dimensions();
+ const auto attributes = GetCurrentAttributes();
+
+ SHORT TopRow = 0; // new top row of the screen buffer
+ if (newSize.Y <= GetCursor().GetPosition().Y)
+ {
+ TopRow = GetCursor().GetPosition().Y - newSize.Y + 1;
+ }
+ const SHORT TopRowIndex = (GetFirstRowIndex() + TopRow) % currentSize.Y;
+
+ // rotate rows until the top row is at index 0
+ try
+ {
+ const ROW& newTopRow = _storage[TopRowIndex];
+ while (&newTopRow != &_storage.front())
+ {
+ _storage.push_back(std::move(_storage.front()));
+ _storage.pop_front();
+ }
+
+ _SetFirstRowIndex(0);
+
+ // realloc in the Y direction
+ // remove rows if we're shrinking
+ while (_storage.size() > static_cast(newSize.Y))
+ {
+ _storage.pop_back();
+ }
+ // add rows if we're growing
+ while (_storage.size() < static_cast(newSize.Y))
+ {
+ _storage.emplace_back(static_cast(_storage.size()), newSize.X, attributes, this);
+ }
+
+ // Now that we've tampered with the row placement, refresh all the row IDs.
+ // Also take advantage of the row ID refresh loop to resize the rows in the X dimension
+ // and cleanup the UnicodeStorage characters that might fall outside the resized buffer.
+ _RefreshRowIDs(newSize.X);
+
+ }
+ CATCH_RETURN();
+
+ return S_OK;
+}
+
+const UnicodeStorage& TextBuffer::GetUnicodeStorage() const
+{
+ return _unicodeStorage;
+}
+
+UnicodeStorage& TextBuffer::GetUnicodeStorage()
+{
+ return _unicodeStorage;
+}
+
+// Routine Description:
+// - Method to help refresh all the Row IDs after manipulating the row
+// by shuffling pointers around.
+// - This will also update parent pointers that are stored in depth within the buffer
+// (e.g. it will update CharRow parents pointing at Rows that might have been moved around)
+// - Optionally takes a new row width if we're resizing to perform a resize operation and cleanup
+// any high unicode (UnicodeStorage) runs while we're already looping through the rows.
+// Arguments:
+// - newRowWidth - Optional new value for the row width.
+void TextBuffer::_RefreshRowIDs(std::optional newRowWidth)
+{
+ std::map rowMap;
+ SHORT i = 0;
+ for (auto& it : _storage)
+ {
+ // Build a map so we can update Unicode Storage
+ rowMap.emplace(it.GetId(), i);
+
+ // Update the IDs
+ it.SetId(i++);
+
+ // Also update the char row parent pointers as they can get shuffled up in the rotates.
+ it.GetCharRow().UpdateParent(&it);
+
+ // Resize the rows in the X dimension if we have a new width
+ if (newRowWidth.has_value())
+ {
+ // Realloc in the X direction
+ THROW_IF_FAILED(it.Resize(newRowWidth.value()));
+ }
+ }
+
+ // Give the new mapping to Unicode Storage
+ _unicodeStorage.Remap(rowMap, newRowWidth);
+}
+
+void TextBuffer::_NotifyPaint(const Viewport& viewport) const
+{
+ _renderTarget.TriggerRedraw(viewport);
+}
+
+// Routine Description:
+// - Retrieves the first row from the underlying buffer.
+// Arguments:
+// -
+// Return Value:
+// - reference to the first row.
+ROW& TextBuffer::_GetFirstRow()
+{
+ return GetRowByOffset(0);
+}
+
+// Routine Description:
+// - Retrieves the row that comes before the given row.
+// - Does not wrap around the screen buffer.
+// Arguments:
+// - The current row.
+// Return Value:
+// - reference to the previous row
+// Note:
+// - will throw exception if called with the first row of the text buffer
+ROW& TextBuffer::_GetPrevRowNoWrap(const ROW& Row)
+{
+ int prevRowIndex = Row.GetId() - 1;
+ if (prevRowIndex < 0)
+ {
+ prevRowIndex = TotalRowCount() - 1;
+ }
+
+ THROW_HR_IF(E_FAIL, Row.GetId() == _firstRow);
+ return _storage[prevRowIndex];
+}
+
+// Method Description:
+// - Retrieves this buffer's current render target.
+// Arguments:
+// -
+// Return Value:
+// - This buffer's current render target.
+Microsoft::Console::Render::IRenderTarget& TextBuffer::GetRenderTarget()
+{
+ return _renderTarget;
+}
+
+// Routine Description:
+// - Retrieves the text data from the selected region and presents it in a clipboard-ready format (given little post-processing).
+// Arguments:
+// - lineSelection - true if entire line is being selected. False otherwise (box selection)
+// - trimTrailingWhitespace - setting flag removes trailing whitespace at the end of each row in selection
+// - selectionRects - the selection regions from which the data will be extracted from the buffer
+// - GetForegroundColor - function used to map TextAttribute to RGB COLORREF for foreground color
+// - GetBackgroundColor - function used to map TextAttribute to RGB COLORREF for foreground color
+// Return Value:
+// - The text, background color, and foreground color data of the selected region of the text buffer.
+const TextBuffer::TextAndColor TextBuffer::GetTextForClipboard(const bool lineSelection,
+ const bool trimTrailingWhitespace,
+ const std::vector& selectionRects,
+ std::function GetForegroundColor,
+ std::function GetBackgroundColor) const
+{
+ TextAndColor data;
+
+ // preallocate our vectors to reduce reallocs
+ size_t const rows = selectionRects.size();
+ data.text.reserve(rows);
+ data.FgAttr.reserve(rows);
+ data.BkAttr.reserve(rows);
+
+ // for each row in the selection
+ for (UINT i = 0; i < rows; i++)
+ {
+ const UINT iRow = selectionRects.at(i).Top;
+
+ const Viewport highlight = Viewport::FromInclusive(selectionRects.at(i));
+
+ // retrieve the data from the screen buffer
+ auto it = GetCellDataAt(highlight.Origin(), highlight);
+
+ // allocate a string buffer
+ std::wstring selectionText;
+ std::vector selectionFgAttr;
+ std::vector selectionBkAttr;
+
+ // preallocate to avoid reallocs
+ selectionText.reserve(highlight.Width() + 2); // + 2 for \r\n if we munged it
+ selectionFgAttr.reserve(highlight.Width() + 2);
+ selectionBkAttr.reserve(highlight.Width() + 2);
+
+ // copy char data into the string buffer, skipping trailing bytes
+ while (it)
+ {
+ const auto& cell = *it;
+ auto cellData = cell.TextAttr();
+ COLORREF const CellFgAttr = GetForegroundColor(cellData);
+ COLORREF const CellBkAttr = GetBackgroundColor(cellData);
+
+ if (!cell.DbcsAttr().IsTrailing())
+ {
+ selectionText.append(cell.Chars());
+ for (const wchar_t wch : cell.Chars())
+ {
+ selectionFgAttr.push_back(CellFgAttr);
+ selectionBkAttr.push_back(CellBkAttr);
+ }
+ }
+ it++;
+ }
+
+ // trim trailing spaces if SHIFT key not held
+ if (trimTrailingWhitespace)
+ {
+ const ROW& Row = GetRowByOffset(iRow);
+
+ // FOR LINE SELECTION ONLY: if the row was wrapped, don't remove the spaces at the end.
+ if (!lineSelection || !Row.GetCharRow().WasWrapForced())
+ {
+ while (!selectionText.empty() && selectionText.back() == UNICODE_SPACE)
+ {
+ selectionText.pop_back();
+ selectionFgAttr.pop_back();
+ selectionBkAttr.pop_back();
+ }
+ }
+
+ // apply CR/LF to the end of the final string, unless we're the last line.
+ // a.k.a if we're earlier than the bottom, then apply CR/LF.
+ if (i < selectionRects.size() - 1)
+ {
+ // FOR LINE SELECTION ONLY: if the row was wrapped, do not apply CR/LF.
+ // a.k.a. if the row was NOT wrapped, then we can assume a CR/LF is proper
+ // always apply \r\n for box selection
+ if (!lineSelection || !GetRowByOffset(iRow).GetCharRow().WasWrapForced())
+ {
+ COLORREF const Blackness = RGB(0x00, 0x00, 0x00); // cant see CR/LF so just use black FG & BK
+
+ selectionText.push_back(UNICODE_CARRIAGERETURN);
+ selectionText.push_back(UNICODE_LINEFEED);
+ selectionFgAttr.push_back(Blackness);
+ selectionFgAttr.push_back(Blackness);
+ selectionBkAttr.push_back(Blackness);
+ selectionBkAttr.push_back(Blackness);
+ }
+ }
+ }
+
+ data.text.emplace_back(selectionText);
+ data.FgAttr.emplace_back(selectionFgAttr);
+ data.BkAttr.emplace_back(selectionBkAttr);
+ }
+
+ return data;
+}
diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp
new file mode 100644
index 00000000000..7d46022e4e7
--- /dev/null
+++ b/src/buffer/out/textBuffer.hpp
@@ -0,0 +1,185 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- textBuffer.hpp
+
+Abstract:
+- This module contains structures and functions for manipulating a text
+ based buffer within the console host window.
+
+Author(s):
+- Michael Niksa (miniksa) 10-Apr-2014
+- Paul Campbell (paulcam) 10-Apr-2014
+
+Revision History:
+- From components of output.h/.c
+ by Therese Stowell (ThereseS) 1990-1991
+
+Notes:
+ScreenBuffer data structure overview:
+
+each screen buffer has an array of ROW structures. each ROW structure
+contains the data for one row of text. the data stored for one row of
+text is a character array and an attribute array. the character array
+is allocated the full length of the row from the heap, regardless of the
+non-space length. we also maintain the non-space length. the character
+array is initialized to spaces. the attribute
+array is run length encoded (i.e 5 BLUE, 3 RED). if there is only one
+attribute for the whole row (the normal case), it is stored in the ATTR_ROW
+structure. otherwise the attr string is allocated from the heap.
+
+ROW - CHAR_ROW - CHAR string
+\ \ length of char string
+\
+ATTR_ROW - ATTR_PAIR string
+\ length of attr pair string
+ROW
+ROW
+ROW
+
+ScreenInfo->Rows points to the ROW array. ScreenInfo->Rows[0] is not
+necessarily the top row. ScreenInfo->BufferInfo.TextInfo->FirstRow contains the index of
+the top row. That means scrolling (if scrolling entire screen)
+merely involves changing the FirstRow index,
+filling in the last row, and updating the screen.
+
+--*/
+
+#pragma once
+
+#include "cursor.h"
+#include "Row.hpp"
+#include "TextAttribute.hpp"
+#include "UnicodeStorage.hpp"
+#include "../types/inc/Viewport.hpp"
+
+#include "../buffer/out/textBufferCellIterator.hpp"
+#include "../buffer/out/textBufferTextIterator.hpp"
+
+#include "../renderer/inc/IRenderTarget.hpp"
+
+class TextBuffer final
+{
+public:
+ TextBuffer(const COORD screenBufferSize,
+ const TextAttribute defaultAttributes,
+ const UINT cursorSize,
+ Microsoft::Console::Render::IRenderTarget& renderTarget);
+ TextBuffer(const TextBuffer& a) = delete;
+
+ ~TextBuffer() = default;
+
+ // Used for duplicating properties to another text buffer
+ void CopyProperties(const TextBuffer& OtherBuffer);
+
+ // row manipulation
+ const ROW& GetRowByOffset(const size_t index) const;
+ ROW& GetRowByOffset(const size_t index);
+
+ TextBufferCellIterator GetCellDataAt(const COORD at) const;
+ TextBufferCellIterator GetCellLineDataAt(const COORD at) const;
+ TextBufferCellIterator GetCellDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const;
+ TextBufferTextIterator GetTextDataAt(const COORD at) const;
+ TextBufferTextIterator GetTextLineDataAt(const COORD at) const;
+ TextBufferTextIterator GetTextDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const;
+
+ // Text insertion functions
+ OutputCellIterator Write(const OutputCellIterator givenIt);
+
+ OutputCellIterator Write(const OutputCellIterator givenIt,
+ const COORD target);
+
+ OutputCellIterator WriteLine(const OutputCellIterator givenIt,
+ const COORD target,
+ const bool setWrap = false,
+ const std::optional limitRight = std::nullopt);
+
+ bool InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr);
+ bool InsertCharacter(const std::wstring_view chars, const DbcsAttribute dbcsAttribute, const TextAttribute attr);
+ bool IncrementCursor();
+ bool NewlineCursor();
+
+ // Scroll needs access to this to quickly rotate around the buffer.
+ bool IncrementCircularBuffer();
+
+ COORD GetLastNonSpaceCharacter() const;
+
+ Cursor& GetCursor();
+ const Cursor& GetCursor() const;
+
+ const SHORT GetFirstRowIndex() const;
+
+ const Microsoft::Console::Types::Viewport GetSize() const;
+
+ void ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta);
+
+ UINT TotalRowCount() const;
+
+ [[nodiscard]]
+ TextAttribute GetCurrentAttributes() const noexcept;
+
+ void SetCurrentAttributes(const TextAttribute currentAttributes) noexcept;
+
+ void Reset();
+
+ [[nodiscard]]
+ HRESULT ResizeTraditional(const COORD newSize) noexcept;
+
+ const UnicodeStorage& GetUnicodeStorage() const;
+ UnicodeStorage& GetUnicodeStorage();
+
+ Microsoft::Console::Render::IRenderTarget& GetRenderTarget();
+
+ class TextAndColor
+ {
+ public:
+ std::vector text;
+ std::vector> FgAttr;
+ std::vector> BkAttr;
+ };
+
+ const TextAndColor GetTextForClipboard(const bool lineSelection,
+ const bool trimTrailingWhitespace,
+ const std::vector& selectionRects,
+ std::function GetForegroundColor,
+ std::function GetBackgroundColor) const;
+
+private:
+
+ std::deque _storage;
+ Cursor _cursor;
+
+ SHORT _firstRow; // indexes top row (not necessarily 0)
+
+ TextAttribute _currentAttributes;
+
+ // storage location for glyphs that can't fit into the buffer normally
+ UnicodeStorage _unicodeStorage;
+
+ void _RefreshRowIDs(std::optional newRowWidth);
+
+ Microsoft::Console::Render::IRenderTarget& _renderTarget;
+
+ void _SetFirstRowIndex(const SHORT FirstRowIndex);
+
+ COORD _GetPreviousFromCursor() const;
+
+ void _SetWrapOnCurrentRow();
+ void _AdjustWrapOnCurrentRow(const bool fSet);
+
+ void _NotifyPaint(const Microsoft::Console::Types::Viewport& viewport) const;
+
+ // Assist with maintaining proper buffer state for Double Byte character sequences
+ bool _PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute);
+ bool _AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribute);
+
+ ROW& _GetFirstRow();
+ ROW& _GetPrevRowNoWrap(const ROW& row);
+
+#ifdef UNIT_TESTING
+ friend class TextBufferTests;
+ friend class UiaTextRangeTests;
+#endif
+};
diff --git a/src/buffer/out/textBufferCellIterator.cpp b/src/buffer/out/textBufferCellIterator.cpp
new file mode 100644
index 00000000000..765214a3196
--- /dev/null
+++ b/src/buffer/out/textBufferCellIterator.cpp
@@ -0,0 +1,267 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "textBufferCellIterator.hpp"
+
+#include "CharRow.hpp"
+#include "textBuffer.hpp"
+#include "../types/inc/convert.hpp"
+#include "../types/inc/viewport.hpp"
+
+#pragma hdrstop
+
+using namespace Microsoft::Console::Types;
+
+// Routine Description:
+// - Creates a new read-only iterator to seek through cell data stored within a screen buffer
+// Arguments:
+// - buffer - Text buffer to seek throught
+// - pos - Starting position to retrieve text data from (within screen buffer bounds)
+TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, COORD pos) :
+ TextBufferCellIterator(buffer, pos, buffer.GetSize())
+{
+}
+
+// Routine Description:
+// - Creates a new read-only iterator to seek through cell data stored within a screen buffer
+// Arguments:
+// - buffer - Pointer to screen buffer to seek through
+// - pos - Starting position to retrieve text data from (within screen buffer bounds)
+// - limits - Viewport limits to restrict the iterator within the buffer bounds (smaller than the buffer itself)
+TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, COORD pos, const Viewport limits) :
+ _buffer(buffer),
+ _pos(pos),
+ _pRow(s_GetRow(buffer, pos)),
+ _bounds(limits),
+ _exceeded(false),
+ _view({}, {}, {}, TextAttributeBehavior::Stored),
+ _attrIter(s_GetRow(buffer, pos)->GetAttrRow().cbegin())
+{
+ // Throw if the bounds rectangle is not limited to the inside of the given buffer.
+ THROW_HR_IF(E_INVALIDARG, !buffer.GetSize().IsInBounds(limits));
+
+ // Throw if the coordinate is not limited to the inside of the given buffer.
+ THROW_HR_IF(E_INVALIDARG, !limits.IsInBounds(pos));
+
+ _attrIter += pos.X;
+
+ _GenerateView();
+}
+
+// Routine Description:
+// - Tells if the iterator is still valid (hasn't exceeded boundaries of underlying text buffer)
+// Return Value:
+// - True if this iterator can still be dereferenced for data. False if we've passed the end and are out of data.
+TextBufferCellIterator::operator bool() const noexcept
+{
+ return !_exceeded && _bounds.IsInBounds(_pos);
+}
+
+// Routine Description:
+// - Compares two iterators to see if they're pointing to the same position in the same buffer
+// Arguments:
+// - it - The other iterator to compare to this one.
+// Return Value:
+// - True if it's the same text buffer and same cell position. False otherwise.
+bool TextBufferCellIterator::operator==(const TextBufferCellIterator& it) const noexcept
+{
+ return _pos == it._pos &&
+ &_buffer == &it._buffer &&
+ _exceeded == it._exceeded &&
+ _bounds == it._bounds &&
+ _pRow == it._pRow &&
+ _attrIter == it._attrIter;
+}
+
+// Routine Description:
+// - Compares two iterators to see if they're pointing to the different positions in the same buffer or different buffers entirely.
+// Arguments:
+// - it - The other iterator to compare to this one.
+// Return Value:
+// - True if it's the same text buffer and different cell position or if they're different buffers. False otherwise.
+bool TextBufferCellIterator::operator!=(const TextBufferCellIterator& it) const noexcept
+{
+ return !(*this == it);
+}
+
+// Routine Description:
+// - Advances the iterator forward relative to the underlying text buffer by the specified movement
+// Arguments:
+// - movement - Magnitude and direction of movement.
+// Return Value:
+// - Reference to self after movement.
+TextBufferCellIterator& TextBufferCellIterator::operator+=(const ptrdiff_t& movement)
+{
+ ptrdiff_t move = movement;
+ auto newPos = _pos;
+ while (move > 0 && !_exceeded)
+ {
+ _exceeded = !_bounds.IncrementInBounds(newPos);
+ move--;
+ }
+ while (move < 0 && !_exceeded)
+ {
+ _exceeded = !_bounds.DecrementInBounds(newPos);
+ move++;
+ }
+ _SetPos(newPos);
+ return (*this);
+}
+
+// Routine Description:
+// - Advances the iterator backward relative to the underlying text buffer by the specified movement
+// Arguments:
+// - movement - Magnitude and direction of movement.
+// Return Value:
+// - Reference to self after movement.
+TextBufferCellIterator& TextBufferCellIterator::operator-=(const ptrdiff_t& movement)
+{
+ return this->operator+=(-movement);
+}
+
+// Routine Description:
+// - Advances the iterator forward relative to the underlying text buffer by exactly 1
+// Return Value:
+// - Reference to self after movement.
+TextBufferCellIterator& TextBufferCellIterator::operator++()
+{
+ return this->operator+=(1);
+}
+
+// Routine Description:
+// - Advances the iterator backward relative to the underlying text buffer by exactly 1
+// Return Value:
+// - Reference to self after movement.
+TextBufferCellIterator& TextBufferCellIterator::operator--()
+{
+ return this->operator-=(1);
+}
+
+// Routine Description:
+// - Advances the iterator forward relative to the underlying text buffer by exactly 1
+// Return Value:
+// - Value with previous position prior to movement.
+TextBufferCellIterator TextBufferCellIterator::operator++(int)
+{
+ auto temp(*this);
+ operator++();
+ return temp;
+}
+
+// Routine Description:
+// - Advances the iterator backward relative to the underlying text buffer by exactly 1
+// Return Value:
+// - Value with previous position prior to movement.
+TextBufferCellIterator TextBufferCellIterator::operator--(int)
+{
+ auto temp(*this);
+ operator--();
+ return temp;
+}
+
+// Routine Description:
+// - Advances the iterator forward relative to the underlying text buffer by the specified movement
+// Arguments:
+// - movement - Magnitude and direction of movement.
+// Return Value:
+// - Value with previous position prior to movement.
+TextBufferCellIterator TextBufferCellIterator::operator+(const ptrdiff_t& movement)
+{
+ auto temp(*this);
+ temp += movement;
+ return temp;
+}
+
+// Routine Description:
+// - Advances the iterator negative relative to the underlying text buffer by the specified movement
+// Arguments:
+// - movement - Magnitude and direction of movement.
+// Return Value:
+// - Value with previous position prior to movement.
+TextBufferCellIterator TextBufferCellIterator::operator-(const ptrdiff_t& movement)
+{
+ auto temp(*this);
+ temp -= movement;
+ return temp;
+}
+
+// Routine Description:
+// - Provides the difference in position between two iterators.
+// Arguments:
+// - it - The other iterator to compare to this one.
+ptrdiff_t TextBufferCellIterator::operator-(const TextBufferCellIterator& it)
+{
+ THROW_HR_IF(E_NOT_VALID_STATE, &_buffer != &it._buffer); // It's not valid to compare this for iterators pointing at different buffers.
+ return _bounds.CompareInBounds(_pos, it._pos);
+}
+
+// Routine Description:
+// - Sets the coordinate position that this iterator will inspect within the text buffer on dereference.
+// Arguments:
+// - newPos - The new coordinate position.
+void TextBufferCellIterator::_SetPos(const COORD newPos)
+{
+ if (newPos.Y != _pos.Y)
+ {
+ _pRow = s_GetRow(_buffer, newPos);
+ _attrIter = _pRow->GetAttrRow().cbegin();
+ _pos.X = 0;
+ }
+
+ if (newPos.X != _pos.X)
+ {
+ const ptrdiff_t diff = newPos.X - _pos.X;
+ _attrIter += diff;
+ }
+
+ _pos = newPos;
+
+ _GenerateView();
+}
+
+// Routine Description:
+// - Shortcut for pulling the row out of the text buffer embedded in the screen information.
+// We'll hold and cache this to improve performance over looking it up every time.
+// Arguments:
+// - buffer - Screen information pointer to pull text buffer data from
+// - pos - Position inside screen buffer bounds to retrieve row
+// Return Value:
+// - Pointer to the underlying CharRow structure
+const ROW* TextBufferCellIterator::s_GetRow(const TextBuffer& buffer, const COORD pos)
+{
+ return &buffer.GetRowByOffset(pos.Y);
+}
+
+// Routine Description:
+// - Updates the internal view. Call after updating row, attribute, or positions.
+void TextBufferCellIterator::_GenerateView()
+{
+ _view = OutputCellView(_pRow->GetCharRow().GlyphAt(_pos.X),
+ _pRow->GetCharRow().DbcsAttrAt(_pos.X),
+ *_attrIter,
+ TextAttributeBehavior::Stored);
+}
+
+// Routine Description:
+// - Provides full fidelity view of the cell data in the underlying buffer.
+// Arguments:
+// - - Uses current position
+// Return Value:
+// - OutputCellView representation that provides a read-only view into the underlying text buffer data.
+const OutputCellView& TextBufferCellIterator::operator*() const noexcept
+{
+ return _view;
+}
+
+// Routine Description:
+// - Provides full fidelity view of the cell data in the underlying buffer.
+// Arguments:
+// - - Uses current position
+// Return Value:
+// - OutputCellView representation that provides a read-only view into the underlying text buffer data.
+const OutputCellView* TextBufferCellIterator::operator->() const noexcept
+{
+ return &_view;
+}
diff --git a/src/buffer/out/textBufferCellIterator.hpp b/src/buffer/out/textBufferCellIterator.hpp
new file mode 100644
index 00000000000..75cc8d08c87
--- /dev/null
+++ b/src/buffer/out/textBufferCellIterator.hpp
@@ -0,0 +1,73 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- textBufferCellIterator.hpp
+
+Abstract:
+- This module abstracts walking through text on the screen
+- It is currently intended for read-only operations
+
+Author(s):
+- Michael Niksa (MiNiksa) 29-Jun-2018
+--*/
+
+#pragma once
+
+#include "AttrRowIterator.hpp"
+#include "CharRow.hpp"
+#include "OutputCellView.hpp"
+#include "../../types/inc/viewport.hpp"
+
+class TextBuffer;
+
+class TextBufferCellIterator
+{
+public:
+ TextBufferCellIterator(const TextBuffer& buffer, COORD pos);
+ TextBufferCellIterator(const TextBuffer& buffer, COORD pos, const Microsoft::Console::Types::Viewport limits);
+
+ ~TextBufferCellIterator() = default;
+
+ operator bool() const noexcept;
+
+ bool operator==(const TextBufferCellIterator& it) const noexcept;
+ bool operator!=(const TextBufferCellIterator& it) const noexcept;
+
+ TextBufferCellIterator& operator+=(const ptrdiff_t& movement);
+ TextBufferCellIterator& operator-=(const ptrdiff_t& movement);
+ TextBufferCellIterator& operator++();
+ TextBufferCellIterator& operator--();
+ TextBufferCellIterator operator++(int);
+ TextBufferCellIterator operator--(int);
+ TextBufferCellIterator operator+(const ptrdiff_t& movement);
+ TextBufferCellIterator operator-(const ptrdiff_t& movement);
+
+ ptrdiff_t operator-(const TextBufferCellIterator& it);
+
+ const OutputCellView& operator*() const noexcept;
+ const OutputCellView* operator->() const noexcept;
+
+protected:
+
+ void _SetPos(const COORD newPos);
+ void _GenerateView();
+ static const ROW* s_GetRow(const TextBuffer& buffer, const COORD pos);
+
+ OutputCellView _view;
+
+ const ROW* _pRow;
+ AttrRowIterator _attrIter;
+ const TextBuffer& _buffer;
+ const Microsoft::Console::Types::Viewport _bounds;
+ bool _exceeded;
+ COORD _pos;
+
+#if UNIT_TESTING
+ friend class TextBufferIteratorTests;
+ friend class TextBufferTests;
+ friend class ApiRoutinesTests;
+#endif
+};
+
diff --git a/src/buffer/out/textBufferTextIterator.cpp b/src/buffer/out/textBufferTextIterator.cpp
new file mode 100644
index 00000000000..e1fe1a65b1d
--- /dev/null
+++ b/src/buffer/out/textBufferTextIterator.cpp
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#include "textBufferTextIterator.hpp"
+
+#include "CharRow.hpp"
+#include "Row.hpp"
+
+#pragma hdrstop
+
+using namespace Microsoft::Console::Types;
+
+// Routine Description:
+// - Narrows the view of a cell iterator into a text only iterator.
+// Arguments:
+// - A cell iterator
+TextBufferTextIterator::TextBufferTextIterator(const TextBufferCellIterator& cellIt) :
+ TextBufferCellIterator(cellIt)
+{
+}
+
+// Routine Description:
+// - Returns the text information from the text buffer position addressed by this iterator.
+// Return Value:
+// - Read only UTF-16 text data
+const std::wstring_view TextBufferTextIterator::operator*() const
+{
+ return _view.Chars();
+}
+
+// Routine Description:
+// - Returns the text information from the text buffer position addressed by this iterator.
+// Return Value:
+// - Read only UTF-16 text data
+const std::wstring_view* TextBufferTextIterator::operator->() const
+{
+ return &_view.Chars();
+}
+
diff --git a/src/buffer/out/textBufferTextIterator.hpp b/src/buffer/out/textBufferTextIterator.hpp
new file mode 100644
index 00000000000..8d8b5cbf9d7
--- /dev/null
+++ b/src/buffer/out/textBufferTextIterator.hpp
@@ -0,0 +1,35 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- textBufferTextIterator.hpp
+
+Abstract:
+- This module abstracts walking through text on the screen
+- It is currently intended for read-only operations
+
+Author(s):
+- Michael Niksa (MiNiksa) 01-May-2018
+--*/
+
+#pragma once
+
+#include "textBufferCellIterator.hpp"
+
+class SCREEN_INFORMATION;
+
+class TextBufferTextIterator final : public TextBufferCellIterator
+{
+public:
+ TextBufferTextIterator(const TextBufferCellIterator& cellIter);
+
+ const std::wstring_view operator*() const;
+ const std::wstring_view* operator->() const;
+
+protected:
+
+#if UNIT_TESTING
+ friend class TextBufferIteratorTests;
+#endif
+};
diff --git a/src/buffer/out/ut_textbuffer/DefaultResource.rc b/src/buffer/out/ut_textbuffer/DefaultResource.rc
new file mode 100644
index 00000000000..b9c0c585f91
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/DefaultResource.rc
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+//Autogenerated file name + version resource file for Device Guard whitelisting effort
+
+#include
+#include
+
+#define VER_FILETYPE VFT_UNKNOWN
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR ___TARGETNAME
+#define VER_INTERNALNAME_STR ___TARGETNAME
+#define VER_ORIGINALFILENAME_STR ___TARGETNAME
+
+#include "common.ver"
diff --git a/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp b/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp
new file mode 100644
index 00000000000..0906803046b
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp
@@ -0,0 +1,209 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "WexTestClass.h"
+#include "../../inc/consoletaeftemplates.hpp"
+
+#include "../TextAttribute.hpp"
+
+using namespace WEX::Common;
+using namespace WEX::Logging;
+using namespace WEX::TestExecution;
+
+class TextAttributeTests
+{
+ TEST_CLASS(TextAttributeTests);
+ TEST_CLASS_SETUP(ClassSetup);
+
+ TEST_METHOD(TestRoundtripLegacy);
+ TEST_METHOD(TestRoundtripMetaBits);
+ TEST_METHOD(TestRoundtripExhaustive);
+ TEST_METHOD(TestTextAttributeColorGetters);
+ TEST_METHOD(TestReverseDefaultColors);
+
+ static const int COLOR_TABLE_SIZE = 16;
+ COLORREF _colorTable[COLOR_TABLE_SIZE];
+ COLORREF _defaultFg = RGB(1, 2, 3);
+ COLORREF _defaultBg = RGB(4, 5, 6);
+ std::basic_string_view _GetTableView();
+};
+
+bool TextAttributeTests::ClassSetup()
+{
+ _colorTable[0] = RGB(12, 12, 12); // Black
+ _colorTable[1] = RGB(0, 55, 218); // Dark Blue
+ _colorTable[2] = RGB(19, 161, 14); // Dark Green
+ _colorTable[3] = RGB(58, 150, 221); // Dark Cyan
+ _colorTable[4] = RGB(197, 15, 31); // Dark Red
+ _colorTable[5] = RGB(136, 23, 152); // Dark Magenta
+ _colorTable[6] = RGB(193, 156, 0); // Dark Yellow
+ _colorTable[7] = RGB(204, 204, 204); // Dark White
+ _colorTable[8] = RGB(118, 118, 118); // Bright Black
+ _colorTable[9] = RGB(59, 120, 255); // Bright Blue
+ _colorTable[10] = RGB(22, 198, 12); // Bright Green
+ _colorTable[11] = RGB(97, 214, 214); // Bright Cyan
+ _colorTable[12] = RGB(231, 72, 86); // Bright Red
+ _colorTable[13] = RGB(180, 0, 158); // Bright Magenta
+ _colorTable[14] = RGB(249, 241, 165); // Bright Yellow
+ _colorTable[15] = RGB(242, 242, 242); // White
+ return true;
+}
+
+std::basic_string_view TextAttributeTests::_GetTableView()
+{
+ return std::basic_string_view(&_colorTable[0], COLOR_TABLE_SIZE);
+}
+
+void TextAttributeTests::TestRoundtripLegacy()
+{
+ WORD expectedLegacy = FOREGROUND_BLUE | BACKGROUND_RED;
+ WORD bgOnly = expectedLegacy & BG_ATTRS;
+ WORD bgShifted = bgOnly >> 4;
+ BYTE bgByte = (BYTE)(bgShifted);
+
+ VERIFY_ARE_EQUAL(FOREGROUND_RED, bgByte);
+
+ auto attr = TextAttribute(expectedLegacy);
+
+ VERIFY_IS_TRUE(attr.IsLegacy());
+ VERIFY_ARE_EQUAL(expectedLegacy, attr.GetLegacyAttributes());
+}
+
+void TextAttributeTests::TestRoundtripMetaBits()
+{
+ WORD metaFlags[] =
+ {
+ COMMON_LVB_GRID_HORIZONTAL,
+ COMMON_LVB_GRID_LVERTICAL,
+ COMMON_LVB_GRID_RVERTICAL,
+ COMMON_LVB_REVERSE_VIDEO,
+ COMMON_LVB_UNDERSCORE
+ };
+
+ for (int i = 0; i < ARRAYSIZE(metaFlags); ++i)
+ {
+ WORD flag = metaFlags[i];
+ WORD expectedLegacy = FOREGROUND_BLUE | BACKGROUND_RED | flag;
+ WORD metaOnly = expectedLegacy & META_ATTRS;
+ VERIFY_ARE_EQUAL(flag, metaOnly);
+
+ auto attr = TextAttribute(expectedLegacy);
+ VERIFY_IS_TRUE(attr.IsLegacy());
+ VERIFY_ARE_EQUAL(expectedLegacy, attr.GetLegacyAttributes());
+ VERIFY_ARE_EQUAL(flag, attr._wAttrLegacy);
+ }
+}
+
+void TextAttributeTests::TestRoundtripExhaustive()
+{
+ WORD allAttrs = (META_ATTRS | FG_ATTRS | BG_ATTRS);
+ // This test covers some 0xdfff test cases, printing out Verify: IsTrue for
+ // each takes a lot longer than checking.
+ // Only VERIFY if the comparison actually fails to speed up the test.
+ Log::Comment(L"This test will check each possible legacy attribute to make "
+ "sure it roundtrips through the creation of a text attribute.");
+ Log::Comment(L"It will only log if it fails.");
+ for (WORD wLegacy = 0; wLegacy < allAttrs; wLegacy++)
+ {
+ // 0x2000 is not an actual meta attribute
+ // COMMON_LVB_TRAILING_BYTE and COMMON_LVB_TRAILING_BYTE are no longer
+ // stored in the TextAttributes, they're stored in the CharRow
+ if (WI_IsFlagSet(wLegacy, 0x2000) ||
+ WI_IsFlagSet(wLegacy, COMMON_LVB_LEADING_BYTE) ||
+ WI_IsFlagSet(wLegacy, COMMON_LVB_TRAILING_BYTE))
+ {
+ continue;
+ }
+
+ auto attr = TextAttribute(wLegacy);
+
+ bool isLegacy = attr.IsLegacy();
+ bool areEqual = (wLegacy == attr.GetLegacyAttributes());
+ if (!(isLegacy && areEqual))
+ {
+ Log::Comment(NoThrowString().Format(
+ L"Failed on wLegacy=0x%x", wLegacy
+ ));
+ VERIFY_IS_TRUE(attr.IsLegacy());
+ VERIFY_ARE_EQUAL(wLegacy, attr.GetLegacyAttributes());
+ }
+ }
+}
+
+void TextAttributeTests::TestTextAttributeColorGetters()
+{
+ const COLORREF red = RGB(255, 0, 0);
+ const COLORREF green = RGB(0, 255, 0);
+ TextAttribute attr(red, green);
+ auto view = _GetTableView();
+
+ // verify that calculated foreground/background are the same as the direct
+ // values when reverse video is not set
+ VERIFY_IS_FALSE(attr._IsReverseVideo());
+
+ VERIFY_ARE_EQUAL(red, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(red, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(green, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(green, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+
+ // with reverse video set, calucated foreground/background values should be
+ // switched while getters stay the same
+ attr.SetMetaAttributes(COMMON_LVB_REVERSE_VIDEO);
+
+ VERIFY_ARE_EQUAL(red, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(green, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(green, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(red, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+}
+
+void TextAttributeTests::TestReverseDefaultColors()
+{
+ const COLORREF red = RGB(255, 0, 0);
+ const COLORREF green = RGB(0, 255, 0);
+ TextAttribute attr{};
+ auto view = _GetTableView();
+
+ // verify that calculated foreground/background are the same as the direct
+ // values when reverse video is not set
+ VERIFY_IS_FALSE(attr._IsReverseVideo());
+
+ VERIFY_ARE_EQUAL(_defaultFg, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(_defaultFg, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(_defaultBg, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(_defaultBg, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+
+ // with reverse video set, calucated foreground/background values should be
+ // switched while getters stay the same
+ attr.SetMetaAttributes(COMMON_LVB_REVERSE_VIDEO);
+ VERIFY_IS_TRUE(attr._IsReverseVideo());
+
+ VERIFY_ARE_EQUAL(_defaultFg, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(_defaultBg, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(_defaultBg, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(_defaultFg, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+
+ attr.SetForeground(red);
+ VERIFY_IS_TRUE(attr._IsReverseVideo());
+
+ VERIFY_ARE_EQUAL(red, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(_defaultBg, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(_defaultBg, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(red, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+
+ attr.Invert();
+ VERIFY_IS_FALSE(attr._IsReverseVideo());
+ attr.SetDefaultForeground();
+ attr.SetBackground(green);
+
+ VERIFY_ARE_EQUAL(_defaultFg, attr._GetRgbForeground(view, _defaultFg));
+ VERIFY_ARE_EQUAL(_defaultFg, attr.CalculateRgbForeground(view, _defaultFg, _defaultBg));
+
+ VERIFY_ARE_EQUAL(green, attr._GetRgbBackground(view, _defaultBg));
+ VERIFY_ARE_EQUAL(green, attr.CalculateRgbBackground(view, _defaultFg, _defaultBg));
+}
diff --git a/src/buffer/out/ut_textbuffer/TextBuffer.Unittests.vcxproj b/src/buffer/out/ut_textbuffer/TextBuffer.Unittests.vcxproj
new file mode 100644
index 00000000000..e763c0f9117
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/TextBuffer.Unittests.vcxproj
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+ {0cf235bd-2da0-407e-90ee-c467e8bbc714}
+
+
+
+
+
+
+ {531C23E7-4B76-4C08-8BBD-04164CB628C9}
+ Win32Proj
+ TextBufferUnitTests
+ TextBuffer.UnitTests
+ TextBuffer.UnitTests
+
+
+
+ ..;$(SolutionDir)src\inc;$(SolutionDir)src\inc\test;%(AdditionalIncludeDirectories)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/buffer/out/ut_textbuffer/TextColorTests.cpp b/src/buffer/out/ut_textbuffer/TextColorTests.cpp
new file mode 100644
index 00000000000..dc5c23adb97
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/TextColorTests.cpp
@@ -0,0 +1,215 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "WexTestClass.h"
+#include "../../inc/consoletaeftemplates.hpp"
+
+#include "../TextColor.h"
+
+using namespace WEX::Common;
+using namespace WEX::Logging;
+using namespace WEX::TestExecution;
+
+class TextColorTests
+{
+ TEST_CLASS(TextColorTests);
+
+ TEST_CLASS_SETUP(ClassSetup);
+
+ TEST_METHOD(TestDefaultColor);
+ TEST_METHOD(TestDarkIndexColor);
+ TEST_METHOD(TestBrightIndexColor);
+ TEST_METHOD(TestRgbColor);
+ TEST_METHOD(TestChangeColor);
+
+ static const int COLOR_TABLE_SIZE = 16;
+ COLORREF _colorTable[COLOR_TABLE_SIZE];
+ COLORREF _defaultFg = RGB(1, 2, 3);
+ COLORREF _defaultBg = RGB(4, 5, 6);
+ std::basic_string_view _GetTableView();
+};
+
+bool TextColorTests::ClassSetup()
+{
+ _colorTable[0] = RGB(12, 12, 12); // Black
+ _colorTable[1] = RGB(0, 55, 218); // Dark Blue
+ _colorTable[2] = RGB(19, 161, 14); // Dark Green
+ _colorTable[3] = RGB(58, 150, 221); // Dark Cyan
+ _colorTable[4] = RGB(197, 15, 31); // Dark Red
+ _colorTable[5] = RGB(136, 23, 152); // Dark Magenta
+ _colorTable[6] = RGB(193, 156, 0); // Dark Yellow
+ _colorTable[7] = RGB(204, 204, 204); // Dark White
+ _colorTable[8] = RGB(118, 118, 118); // Bright Black
+ _colorTable[9] = RGB(59, 120, 255); // Bright Blue
+ _colorTable[10] = RGB(22, 198, 12); // Bright Green
+ _colorTable[11] = RGB(97, 214, 214); // Bright Cyan
+ _colorTable[12] = RGB(231, 72, 86); // Bright Red
+ _colorTable[13] = RGB(180, 0, 158); // Bright Magenta
+ _colorTable[14] = RGB(249, 241, 165); // Bright Yellow
+ _colorTable[15] = RGB(242, 242, 242); // White
+ return true;
+}
+
+std::basic_string_view TextColorTests::_GetTableView()
+{
+ return std::basic_string_view(&_colorTable[0], COLOR_TABLE_SIZE);
+}
+
+void TextColorTests::TestDefaultColor()
+{
+ TextColor defaultColor;
+
+ VERIFY_IS_TRUE(defaultColor.IsDefault());
+ VERIFY_IS_FALSE(defaultColor.IsLegacy());
+ VERIFY_IS_FALSE(defaultColor.IsRgb());
+
+ auto view = _GetTableView();
+
+ auto color = defaultColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_defaultFg, color);
+
+ color = defaultColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_defaultFg, color);
+
+ color = defaultColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_defaultBg, color);
+
+ color = defaultColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_defaultBg, color);
+}
+
+void TextColorTests::TestDarkIndexColor()
+{
+ TextColor indexColor((BYTE)(7));
+
+ VERIFY_IS_FALSE(indexColor.IsDefault());
+ VERIFY_IS_TRUE(indexColor.IsLegacy());
+ VERIFY_IS_FALSE(indexColor.IsRgb());
+
+ auto view = _GetTableView();
+
+ auto color = indexColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_colorTable[7], color);
+
+ color = indexColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = indexColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_colorTable[7], color);
+
+ color = indexColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+}
+
+void TextColorTests::TestBrightIndexColor()
+{
+ TextColor indexColor((BYTE)(15));
+
+ VERIFY_IS_FALSE(indexColor.IsDefault());
+ VERIFY_IS_TRUE(indexColor.IsLegacy());
+ VERIFY_IS_FALSE(indexColor.IsRgb());
+
+ auto view = _GetTableView();
+
+ auto color = indexColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = indexColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = indexColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = indexColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+}
+
+void TextColorTests::TestRgbColor()
+{
+ COLORREF myColor = RGB(7, 8, 9);
+ TextColor rgbColor(myColor);
+
+ VERIFY_IS_FALSE(rgbColor.IsDefault());
+ VERIFY_IS_FALSE(rgbColor.IsLegacy());
+ VERIFY_IS_TRUE(rgbColor.IsRgb());
+
+ auto view = _GetTableView();
+
+ auto color = rgbColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(myColor, color);
+}
+
+void TextColorTests::TestChangeColor()
+{
+ COLORREF myColor = RGB(7, 8, 9);
+ TextColor rgbColor(myColor);
+
+ VERIFY_IS_FALSE(rgbColor.IsDefault());
+ VERIFY_IS_FALSE(rgbColor.IsLegacy());
+ VERIFY_IS_TRUE(rgbColor.IsRgb());
+
+ auto view = _GetTableView();
+
+ auto color = rgbColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(myColor, color);
+
+ rgbColor.SetDefault();
+
+ color = rgbColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_defaultFg, color);
+
+ color = rgbColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_defaultFg, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_defaultBg, color);
+
+ color = rgbColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_defaultBg, color);
+
+ rgbColor.SetIndex(7);
+ color = rgbColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_colorTable[7], color);
+
+ color = rgbColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = rgbColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_colorTable[7], color);
+
+ color = rgbColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+
+ rgbColor.SetIndex(15);
+ color = rgbColor.GetColor(view, _defaultFg, false);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = rgbColor.GetColor(view, _defaultFg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = rgbColor.GetColor(view, _defaultBg, false);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+
+ color = rgbColor.GetColor(view, _defaultBg, true);
+ VERIFY_ARE_EQUAL(_colorTable[15], color);
+}
diff --git a/src/buffer/out/ut_textbuffer/UnicodeStorageTests.cpp b/src/buffer/out/ut_textbuffer/UnicodeStorageTests.cpp
new file mode 100644
index 00000000000..9ba5aceac90
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/UnicodeStorageTests.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "WexTestClass.h"
+#include "../../inc/consoletaeftemplates.hpp"
+
+#include "../UnicodeStorage.hpp"
+
+using namespace WEX::Common;
+using namespace WEX::Logging;
+using namespace WEX::TestExecution;
+
+class UnicodeStorageTests
+{
+ TEST_CLASS(UnicodeStorageTests);
+
+
+ TEST_METHOD(CanOverwriteEmoji)
+ {
+ UnicodeStorage storage;
+ const COORD coord{ 1, 3 };
+ const std::vector newMoon{ 0xD83C, 0xDF11 };
+ const std::vector fullMoon{ 0xD83C, 0xDF15 };
+
+ // store initial glyph
+ storage.StoreGlyph(coord, newMoon);
+
+ // verify it was stored
+ auto findIt = storage._map.find(coord);
+ VERIFY_ARE_NOT_EQUAL(findIt, storage._map.end());
+ const std::vector& newMoonGlyph = findIt->second;
+ VERIFY_ARE_EQUAL(newMoonGlyph.size(), newMoon.size());
+ for (size_t i = 0; i < newMoon.size(); ++i)
+ {
+ VERIFY_ARE_EQUAL(newMoonGlyph.at(i), newMoon.at(i));
+ }
+
+ // overwrite it
+ storage.StoreGlyph(coord, fullMoon);
+
+ // verify the glyph was overwritten
+ findIt = storage._map.find(coord);
+ VERIFY_ARE_NOT_EQUAL(findIt, storage._map.end());
+ const std::vector& fullMoonGlyph = findIt->second;
+ VERIFY_ARE_EQUAL(fullMoonGlyph.size(), fullMoon.size());
+ for (size_t i = 0; i < fullMoon.size(); ++i)
+ {
+ VERIFY_ARE_EQUAL(fullMoonGlyph.at(i), fullMoon.at(i));
+ }
+ }
+};
diff --git a/src/buffer/out/ut_textbuffer/precomp.cpp b/src/buffer/out/ut_textbuffer/precomp.cpp
new file mode 100644
index 00000000000..c51e9b31b2f
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/precomp.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "precomp.h"
diff --git a/src/buffer/out/ut_textbuffer/precomp.h b/src/buffer/out/ut_textbuffer/precomp.h
new file mode 100644
index 00000000000..42155ece062
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/precomp.h
@@ -0,0 +1,37 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- precomp.h
+
+Abstract:
+- Contains external headers to include in the precompile phase of console build process.
+- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
+--*/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+// This includes support libraries from the CRT, STL, WIL, and GSL
+#include "LibraryIncludes.h"
+
+#pragma warning(push)
+#pragma warning(disable: ALL_CPPCORECHECK_WARNINGS)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+// Windows Header Files:
+#include
+#include
+
+// private dependencies
+#include "..\host\conddkrefs.h"
+#include "..\inc\operators.hpp"
+#include "..\inc\unicode.hpp"
+#pragma warning(pop)
diff --git a/src/buffer/out/ut_textbuffer/product.pbxproj b/src/buffer/out/ut_textbuffer/product.pbxproj
new file mode 100644
index 00000000000..9e5ef983069
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/product.pbxproj
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/buffer/out/ut_textbuffer/sources b/src/buffer/out/ut_textbuffer/sources
new file mode 100644
index 00000000000..ba50be8e342
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/sources
@@ -0,0 +1,31 @@
+!include ..\..\..\project.unittest.inc
+
+# -------------------------------------
+# Program Information
+# -------------------------------------
+
+TARGETNAME = Microsoft.Console.TextBuffer.UnitTests
+TARGETTYPE = DYNLINK
+DLLDEF =
+
+# -------------------------------------
+# Sources, Headers, and Libraries
+# -------------------------------------
+
+SOURCES = \
+ $(SOURCES) \
+ TextColorTests.cpp \
+ TextAttributeTests.cpp \
+ DefaultResource.rc \
+
+TARGETLIBS = \
+ $(CONSOLE_OBJ_PATH)\buffer\out\lib\$(O)\ConBufferOut.lib \
+ $(TARGETLIBS) \
+
+# -------------------------------------
+# Localization
+# -------------------------------------
+
+# Autogenerated. Sets file name for Device Guard whitelisting effort, used in RC.exe.
+C_DEFINES = $(C_DEFINES) -D___TARGETNAME="""$(TARGETNAME).$(TARGETTYPE)"""
+MUI_VERIFY_NO_LOC_RESOURCE = 1
diff --git a/src/buffer/out/ut_textbuffer/sources.dep b/src/buffer/out/ut_textbuffer/sources.dep
new file mode 100644
index 00000000000..ec5b5178605
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/sources.dep
@@ -0,0 +1,2 @@
+BUILD_PASS3_CONSUMES= \
+ onecore\merged\mbs\bootableskus\prepareimagingtools|PASS3 \
diff --git a/src/buffer/out/ut_textbuffer/testmd.definition b/src/buffer/out/ut_textbuffer/testmd.definition
new file mode 100644
index 00000000000..2f5ebc48821
--- /dev/null
+++ b/src/buffer/out/ut_textbuffer/testmd.definition
@@ -0,0 +1,18 @@
+{
+ "$schema": "http://universaltest/schema/testmddefinition-2.json",
+ "Package": {
+ "ComponentName": "Console",
+ "SubComponentName": "TextBuffer-UnitTests"
+ },
+ "Execution": {
+ "Type": "TAEF",
+ "Parameter": ""
+ },
+ "Dependencies": {
+ "Files": [ ],
+ "RemoteFiles": [ ],
+ "Packages": [ ]
+ },
+ "Logs": [ ],
+ "Plugins": [ ]
+}
diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj
new file mode 100644
index 00000000000..832a6516f69
--- /dev/null
+++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+
+ 10.0.17763.0
+ 10.0.17763.0
+
+ false
+ false
+
+
+
+ CA5CAD1A-224A-4171-B13A-F16E576FDD12
+ ..\WindowsTerminal\WindowsTerminal.vcxproj
+
+
+
+ false
+ Never
+
+
+
+ true
+ False
+ CascadiaPackage_TemporaryKey.pfx
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+ $(WapProjBeforeGenerateAppxManifestDependsOn);
+ _ConsoleInjectMUXWinmdIntoReferences;
+
+
+
+
+ <_WinmdFilesFromReferences Include="@(Reference)" Condition="'%(Reference.Filename)' == 'Microsoft.UI.Xaml' and '%(Reference.Extension)' == '.winmd'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TemporaryFilteredWapProjOutput
+ Include="@(_FilteredNonWapProjProjectOutput)" />
+ <_FilteredNonWapProjProjectOutput Remove="@(_TemporaryFilteredWapProjOutput)" />
+ <_FilteredNonWapProjProjectOutput Include="@(_TemporaryFilteredWapProjOutput)">
+
+ conhost.exe
+
+
+
+
+
+
+
diff --git a/src/cascadia/CascadiaPackage/Images/LargeTile.scale-100.png b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-100.png
new file mode 100644
index 00000000000..9dc3142df48
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/LargeTile.scale-125.png b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-125.png
new file mode 100644
index 00000000000..5e8f1ef7033
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/LargeTile.scale-150.png b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-150.png
new file mode 100644
index 00000000000..a1a56a21e23
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/LargeTile.scale-200.png b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-200.png
new file mode 100644
index 00000000000..187c1149792
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/LargeTile.scale-400.png b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-400.png
new file mode 100644
index 00000000000..5e4fcd64455
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LargeTile.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/LockScreenLogo.scale-200.png b/src/cascadia/CascadiaPackage/Images/LockScreenLogo.scale-200.png
new file mode 100644
index 00000000000..049e9f3f5e7
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/LockScreenLogo.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SmallTile.scale-100.png b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-100.png
new file mode 100644
index 00000000000..04fc0ef9ee8
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SmallTile.scale-125.png b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-125.png
new file mode 100644
index 00000000000..9697ca7a0c2
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SmallTile.scale-150.png b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-150.png
new file mode 100644
index 00000000000..0053392c98d
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SmallTile.scale-200.png b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-200.png
new file mode 100644
index 00000000000..354ee74e238
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SmallTile.scale-400.png b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-400.png
new file mode 100644
index 00000000000..d910a79caf2
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SmallTile.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-100.png b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-100.png
new file mode 100644
index 00000000000..2817a1fb6c7
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-125.png b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-125.png
new file mode 100644
index 00000000000..f47191372a6
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-150.png b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-150.png
new file mode 100644
index 00000000000..14bbabe616a
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-200.png b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-200.png
new file mode 100644
index 00000000000..277cc6345c0
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-400.png b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-400.png
new file mode 100644
index 00000000000..6ba469bce65
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/SplashScreen.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-100.png b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-100.png
new file mode 100644
index 00000000000..cb220615631
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-125.png b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-125.png
new file mode 100644
index 00000000000..072b5a266d8
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-150.png b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-150.png
new file mode 100644
index 00000000000..21c55017aa6
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-200.png b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-200.png
new file mode 100644
index 00000000000..9809eea3b6e
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-400.png b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-400.png
new file mode 100644
index 00000000000..3348a8de3ec
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square150x150Logo.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-16.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-16.png
new file mode 100644
index 00000000000..c6ba2a8cf4d
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-16.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-256.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-256.png
new file mode 100644
index 00000000000..95891c26d5f
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-256.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-32.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-32.png
new file mode 100644
index 00000000000..7ea2557f57b
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-32.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-48.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-48.png
new file mode 100644
index 00000000000..a2d75e6a2c8
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.altform-unplated_targetsize-48.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-100.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-100.png
new file mode 100644
index 00000000000..f963d974437
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-125.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-125.png
new file mode 100644
index 00000000000..7918b1f1735
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-150.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-150.png
new file mode 100644
index 00000000000..d08aaca1ecb
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-200.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-200.png
new file mode 100644
index 00000000000..74568d91611
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-400.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-400.png
new file mode 100644
index 00000000000..cd966fc4e27
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-16.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-16.png
new file mode 100644
index 00000000000..08b9ea134d8
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-16.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24.png
new file mode 100644
index 00000000000..a3d86e50e3a
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 00000000000..ee78927eb8f
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-256.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-256.png
new file mode 100644
index 00000000000..5e2f32f440e
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-256.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-32.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-32.png
new file mode 100644
index 00000000000..7121f26ea84
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-32.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-48.png b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-48.png
new file mode 100644
index 00000000000..15a0929cf4f
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Square44x44Logo.targetsize-48.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-100.png b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-100.png
new file mode 100644
index 00000000000..2f7faf804e8
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-125.png b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-125.png
new file mode 100644
index 00000000000..4774dd8fa87
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-150.png b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-150.png
new file mode 100644
index 00000000000..32bfb681bb9
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-200.png b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-200.png
new file mode 100644
index 00000000000..64844192823
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-400.png b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-400.png
new file mode 100644
index 00000000000..d9781657713
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/StoreLogo.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-100.png b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-100.png
new file mode 100644
index 00000000000..e4c22ff1519
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-100.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-125.png b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-125.png
new file mode 100644
index 00000000000..f870fd5565d
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-125.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-150.png b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-150.png
new file mode 100644
index 00000000000..8090686f36b
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-150.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-200.png b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-200.png
new file mode 100644
index 00000000000..21489524a52
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-200.png differ
diff --git a/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-400.png b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-400.png
new file mode 100644
index 00000000000..277cc6345c0
Binary files /dev/null and b/src/cascadia/CascadiaPackage/Images/Wide310x150Logo.scale-400.png differ
diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest
new file mode 100644
index 00000000000..92ce4eb4ac4
--- /dev/null
+++ b/src/cascadia/CascadiaPackage/Package.appxmanifest
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+ ms-resource:AppName
+ Microsoft Corporation
+ Images\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cascadia/CascadiaPackage/Resources/en-US/Resources.resw b/src/cascadia/CascadiaPackage/Resources/en-US/Resources.resw
new file mode 100644
index 00000000000..f759e568acc
--- /dev/null
+++ b/src/cascadia/CascadiaPackage/Resources/en-US/Resources.resw
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Codename Cascadia
+
+
+ Windows Terminal (Preview)
+
+
\ No newline at end of file
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.def b/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.def
new file mode 100644
index 00000000000..8c1a02932d0
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.vcxproj b/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.vcxproj
new file mode 100644
index 00000000000..a5a61ab394c
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/Microsoft.UI.Xaml.Markup.vcxproj
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+ DynamicLibrary
+ Console
+
+ true
+
+
+
+
+ {015a0047-772d-4f1a-88c9-45c18f0adfb6}
+ Microsoft.UI.Xaml.Markup
+ Microsoft.UI.Xaml.Markup
+
+
+
+
+ $(OutDir)\$(TargetName)$(TargetExt)
+ WindowsApp.lib;Kernel32.lib;User32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ XamlApplication.idl
+
+
+
+
+
+ Create
+
+
+ XamlApplication.idl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/ReadMe.md b/src/cascadia/Microsoft.UI.Xaml.Markup/ReadMe.md
new file mode 100644
index 00000000000..089dc8d5cfd
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/ReadMe.md
@@ -0,0 +1,22 @@
+# Xaml Application for Win32
+
+This project implements an Xaml application that is suited for Win32 projects.
+A pseudo implementation of this object is:
+```
+namespace Microsoft.UI.Xaml.Markup
+{
+ interface IXamlMetadataProviderContainer
+ {
+ Windows.Foundation.Collections.IVector Providers { get; };
+ };
+
+ class XamlApplication : Windows.UI.Xaml.Application, IXamlMetadataProviderContainer, IDisposable
+ {
+ XamlApplication()
+ {
+ WindowsXamlManager.InitializeForThread();
+ }
+ }
+}
+```
+
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.cpp b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.cpp
new file mode 100644
index 00000000000..9182ab92058
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.cpp
@@ -0,0 +1,128 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+
+#include "XamlApplication.h"
+
+namespace xaml = ::winrt::Windows::UI::Xaml;
+
+extern "C" {
+ WINBASEAPI HMODULE WINAPI LoadLibraryExW(_In_ LPCWSTR lpLibFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags);
+ WINBASEAPI HMODULE WINAPI GetModuleHandleW(_In_opt_ LPCWSTR lpModuleName);
+ WINUSERAPI BOOL WINAPI PeekMessageW(_Out_ LPMSG lpMsg, _In_opt_ HWND hWnd, _In_ UINT wMsgFilterMin, _In_ UINT wMsgFilterMax, _In_ UINT wRemoveMsg);
+ WINUSERAPI LRESULT WINAPI DispatchMessageW(_In_ CONST MSG* lpMsg);
+}
+
+namespace winrt::Microsoft::UI::Xaml::Markup::implementation
+{
+ XamlApplication::XamlApplication(winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider parentProvider)
+ {
+ m_providers.Append(parentProvider);
+ }
+
+ XamlApplication::XamlApplication()
+ {
+ }
+
+ void XamlApplication::Close()
+ {
+ if (m_bIsClosed)
+ {
+ return;
+ }
+
+ m_bIsClosed = true;
+
+ m_providers.Clear();
+
+ Exit();
+ {
+ MSG msg = {};
+ while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
+ {
+ ::DispatchMessageW(&msg);
+ }
+ }
+ }
+
+ XamlApplication::~XamlApplication()
+ {
+ Close();
+ }
+
+ xaml::Markup::IXamlType XamlApplication::GetXamlType(xaml::Interop::TypeName const& type)
+ {
+ for (const auto& provider : m_providers)
+ {
+ const auto xamlType = provider.GetXamlType(type);
+ if (xamlType != nullptr)
+ {
+ return xamlType;
+ }
+ }
+
+ return nullptr;
+ }
+
+ xaml::Markup::IXamlType XamlApplication::GetXamlType(winrt::hstring const& fullName)
+ {
+ for (const auto& provider : m_providers)
+ {
+ const auto xamlType = provider.GetXamlType(fullName);
+ if (xamlType != nullptr)
+ {
+ return xamlType;
+ }
+ }
+
+ return nullptr;
+ }
+
+ winrt::com_array XamlApplication::GetXmlnsDefinitions()
+ {
+ std::list definitions;
+ for (const auto& provider : m_providers)
+ {
+ auto defs = provider.GetXmlnsDefinitions();
+ for (const auto& def : defs)
+ {
+ definitions.insert(definitions.begin(), def);
+ }
+ }
+
+ return winrt::com_array(definitions.begin(), definitions.end());
+ }
+
+ winrt::Windows::Foundation::Collections::IVector XamlApplication::Providers()
+ {
+ return m_providers;
+ }
+}
+
+namespace winrt::Microsoft::UI::Xaml::Markup::factory_implementation
+{
+ XamlApplication::XamlApplication()
+ {
+ // Workaround a bug where twinapi.appcore.dll and threadpoolwinrt.dll gets loaded after it has been unloaded
+ // because of a call to GetActivationFactory
+ const wchar_t* preloadDlls[] = {
+ L"twinapi.appcore.dll",
+ L"threadpoolwinrt.dll",
+ };
+ for (auto dllName : preloadDlls)
+ {
+ const auto module = ::LoadLibraryExW(dllName, nullptr, 0);
+ m_preloadInstances.push_back(module);
+ }
+ }
+
+ XamlApplication::~XamlApplication()
+ {
+ for (auto module : m_preloadInstances)
+ {
+ ::FreeLibrary(module);
+ }
+ m_preloadInstances.clear();
+ }
+}
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.h b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.h
new file mode 100644
index 00000000000..af9823f6fdf
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.h
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "XamlApplication.g.h"
+#include
+#include
+#include
+#include
+
+namespace winrt::Microsoft::UI::Xaml::Markup::implementation
+{
+ class XamlApplication : public XamlApplicationT
+ {
+ public:
+ XamlApplication();
+ XamlApplication(winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider parentProvider);
+ ~XamlApplication();
+
+ void Close();
+
+ winrt::Windows::UI::Xaml::Markup::IXamlType GetXamlType(winrt::Windows::UI::Xaml::Interop::TypeName const& type);
+ winrt::Windows::UI::Xaml::Markup::IXamlType GetXamlType(winrt::hstring const& fullName);
+ winrt::com_array GetXmlnsDefinitions();
+
+ winrt::Windows::Foundation::Collections::IVector Providers();
+
+ private:
+ winrt::Windows::Foundation::Collections::IVector m_providers = winrt::single_threaded_vector();
+ bool m_bIsClosed = false;
+ };
+}
+
+namespace winrt::Microsoft::UI::Xaml::Markup::factory_implementation
+{
+ class XamlApplication : public XamlApplicationT
+ {
+ public:
+ XamlApplication();
+ ~XamlApplication();
+ private:
+ std::vector m_preloadInstances;
+ };
+}
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.idl b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.idl
new file mode 100644
index 00000000000..19ba6175283
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/XamlApplication.idl
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+namespace Microsoft.UI.Xaml.Markup
+{
+ interface IXamlMetadataProviderContainer
+ {
+ Windows.Foundation.Collections.IVector Providers { get; };
+ };
+
+ [default_interface]
+ unsealed runtimeclass XamlApplication : Windows.UI.Xaml.Application, IXamlMetadataProviderContainer, Windows.Foundation.IClosable
+ {
+ XamlApplication();
+ protected XamlApplication(Windows.UI.Xaml.Markup.IXamlMetadataProvider parentProvider);
+ }
+}
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/packages.config b/src/cascadia/Microsoft.UI.Xaml.Markup/packages.config
new file mode 100644
index 00000000000..4f7a6f98af4
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/pch.cpp b/src/cascadia/Microsoft.UI.Xaml.Markup/pch.cpp
new file mode 100644
index 00000000000..3c27d44d570
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
diff --git a/src/cascadia/Microsoft.UI.Xaml.Markup/pch.h b/src/cascadia/Microsoft.UI.Xaml.Markup/pch.h
new file mode 100644
index 00000000000..eb8e9db80b1
--- /dev/null
+++ b/src/cascadia/Microsoft.UI.Xaml.Markup/pch.h
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+// Exclude rarely-used stuff from Windows headers
+#define WIN32_LEAN_AND_MEAN
+#include
+// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
+// SDK definition of this function, so the only fix is to undef it.
+// from WinBase.h
+// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
+// To enable support for non-WinRT interfaces, unknwn.h must be included before any C++/WinRT headers.
+#include
+
+#include
+
diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp
new file mode 100644
index 00000000000..0d8f39b2754
--- /dev/null
+++ b/src/cascadia/TerminalApp/App.cpp
@@ -0,0 +1,877 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "App.h"
+#include
+#include
+#include
+
+using namespace winrt::Windows::ApplicationModel::DataTransfer;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Core;
+using namespace winrt::Windows::System;
+using namespace winrt::Microsoft::Terminal;
+using namespace winrt::Microsoft::Terminal::Settings;
+using namespace winrt::Microsoft::Terminal::TerminalControl;
+using namespace ::TerminalApp;
+
+// Note: Generate GUID using TlgGuid.exe tool
+TRACELOGGING_DEFINE_PROVIDER(
+ g_hTerminalAppProvider,
+ "Microsoft.Windows.Terminal.App",
+ // {24a1622f-7da7-5c77-3303-d850bd1ab2ed}
+ (0x24a1622f, 0x7da7, 0x5c77, 0x33, 0x03, 0xd8, 0x50, 0xbd, 0x1a, 0xb2, 0xed),
+ TraceLoggingOptionMicrosoftTelemetry());
+
+namespace winrt
+{
+ namespace MUX = Microsoft::UI::Xaml;
+ using IInspectable = Windows::Foundation::IInspectable;
+}
+
+namespace winrt::TerminalApp::implementation
+{
+
+ App::App() :
+ App(winrt::TerminalApp::XamlMetaDataProvider())
+ {
+ }
+
+ App::App(Windows::UI::Xaml::Markup::IXamlMetadataProvider const& parentProvider) :
+ base_type(parentProvider),
+ _settings{ },
+ _tabs{ },
+ _loadedInitialSettings{ false }
+ {
+ // For your own sanity, it's better to do setup outside the ctor.
+ // If you do any setup in the ctor that ends up throwing an exception,
+ // then it might look like App just failed to activate, which will
+ // cause you to chase down the rabbit hole of "why is App not
+ // registered?" when it definitely is.
+ }
+
+ // Method Description:
+ // - Build the UI for the terminal app. Before this method is called, it
+ // should not be assumed that the TerminalApp is usable. The Settings
+ // should be loaded before this is called, either with LoadSettings or
+ // GetLaunchDimensions (which will call LoadSettings)
+ // Arguments:
+ // -
+ // Return Value:
+ // -
+ void App::Create()
+ {
+ // Assert that we've already loaded our settings. We have to do
+ // this as a MTA, before the app is Create()'d
+ WINRT_ASSERT(_loadedInitialSettings);
+ TraceLoggingRegister(g_hTerminalAppProvider);
+ _Create();
+ }
+
+ App::~App()
+ {
+ TraceLoggingUnregister(g_hTerminalAppProvider);
+ }
+
+ // Method Description:
+ // - Create all of the initial UI elements of the Terminal app.
+ // * Creates the tab bar, initially hidden.
+ // * Creates the tab content area, which is where we'll display the tabs/panes.
+ // * Initializes the first terminal control, using the default profile,
+ // and adds it to our list of tabs.
+ void App::_Create()
+ {
+ _tabView = MUX::Controls::TabView{};
+
+ _tabView.SelectionChanged({ this, &App::_OnTabSelectionChanged });
+ _tabView.TabClosing({ this, &App::_OnTabClosing });
+ _tabView.Items().VectorChanged({ this, &App::_OnTabItemsChanged });
+
+ _root = Controls::Grid{};
+
+ _tabRow = Controls::Grid{};
+ _tabRow.Name(L"Tab Row");
+ _tabContent = Controls::Grid{};
+ _tabContent.Name(L"Tab Content");
+
+ // Set up two columns in the tabs row - one for the tabs themselves, and
+ // another for the settings button.
+ auto tabsColDef = Controls::ColumnDefinition();
+ auto newTabBtnColDef = Controls::ColumnDefinition();
+
+ newTabBtnColDef.Width(GridLengthHelper::Auto());
+
+ _tabRow.ColumnDefinitions().Append(tabsColDef);
+ _tabRow.ColumnDefinitions().Append(newTabBtnColDef);
+
+ // Set up two rows - one for the tabs, the other for the tab content,
+ // the terminal panes.
+ auto tabBarRowDef = Controls::RowDefinition();
+ tabBarRowDef.Height(GridLengthHelper::Auto());
+ _root.RowDefinitions().Append(tabBarRowDef);
+ _root.RowDefinitions().Append(Controls::RowDefinition{});
+
+ if (_settings->GlobalSettings().GetShowTabsInTitlebar() == false)
+ {
+ _root.Children().Append(_tabRow);
+ Controls::Grid::SetRow(_tabRow, 0);
+ }
+ _root.Children().Append(_tabContent);
+ Controls::Grid::SetRow(_tabContent, 1);
+ Controls::Grid::SetColumn(_tabView, 0);
+
+ // Create the new tab button.
+ _newTabButton = Controls::SplitButton{};
+ Controls::SymbolIcon newTabIco{};
+ newTabIco.Symbol(Controls::Symbol::Add);
+ _newTabButton.Content(newTabIco);
+ Controls::Grid::SetRow(_newTabButton, 0);
+ Controls::Grid::SetColumn(_newTabButton, 1);
+ _newTabButton.VerticalAlignment(VerticalAlignment::Stretch);
+ _newTabButton.HorizontalAlignment(HorizontalAlignment::Left);
+
+ // When the new tab button is clicked, open the default profile
+ _newTabButton.Click([this](auto&&, auto&&){
+ this->_OpenNewTab(std::nullopt);
+ });
+
+ // Populate the new tab button's flyout with entries for each profile
+ _CreateNewTabFlyout();
+
+ _tabRow.Children().Append(_tabView);
+ _tabRow.Children().Append(_newTabButton);
+
+ _tabContent.VerticalAlignment(VerticalAlignment::Stretch);
+ _tabContent.HorizontalAlignment(HorizontalAlignment::Stretch);
+
+ // Here, we're doing the equivalent of defining the _tabRow as the
+ // following: We need to set the Background
+ // to that ThemeResource, so it'll be colored appropriately regardless
+ // of what theme the user has selected.
+ // We're looking up the Style we've defined in App.xaml, and applying it
+ // here. A ResourceDictionary is a Map, so
+ // you'll need to try_as to get the type we actually want.
+ auto res = Resources();
+ IInspectable key = winrt::box_value(L"BackgroundGridThemeStyle");
+ if (res.HasKey(key))
+ {
+ IInspectable g = res.Lookup(key);
+ winrt::Windows::UI::Xaml::Style style = g.try_as();
+ _tabRow.Style(style);
+ }
+
+ // Apply the UI theme from our settings to our UI elements
+ _ApplyTheme(_settings->GlobalSettings().GetRequestedTheme());
+
+ _OpenNewTab(std::nullopt);
+ }
+
+ // Method Description:
+ // - Get the size in pixels of the client area we'll need to launch this
+ // terminal app. This method will use the default profile's settings to do
+ // this calculation, as well as the _system_ dpi scaling. See also
+ // TermControl::GetProposedDimensions.
+ // Arguments:
+ // -
+ // Return Value:
+ // - a point containing the requested dimensions in pixels.
+ winrt::Windows::Foundation::Point App::GetLaunchDimensions(uint32_t dpi)
+ {
+ if (!_loadedInitialSettings)
+ {
+ // Load settings if we haven't already
+ LoadSettings();
+ }
+
+ // Use the default profile to determine how big of a window we need.
+ TerminalSettings settings = _settings->MakeSettings(std::nullopt);
+
+ // TODO MSFT:21150597 - If the global setting "Always show tab bar" is
+ // set, then we'll need to add the height of the tab bar here.
+
+ return TermControl::GetProposedDimensions(settings, dpi);
+ }
+
+
+ bool App::GetShowTabsInTitlebar()
+ {
+ if (!_loadedInitialSettings)
+ {
+ // Load settings if we haven't already
+ LoadSettings();
+ }
+
+ return _settings->GlobalSettings().GetShowTabsInTitlebar();
+ }
+
+ // Method Description:
+ // - Builds the flyout (dropdown) attached to the new tab button, and
+ // attaches it to the button. Populates the flyout with one entry per
+ // Profile, displaying the profile's name. Clicking each flyout item will
+ // open a new tab with that profile.
+ // Below the profiles are the static menu items: settings, feedback
+ void App::_CreateNewTabFlyout()
+ {
+ auto newTabFlyout = Controls::MenuFlyout{};
+ for (int profileIndex = 0; profileIndex < _settings->GetProfiles().size(); profileIndex++)
+ {
+ const auto& profile = _settings->GetProfiles()[profileIndex];
+ auto profileMenuItem = Controls::MenuFlyoutItem{};
+
+ auto profileName = profile.GetName();
+ winrt::hstring hName{ profileName };
+ profileMenuItem.Text(hName);
+
+ // If there's an icon set for this profile, set it as the icon for
+ // this flyout item.
+ if (profile.HasIcon())
+ {
+ profileMenuItem.Icon(_GetIconFromProfile(profile));
+ }
+
+ profileMenuItem.Click([this, profileIndex](auto&&, auto&&){
+ this->_OpenNewTab({ profileIndex });
+ });
+ newTabFlyout.Items().Append(profileMenuItem);
+ }
+
+ // add menu separator
+ auto separatorItem = Controls::MenuFlyoutSeparator{};
+ newTabFlyout.Items().Append(separatorItem);
+
+ // add static items
+ {
+ // Create the settings button.
+ auto settingsItem = Controls::MenuFlyoutItem{};
+ settingsItem.Text(L"Settings");
+
+ Controls::SymbolIcon ico{};
+ ico.Symbol(Controls::Symbol::Setting);
+ settingsItem.Icon(ico);
+
+ settingsItem.Click({ this, &App::_SettingsButtonOnClick });
+ newTabFlyout.Items().Append(settingsItem);
+
+ // Create the feedback button.
+ auto feedbackFlyout = Controls::MenuFlyoutItem{};
+ feedbackFlyout.Text(L"Feedback");
+
+ Controls::FontIcon feedbackIco{};
+ feedbackIco.Glyph(L"\xE939");
+ feedbackIco.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
+ feedbackFlyout.Icon(feedbackIco);
+
+ feedbackFlyout.Click({ this, &App::_FeedbackButtonOnClick });
+ newTabFlyout.Items().Append(feedbackFlyout);
+ }
+
+ _newTabButton.Flyout(newTabFlyout);
+ }
+
+ // Function Description:
+ // - Called when the settings button is clicked. ShellExecutes the settings
+ // file, as to open it in the default editor for .json files. Does this in
+ // a background thread, as to not hang/crash the UI thread.
+ fire_and_forget LaunchSettings()
+ {
+ // This will switch the execution of the function to a background (not
+ // UI) thread. This is IMPORTANT, because the Windows.Storage API's
+ // (used for retrieving the path to the file) will crash on the UI
+ // thread, because the main thread is a STA.
+ co_await winrt::resume_background();
+
+ const auto settingsPath = CascadiaSettings::GetSettingsPath();
+ ShellExecute(nullptr, L"open", settingsPath.c_str(), nullptr, nullptr, SW_SHOW);
+ }
+
+ // Method Description:
+ // - Called when the settings button is clicked. Launches a background
+ // thread to open the settings file in the default JSON editor.
+ // Arguments:
+ // -
+ // Return Value:
+ // -