This commit is contained in:
Leonard Hecker 2021-08-19 21:21:33 +02:00
parent 479ef264b2
commit 9cb4fc4373
99 changed files with 5826 additions and 1139 deletions

View file

@ -9,6 +9,7 @@ BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
calloc
charconv
CLASSNOTAVAILABLE
cmdletbinding
@ -25,6 +26,8 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
dxgidebug
dxguid
enumset
environstrings
EXPCMDFLAGS
@ -66,8 +69,8 @@ IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
isspace
IStorage
istream
IStringable
@ -82,12 +85,12 @@ llu
localtime
lround
LSHIFT
memicmp
MENUCOMMAND
MENUDATA
MENUINFO
memicmp
mptt
mov
mptt
msappx
MULTIPLEUSE
NCHITTEST

View file

@ -3,6 +3,7 @@ austdi
Ballmer
bhoj
Bhojwani
Bilodeau
carlos
dhowett
Diviness
@ -25,8 +26,8 @@ jerrysh
Kaiyu
kimwalisch
KMehrain
KODELIFE
Kodelife
KODELIFE
Kourosh
kowalczyk
leonmsft
@ -73,8 +74,8 @@ Wirt
Wojciech
zadjii
Zamor
Zamora
zamora
Zamora
Zoey
zorio
Zverovich

View file

@ -312,6 +312,7 @@ commdlg
COMMITID
compat
componentization
COMPOSITIONSURFACE
conapi
conareainfo
conattrs
@ -426,6 +427,8 @@ cstring
cstyle
csv
CSwitch
csx
csy
CTerminal
CText
ctime
@ -847,6 +850,7 @@ GAUSSIAN
gci
gcx
gcy
GDC
gdi
gdip
gdirenderer
@ -1344,6 +1348,7 @@ LPWINDOWPOS
lpwpos
lpwstr
LRESULT
lroundf
lru
lsb
lsconfig
@ -1445,6 +1450,7 @@ MOUSEMOVE
mousewheel
movemask
MOVESTART
movsb
msb
msbuild
mscorlib
@ -1623,6 +1629,7 @@ NVIDIA
NVR
OACR
oauth
obin
objbase
ocf
ocolor
@ -1746,6 +1753,7 @@ pdx
peb
PEMAGIC
PENDTASKMSG
Pentium
pfa
PFACENODE
pfed
@ -1910,6 +1918,7 @@ pythonw
qos
QRSTU
qsort
Qstrip
queryable
QUESTIONMARK
quickedit
@ -1917,6 +1926,7 @@ QWER
qzmp
RAII
RALT
rapi
rasterbar
rasterfont
rasterization
@ -2199,7 +2209,6 @@ somefile
SOURCEBRANCH
sourced
SOURCESDIRECTORY
SPACEBAR
spammy
spand
sprintf
@ -2309,6 +2318,7 @@ taskbar
tbar
TBase
tbc
TBDR
tbi
Tbl
TBM
@ -2421,6 +2431,7 @@ Trd
TREX
triaged
triaging
TRIANGLELIST
TRIANGLESTRIP
TRIMZEROHEADINGS
truetype
@ -2498,12 +2509,13 @@ unittesting
universaltest
unk
unknwn
Unmap
unmark
UNORM
unparseable
unpause
Unregister
unregistering
unscoped
untests
untextured
untimes
@ -2568,6 +2580,7 @@ vectorized
VERCTRL
versioning
VERTBAR
VERTEXID
VFT
vga
vgaoem
@ -2575,6 +2588,7 @@ viewkind
viewports
Virt
VIRTTERM
virtualalloc
Virtualizing
vkey
VKKEYSCAN
@ -2851,6 +2865,7 @@ YDPI
yIcon
yml
YOffset
yolo
YPosition
YSize
YSubstantial

View file

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29001.49
# Visual Studio Version 17
VisualStudioVersion = 17.0.31410.414
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Terminal", "Terminal", "{59840756-302F-44DF-AA47-441A9D673202}"
EndProject
@ -131,6 +131,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scratch", "src\tools\scratc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InteractivityWin32", "src\interactivity\win32\lib\win32.LIB.vcxproj", "{06EC74CB-9A12-429C-B551-8532EC964726}"
ProjectSection(ProjectDependencies) = postProject
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {8222900C-8B6C-452A-91AC-BE95DB04B95F}
{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}
@ -400,6 +401,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "HostPackage", "src\host\HostPackage\HostPackage.wapproj", "{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenConsoleShellExt", "src\host\ShellExtension\OpenConsoleShellExt.vcxproj", "{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@ -3339,6 +3346,170 @@ Global
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|Any CPU.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|Any CPU.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|Any CPU.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM.ActiveCfg = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM.Build.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM.Deploy.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM64.Build.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x64Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x64Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x64Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x86Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x86Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|DotNet_x86Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x64.ActiveCfg = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x64.Build.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x64.Deploy.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x86.ActiveCfg = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x86.Build.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.AuditMode|x86.Deploy.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM.ActiveCfg = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM.Build.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM.Deploy.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM64.Build.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|ARM64.Deploy.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x64Test.ActiveCfg = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x64Test.Build.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x64Test.Deploy.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x86Test.ActiveCfg = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x86Test.Build.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|DotNet_x86Test.Deploy.0 = Debug|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x64.ActiveCfg = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x64.Build.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x64.Deploy.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x86.ActiveCfg = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x86.Build.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Debug|x86.Deploy.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|Any CPU.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|Any CPU.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|Any CPU.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM.ActiveCfg = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM.Build.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM.Deploy.0 = Debug|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM64.Build.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x64Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x64Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x64Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x86Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x86Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|DotNet_x86Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x64.ActiveCfg = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x64.Build.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x64.Deploy.0 = Debug|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x86.ActiveCfg = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x86.Build.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Fuzzing|x86.Deploy.0 = Debug|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|Any CPU.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|Any CPU.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM.ActiveCfg = Release|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM.Build.0 = Release|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM.Deploy.0 = Release|ARM
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM64.ActiveCfg = Release|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM64.Build.0 = Release|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|ARM64.Deploy.0 = Release|ARM64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x64Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x64Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x64Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x86Test.ActiveCfg = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x86Test.Build.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|DotNet_x86Test.Deploy.0 = Release|Any CPU
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x64.ActiveCfg = Release|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x64.Build.0 = Release|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x64.Deploy.0 = Release|x64
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x86.ActiveCfg = Release|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x86.Build.0 = Release|x86
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE}.Release|x86.Deploy.0 = Release|x86
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|x64.ActiveCfg = AuditMode|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|x64.Build.0 = AuditMode|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.AuditMode|x86.Build.0 = AuditMode|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|ARM.ActiveCfg = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|ARM64.Build.0 = Debug|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|x64.ActiveCfg = Debug|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|x64.Build.0 = Debug|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|x86.ActiveCfg = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Debug|x86.Build.0 = Debug|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|x64.Build.0 = Fuzzing|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|Any CPU.ActiveCfg = Release|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|ARM.ActiveCfg = Release|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|ARM64.ActiveCfg = Release|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|ARM64.Build.0 = Release|ARM64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|x64.ActiveCfg = Release|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|x64.Build.0 = Release|x64
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|x86.ActiveCfg = Release|Win32
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -3438,6 +3609,9 @@ Global
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-2021 Martin Ankerl
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.

View file

@ -0,0 +1,9 @@
### Notes for Future Maintainers
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
Please update the provenance information in that file when ingesting an updated version of the dependent library.
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
## Updates
Get updates from here: https://github.com/martinus/robin-hood-hashing

View file

@ -0,0 +1,14 @@
{
"Registrations": [
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/martinus/robin-hood-hashing",
"commitHash": "24b3f50f9532153edc23b29ae277dcccfd75a462"
}
}
}
],
"Version": 1
}

File diff suppressed because it is too large Load diff

View file

@ -17,8 +17,8 @@
// Note: will through if unable to allocate char/attribute buffers
#pragma warning(push)
#pragma warning(disable : 26447) // small_vector's constructor says it can throw but it should not given how we use it. This suppresses this error for the AuditMode build.
CharRow::CharRow(size_t rowWidth, ROW* const pParent) noexcept :
_data(rowWidth, value_type()),
CharRow::CharRow(CharRowCell* buffer, size_t rowWidth, ROW* const pParent) noexcept :
_data(buffer, rowWidth),
_pParent{ FAIL_FAST_IF_NULL(pParent) }
{
}
@ -53,38 +53,9 @@ void CharRow::Reset() noexcept
// - 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
void CharRow::Resize(CharRowCell* buffer, 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();
_data = { buffer, newSize };
}
// Routine Description:
@ -95,12 +66,16 @@ typename CharRow::const_iterator CharRow::cend() const noexcept
// - The calculated left boundary of the internal string.
size_t CharRow::MeasureLeft() const noexcept
{
const_iterator it = _data.cbegin();
while (it != _data.cend() && it->IsSpace())
const auto beg = _data.begin();
const auto end = _data.end();
auto it = beg;
while (it != end && it->IsSpace())
{
++it;
}
return it - _data.cbegin();
return it - beg;
}
// Routine Description:
@ -111,17 +86,21 @@ size_t CharRow::MeasureLeft() const noexcept
// - The calculated right boundary of the internal string.
size_t CharRow::MeasureRight() const
{
const_reverse_iterator it = _data.crbegin();
while (it != _data.crend() && it->IsSpace())
const auto beg = _data.rbegin();
const auto end = _data.rend();
auto it = beg;
while (it != end && it->IsSpace())
{
++it;
}
return _data.crend() - it;
return end - it;
}
void CharRow::ClearCell(const size_t column)
{
_data.at(column).Reset();
_data[column].Reset();
}
// Routine Description:
@ -132,7 +111,7 @@ void CharRow::ClearCell(const size_t column)
// - True if there is valid text in this row. False otherwise.
bool CharRow::ContainsText() const noexcept
{
for (const value_type& cell : _data)
for (const auto& cell : _data)
{
if (!cell.IsSpace())
{
@ -151,7 +130,7 @@ bool CharRow::ContainsText() const noexcept
// Note: will throw exception if column is out of bounds
const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
{
return _data.at(column).DbcsAttr();
return _data[column].DbcsAttr();
}
// Routine Description:
@ -163,7 +142,7 @@ const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
// Note: will throw exception if column is out of bounds
DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
{
return _data.at(column).DbcsAttr();
return _data[column].DbcsAttr();
}
// Routine Description:
@ -175,7 +154,7 @@ DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
// Note: will throw exception if column is out of bounds
void CharRow::ClearGlyph(const size_t column)
{
_data.at(column).EraseChars();
_data[column].EraseChars();
}
// Routine Description:

View file

@ -49,15 +49,12 @@ class CharRow final
public:
using glyph_type = typename wchar_t;
using value_type = typename CharRowCell;
using iterator = typename boost::container::small_vector_base<value_type>::iterator;
using const_iterator = typename boost::container::small_vector_base<value_type>::const_iterator;
using const_reverse_iterator = typename boost::container::small_vector_base<value_type>::const_reverse_iterator;
using reference = typename CharRowCellReference;
CharRow(size_t rowWidth, ROW* const pParent) noexcept;
CharRow(CharRowCell* buffer, size_t rowWidth, ROW* const pParent) noexcept;
size_t size() const noexcept;
[[nodiscard]] HRESULT Resize(const size_t newSize) noexcept;
void Resize(CharRowCell* buffer, const size_t newSize) noexcept;
size_t MeasureLeft() const noexcept;
size_t MeasureRight() const;
bool ContainsText() const noexcept;
@ -71,14 +68,46 @@ public:
const reference GlyphAt(const size_t column) const;
reference GlyphAt(const size_t column);
// iterators
iterator begin() noexcept;
const_iterator cbegin() const noexcept;
const_iterator begin() const noexcept { return cbegin(); }
auto begin() noexcept
{
// gsl::span uses strict bounds checking even in Release mode.
// While this can be useful, not even our STL is that strict.
// --> Reduce iteration overhead in Release by returning pointers.
#ifdef NDEBUG
return _data.data();
#else
return _data.begin();
#endif
}
iterator end() noexcept;
const_iterator cend() const noexcept;
const_iterator end() const noexcept { return cend(); }
auto begin() const noexcept
{
#ifdef NDEBUG
return _data.data();
#else
return _data.begin();
#endif
}
auto end() noexcept
{
#ifdef NDEBUG
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
return _data.data() + _data.size();
#else
return _data.end();
#endif
}
auto end() const noexcept
{
#ifdef NDEBUG
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
return _data.data() + _data.size();
#else
return _data.end();
#endif
}
UnicodeStorage& GetUnicodeStorage() noexcept;
const UnicodeStorage& GetUnicodeStorage() const noexcept;
@ -96,20 +125,21 @@ private:
protected:
// storage for glyph data and dbcs attributes
boost::container::small_vector<value_type, 120> _data;
gsl::span<CharRowCell> _data;
// ROW that this CharRow belongs to
ROW* _pParent;
};
template<typename InputIt1, typename InputIt2>
void OverwriteColumns(InputIt1 startChars, InputIt1 endChars, InputIt2 startAttrs, CharRow::iterator outIt)
template<typename InputIt1, typename InputIt2, typename OutputIt>
void OverwriteColumns(InputIt1 startChars, InputIt1 endChars, InputIt2 startAttrs, OutputIt outIt)
{
std::transform(startChars,
endChars,
startAttrs,
outIt,
[](const wchar_t wch, const DbcsAttribute attr) {
return CharRow::value_type{ wch, attr };
});
std::transform(
startChars,
endChars,
startAttrs,
outIt,
[](const wchar_t wch, const DbcsAttribute attr) {
return CharRow::value_type{ wch, attr };
});
}

View file

@ -33,7 +33,7 @@ void CharRowCell::Reset() noexcept
// - true if cell contains a space glyph, false otherwise
bool CharRowCell::IsSpace() const noexcept
{
return !_attr.IsGlyphStored() && _wch == UNICODE_SPACE;
return !_attr.IsGlyphStored() && (_wch == 0 || _wch == UNICODE_SPACE);
}
// Routine Description:

View file

@ -50,7 +50,7 @@ public:
friend constexpr bool operator==(const CharRowCell& a, const CharRowCell& b) noexcept;
private:
wchar_t _wch{ UNICODE_SPACE };
wchar_t _wch{};
DbcsAttribute _attr{};
};

View file

@ -5,6 +5,13 @@
#include "UnicodeStorage.hpp"
#include "CharRow.hpp"
CharRowCellReference::CharRowCellReference(CharRow& parent, const size_t index) :
_parent{ parent },
_index{ index }
{
Expects(index < parent.size());
}
// Routine Description:
// - assignment operator. will store extended glyph data in a separate storage location
// Arguments:
@ -41,7 +48,7 @@ CharRowCellReference::operator std::wstring_view() const
// - ref to the CharRowCell
CharRowCell& CharRowCellReference::_cellData()
{
return _parent._data.at(_index);
return til::at(_parent._data, _index);
}
// Routine Description:
@ -50,7 +57,7 @@ CharRowCell& CharRowCellReference::_cellData()
// - ref to the CharRowCell
const CharRowCell& CharRowCellReference::_cellData() const
{
return _parent._data.at(_index);
return til::at(_parent._data, _index);
}
// Routine Description:

View file

@ -25,11 +25,7 @@ class CharRowCellReference final
public:
using const_iterator = const wchar_t*;
CharRowCellReference(CharRow& parent, const size_t index) noexcept :
_parent{ parent },
_index{ index }
{
}
CharRowCellReference(CharRow& parent, const size_t index);
~CharRowCellReference() = default;
CharRowCellReference(const CharRowCellReference&) noexcept = default;

View file

@ -81,7 +81,7 @@ OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t f
// - 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) :
OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text) noexcept :
_mode(Mode::LooseTextOnly),
_currentView(s_GenerateView(utf16Text)),
_run(utf16Text),
@ -97,7 +97,7 @@ OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text) :
// Arguments:
// - utf16Text - UTF-16 text range
// - attribute - Color to apply over the entire range
OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute) :
OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute) noexcept :
_mode(Mode::Loose),
_currentView(s_GenerateView(utf16Text, attribute)),
_run(utf16Text),
@ -362,7 +362,7 @@ bool OutputCellIterator::_TryMoveTrailing() noexcept
// - 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)
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view) noexcept
{
return s_GenerateView(view, InvalidTextAttribute, TextAttributeBehavior::Current);
}
@ -377,8 +377,7 @@ OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view)
// - 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)
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view, const TextAttribute attr) noexcept
{
return s_GenerateView(view, attr, TextAttributeBehavior::Stored);
}
@ -394,9 +393,7 @@ OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
// - 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)
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view, const TextAttribute attr, const TextAttributeBehavior behavior) noexcept
{
const auto glyph = Utf16Parser::ParseNext(view);
DbcsAttribute dbcsAttr;

View file

@ -37,8 +37,8 @@ public:
OutputCellIterator(const TextAttribute& attr, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const std::wstring_view utf16Text);
OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute);
OutputCellIterator(const std::wstring_view utf16Text) noexcept;
OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute) noexcept;
OutputCellIterator(const gsl::span<const WORD> legacyAttributes) noexcept;
OutputCellIterator(const gsl::span<const CHAR_INFO> charInfos) noexcept;
OutputCellIterator(const gsl::span<const OutputCell> cells);
@ -100,14 +100,9 @@ private:
bool _TryMoveTrailing() noexcept;
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 std::wstring_view view) noexcept;
static OutputCellView s_GenerateView(const std::wstring_view view, const TextAttribute attr) noexcept;
static OutputCellView s_GenerateView(const std::wstring_view view, const TextAttribute attr, const TextAttributeBehavior behavior) noexcept;
static OutputCellView s_GenerateView(const wchar_t& wch) noexcept;
static OutputCellView s_GenerateViewLegacyAttr(const WORD& legacyAttr) noexcept;

View file

@ -31,7 +31,17 @@ OutputCellView::OutputCellView(const std::wstring_view view,
// TODO: GH 2681 - remove this suppression by reconciling the probably bad design of the iterators that leads to this being required.
[[gsl::suppress(26445)]] const std::wstring_view& OutputCellView::Chars() const noexcept
{
return _view;
static constexpr std::wstring_view emptyBufferCell{ L"\0", 1 };
static constexpr std::wstring_view spaceBufferCell{ L" ", 1 };
// The buffer uses virtual memory and rows might not be initialized yet.
// To us they'll appear as if they contain \0, but we don't want to pass that to the renderer.
if (_view != emptyBufferCell)
{
return _view;
}
return spaceBufferCell;
}
// Routine Description:

View file

@ -16,10 +16,9 @@
// - pParent - the text buffer that this row belongs to
// Return Value:
// - constructed object
ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) :
ROW::ROW(const SHORT rowId, CharRowCell* buffer, const unsigned short rowWidth, const TextAttribute& fillAttribute, TextBuffer* const pParent) :
_id{ rowId },
_rowWidth{ rowWidth },
_charRow{ rowWidth, this },
_charRow{ buffer, rowWidth, this },
_attrRow{ rowWidth, fillAttribute },
_lineRendition{ LineRendition::SingleWidth },
_wrapForced{ false },
@ -34,7 +33,7 @@ ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute f
// - Attr - The default attribute (color) to fill
// Return Value:
// - <none>
bool ROW::Reset(const TextAttribute Attr)
bool ROW::Reset(const TextAttribute& Attr)
{
_lineRendition = LineRendition::SingleWidth;
_wrapForced = false;
@ -52,26 +51,6 @@ bool ROW::Reset(const TextAttribute Attr)
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 unsigned short 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:

View file

@ -32,9 +32,9 @@ class TextBuffer;
class ROW final
{
public:
ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent);
ROW(const SHORT rowId, CharRowCell* buffer, const unsigned short rowWidth, const TextAttribute& fillAttribute, TextBuffer* const pParent);
size_t size() const noexcept { return _rowWidth; }
size_t size() const noexcept { return _charRow.size(); }
void SetWrapForced(const bool wrap) noexcept { _wrapForced = wrap; }
bool WasWrapForced() const noexcept { return _wrapForced; }
@ -54,8 +54,7 @@ public:
SHORT GetId() const noexcept { return _id; }
void SetId(const SHORT id) noexcept { _id = id; }
bool Reset(const TextAttribute Attr);
[[nodiscard]] HRESULT Resize(const unsigned short width);
bool Reset(const TextAttribute& Attr);
void ClearColumn(const size_t column);
std::wstring GetText() const { return _charRow.GetText(); }
@ -74,13 +73,12 @@ private:
CharRow _charRow;
ATTR_ROW _attrRow;
LineRendition _lineRendition;
TextBuffer* _pParent; // non ownership pointer
SHORT _id;
unsigned short _rowWidth;
// 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;
TextBuffer* _pParent; // non ownership pointer
};
#ifdef UNIT_TESTING

View file

@ -85,10 +85,6 @@ public:
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;

View file

@ -47,7 +47,7 @@ void UnicodeStorage::Erase(const key_type key) noexcept
// - 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::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width)
void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, SHORT width)
{
// Make a temporary map to hold all the new row positioning
std::unordered_map<key_type, mapped_type> newMap;
@ -58,18 +58,10 @@ void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const
// 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())
// If the column index is at/beyond the row width, don't bother copying it to the new map.
if (oldCoord.X >= width)
{
// 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;
}
continue;
}
// Get the row ID from the position as that's what we need to remap

View file

@ -55,7 +55,7 @@ public:
void Erase(const key_type key) noexcept;
void Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width);
void Remap(const std::unordered_map<SHORT, SHORT>& rowMap, SHORT width);
private:
std::unordered_map<key_type, mapped_type> _map;

View file

@ -31,21 +31,19 @@ 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 },
_size{},
_currentHyperlinkId{ 1 },
_currentPatternId{ 0 }
_renderTarget{ renderTarget }
{
// initialize ROWs
_charBuffer = _AllocateCharBuffer(screenBufferSize);
_storage.reserve(static_cast<size_t>(screenBufferSize.Y));
for (size_t i = 0; i < static_cast<size_t>(screenBufferSize.Y); ++i)
auto buffer = _charBuffer.get();
for (SHORT i = 0; i < screenBufferSize.Y; ++i)
{
_storage.emplace_back(static_cast<SHORT>(i), screenBufferSize.X, _currentAttributes, this);
_storage.emplace_back(i, buffer, screenBufferSize.X, _currentAttributes, this);
buffer += screenBufferSize.X;
}
_UpdateSize();
@ -83,11 +81,9 @@ UINT TextBuffer::TotalRowCount() const noexcept
// - 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.at(offsetIndex);
const size_t offsetIndex = (_firstRow + index) % _storage.size();
return _storage[offsetIndex];
}
// Routine Description:
@ -99,11 +95,9 @@ const ROW& TextBuffer::GetRowByOffset(const size_t index) const
// - reference to the requested row. Asserts if out of bounds.
ROW& TextBuffer::GetRowByOffset(const size_t index)
{
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.at(offsetIndex);
const size_t offsetIndex = (_firstRow + index) % _storage.size();
return _storage[offsetIndex];
}
// Routine Description:
@ -400,7 +394,7 @@ OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
//Return Value:
// - true if we successfully inserted the character
// - false otherwise (out of memory)
bool TextBuffer::InsertCharacter(const std::wstring_view chars,
bool TextBuffer::InsertCharacter(const std::wstring_view& chars,
const DbcsAttribute dbcsAttribute,
const TextAttribute attr)
{
@ -670,6 +664,15 @@ const Viewport TextBuffer::GetSize() const noexcept
return _size;
}
wil::unique_virtualalloc_ptr<CharRowCell> TextBuffer::_AllocateCharBuffer(const COORD size)
{
const auto dx = static_cast<size_t>(size.X);
const auto dy = static_cast<size_t>(size.Y);
const auto buffer = static_cast<CharRowCell*>(VirtualAlloc(nullptr, dx * dy * sizeof(CharRowCell), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
THROW_IF_NULL_ALLOC(buffer);
return wil::unique_virtualalloc_ptr<CharRowCell>{ buffer };
}
void TextBuffer::_UpdateSize()
{
_size = Viewport::FromDimensions({ 0, 0 }, { gsl::narrow<SHORT>(_storage.at(0).size()), gsl::narrow<SHORT>(_storage.size()) });
@ -778,7 +781,7 @@ void TextBuffer::ScrollRows(const SHORT firstRow, const SHORT size, const SHORT
// 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);
_RefreshRowIDs(_size.Width());
}
Cursor& TextBuffer::GetCursor() noexcept
@ -863,14 +866,14 @@ COORD TextBuffer::ScreenToBufferPosition(const COORD position) const
{
// Use shift right to quickly divide the X pos by 2 for double width lines.
const SHORT scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
return { position.X >> scale, position.Y };
return { gsl::narrow_cast<SHORT>(position.X >> scale), position.Y };
}
COORD TextBuffer::BufferToScreenPosition(const COORD position) const
{
// Use shift left to quickly multiply the X pos by 2 for double width lines.
const SHORT scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
return { position.X << scale, position.Y };
return { gsl::narrow_cast<SHORT>(position.X << scale), position.Y };
}
// Routine Description:
@ -896,49 +899,43 @@ void TextBuffer::Reset()
{
RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
try
auto charBuffer = _AllocateCharBuffer(newSize);
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)
{
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
for (int i = 0; i < TopRowIndex; i++)
{
_storage.emplace_back(std::move(_storage.front()));
_storage.erase(_storage.begin());
}
_SetFirstRowIndex(0);
// realloc in the Y direction
// remove rows if we're shrinking
while (_storage.size() > static_cast<size_t>(newSize.Y))
{
_storage.pop_back();
}
// add rows if we're growing
while (_storage.size() < static_cast<size_t>(newSize.Y))
{
_storage.emplace_back(static_cast<short>(_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);
// Update the cached size value
_UpdateSize();
TopRow = GetCursor().GetPosition().Y - newSize.Y + 1;
}
CATCH_RETURN();
const SHORT TopRowIndex = (GetFirstRowIndex() + TopRow) % currentSize.Y;
// rotate rows until the top row is at index 0
std::rotate(_storage.begin(), _storage.begin() + TopRowIndex, _storage.end());
_SetFirstRowIndex(0);
// realloc in the Y direction
// remove rows if we're shrinking
while (_storage.size() > static_cast<size_t>(newSize.Y))
{
_storage.pop_back();
}
// add rows if we're growing
while (_storage.size() < static_cast<size_t>(newSize.Y))
{
_storage.emplace_back(static_cast<short>(_storage.size()), nullptr, 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);
_RefreshRowWidth(charBuffer.get(), newSize.X);
// Update the cached size value
_UpdateSize();
_charBuffer = std::move(charBuffer);
return S_OK;
}
@ -961,7 +958,7 @@ UnicodeStorage& TextBuffer::GetUnicodeStorage() noexcept
// 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<SHORT> newRowWidth)
void TextBuffer::_RefreshRowIDs(SHORT width)
{
std::unordered_map<SHORT, SHORT> rowMap;
SHORT i = 0;
@ -975,17 +972,19 @@ void TextBuffer::_RefreshRowIDs(std::optional<SHORT> newRowWidth)
// 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);
_unicodeStorage.Remap(rowMap, width);
}
void TextBuffer::_RefreshRowWidth(CharRowCell* data, size_t width) noexcept
{
for (auto& it : _storage)
{
it.GetCharRow().Resize(data, width);
data += width;
}
}
void TextBuffer::_NotifyPaint(const Viewport& viewport) const
@ -1044,7 +1043,7 @@ Microsoft::Console::Render::IRenderTarget& TextBuffer::GetRenderTarget() noexcep
// - wordDelimiters: the delimiters defined as a part of the DelimiterClass::DelimiterChar
// Return Value:
// - the delimiter class for the given char
const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const
const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std::wstring_view& wordDelimiters) const
{
return GetRowByOffset(pos.Y).GetCharRow().DelimiterClassAt(pos.X, wordDelimiters);
}
@ -1060,7 +1059,7 @@ const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
// Return Value:
// - The COORD for the first character on the "word" (inclusive)
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view& wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
{
// Consider a buffer with this text in it:
// " word other "
@ -1110,7 +1109,7 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
// - wordDelimiters - what characters are we considering for the separation of words
// Return Value:
// - The COORD for the first character on the current/previous READABLE "word" (inclusive)
const COORD TextBuffer::_GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const
const COORD TextBuffer::_GetWordStartForAccessibility(const COORD target, const std::wstring_view& wordDelimiters) const
{
COORD result = target;
const auto bufferSize = GetSize();
@ -1155,7 +1154,7 @@ const COORD TextBuffer::_GetWordStartForAccessibility(const COORD target, const
// - wordDelimiters - what characters are we considering for the separation of words
// Return Value:
// - The COORD for the first character on the current word or delimiter run (stopped by the left margin)
const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const
const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std::wstring_view& wordDelimiters) const
{
COORD result = target;
const auto bufferSize = GetSize();
@ -1188,7 +1187,7 @@ const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std:
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
// Return Value:
// - The COORD for the last character on the "word" (inclusive)
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view& wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
{
// Consider a buffer with this text in it:
// " word other "
@ -1226,7 +1225,7 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
// - limit - the last "valid" position in the text buffer (to improve performance)
// Return Value:
// - The COORD for the first character of the next readable "word". If no next word, return one past the end of the buffer
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view& wordDelimiters, const COORD limit) const
{
const auto bufferSize{ GetSize() };
COORD result{ target };
@ -1276,7 +1275,7 @@ const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const st
// - wordDelimiters - what characters are we considering for the separation of words
// Return Value:
// - The COORD for the last character of the current word or delimiter run (stopped by right margin)
const COORD TextBuffer::_GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const
const COORD TextBuffer::_GetWordEndForSelection(const COORD target, const std::wstring_view& wordDelimiters) const
{
const auto bufferSize = GetSize();
@ -1359,7 +1358,7 @@ void TextBuffer::_PruneHyperlinks()
// Return Value:
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
// - pos - The COORD for the first character on the "word" (inclusive)
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional) const
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view& wordDelimiters, std::optional<til::point> limitOptional) const
{
// move to the beginning of the next word
// NOTE: _GetWordEnd...() returns the exclusive position of the "end of the word"
@ -1385,7 +1384,7 @@ bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimite
// Return Value:
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
// - pos - The COORD for the first character on the "word" (inclusive)
bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters) const
bool TextBuffer::MoveToPreviousWord(COORD& pos, const std::wstring_view& wordDelimiters) const
{
// move to the beginning of the current word
auto copy{ GetWordStart(pos, wordDelimiters, true) };
@ -1782,7 +1781,7 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
// - string containing the generated HTML
std::string TextBuffer::GenHTML(const TextAndColor& rows,
const int fontHeightPoints,
const std::wstring_view fontFaceName,
const std::wstring_view& fontFaceName,
const COLORREF backgroundColor)
{
try
@ -1845,7 +1844,7 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows,
const auto writeAccumulatedChars = [&](bool includeCurrent) {
if (col >= startOffset)
{
const auto unescapedText = ConvertToA(CP_UTF8, std::wstring_view(rows.text.at(row)).substr(startOffset, col - startOffset + includeCurrent));
const auto unescapedText = ConvertToA(CP_UTF8, rows.text.at(row).substr(startOffset, col - startOffset + includeCurrent));
for (const auto c : unescapedText)
{
switch (c)
@ -1971,7 +1970,7 @@ std::string TextBuffer::GenHTML(const TextAndColor& rows,
// - htmlTitle - value used in title tag of html header. Used to name the application
// Return Value:
// - string containing the generated RTF
std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoints, const std::wstring_view fontFaceName, const COLORREF backgroundColor)
std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoints, const std::wstring_view& fontFaceName, const COLORREF backgroundColor)
{
try
{
@ -2033,7 +2032,7 @@ std::string TextBuffer::GenRTF(const TextAndColor& rows, const int fontHeightPoi
const auto writeAccumulatedChars = [&](bool includeCurrent) {
if (col >= startOffset)
{
const auto unescapedText = ConvertToA(CP_UTF8, std::wstring_view(rows.text.at(row)).substr(startOffset, col - startOffset + includeCurrent));
const auto unescapedText = ConvertToA(CP_UTF8, rows.text.at(row).substr(startOffset, col - startOffset + includeCurrent));
for (const auto c : unescapedText)
{
switch (c)
@ -2411,9 +2410,9 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// - Adds or updates a hyperlink in our hyperlink table
// Arguments:
// - The hyperlink URI, the hyperlink id (could be new or old)
void TextBuffer::AddHyperlinkToMap(std::wstring_view uri, uint16_t id)
void TextBuffer::AddHyperlinkToMap(const std::wstring_view& uri, uint16_t id)
{
_hyperlinkMap[id] = uri;
_hyperlinkMap.emplace(id, uri);
}
// Method Description:
@ -2433,28 +2432,31 @@ std::wstring TextBuffer::GetHyperlinkUriFromId(uint16_t id) const
// - The user-defined id
// Return value:
// - The internal hyperlink ID
uint16_t TextBuffer::GetHyperlinkId(std::wstring_view uri, std::wstring_view id)
uint16_t TextBuffer::GetHyperlinkId(const std::wstring_view& uri, const std::wstring_view& id)
{
uint16_t numericId = 0;
if (id.empty())
{
// no custom id specified, return our internal count
numericId = _currentHyperlinkId;
++_currentHyperlinkId;
numericId = _currentHyperlinkId++;
}
else
{
// assign _currentHyperlinkId if the custom id does not already exist
std::wstring newId{ id };
// hash the URL and add it to the custom ID - GH#7698
newId += L"%" + std::to_wstring(std::hash<std::wstring_view>{}(uri));
const auto result = _hyperlinkCustomIdMap.emplace(newId, _currentHyperlinkId);
// We need to use both uri and id for hashing. See GH#7698
std::wstring key;
key.reserve(uri.size() + id.size());
key.append(uri);
key.append(id);
const auto result = _hyperlinkCustomIdMap.emplace(key, _currentHyperlinkId);
numericId = result.first->second;
if (result.second)
{
// the custom id did not already exist
_hyperlinkCustomIdMapReverse.insert_or_assign(_currentHyperlinkId, key);
++_currentHyperlinkId;
}
numericId = (*(result.first)).second;
}
// _currentHyperlinkId could overflow, make sure its not 0
if (_currentHyperlinkId == 0)
@ -2472,13 +2474,11 @@ uint16_t TextBuffer::GetHyperlinkId(std::wstring_view uri, std::wstring_view id)
void TextBuffer::RemoveHyperlinkFromMap(uint16_t id) noexcept
{
_hyperlinkMap.erase(id);
for (const auto& customIdPair : _hyperlinkCustomIdMap)
if (auto it = _hyperlinkCustomIdMapReverse.find(id); it != _hyperlinkCustomIdMapReverse.end())
{
if (customIdPair.second == id)
{
_hyperlinkCustomIdMap.erase(customIdPair.first);
break;
}
_hyperlinkCustomIdMap.erase(it->second);
_hyperlinkCustomIdMapReverse.erase(it);
}
}
@ -2491,12 +2491,9 @@ void TextBuffer::RemoveHyperlinkFromMap(uint16_t id) noexcept
// - The custom ID if there was one, empty string otherwise
std::wstring TextBuffer::GetCustomIdFromId(uint16_t id) const
{
for (auto customIdPair : _hyperlinkCustomIdMap)
if (auto it = _hyperlinkCustomIdMapReverse.find(id); it != _hyperlinkCustomIdMapReverse.end())
{
if (customIdPair.second == id)
{
return customIdPair.first;
}
return it->second;
}
return {};
}
@ -2510,6 +2507,7 @@ void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other)
{
_hyperlinkMap = other._hyperlinkMap;
_hyperlinkCustomIdMap = other._hyperlinkCustomIdMap;
_hyperlinkCustomIdMapReverse = other._hyperlinkCustomIdMapReverse;
_currentHyperlinkId = other._currentHyperlinkId;
}
@ -2520,7 +2518,7 @@ void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other)
// - The regex pattern
// Return value:
// - An ID that the caller should associate with the given pattern
const size_t TextBuffer::AddPatternRecognizer(const std::wstring_view regexString)
const size_t TextBuffer::AddPatternRecognizer(const std::wstring_view& regexString)
{
++_currentPatternId;
_idsAndPatterns.emplace(std::make_pair(_currentPatternId, regexString));

View file

@ -98,7 +98,7 @@ public:
const std::optional<size_t> 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 InsertCharacter(const std::wstring_view& chars, const DbcsAttribute dbcsAttribute, const TextAttribute attr);
bool IncrementCursor();
bool NewlineCursor();
@ -141,10 +141,10 @@ public:
Microsoft::Console::Render::IRenderTarget& GetRenderTarget() noexcept;
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
bool MoveToPreviousWord(COORD& pos, const std::wstring_view wordDelimiters) const;
const COORD GetWordStart(const COORD target, const std::wstring_view& wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
const COORD GetWordEnd(const COORD target, const std::wstring_view& wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
bool MoveToNextWord(COORD& pos, const std::wstring_view& wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
bool MoveToPreviousWord(COORD& pos, const std::wstring_view& wordDelimiters) const;
const til::point GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
const til::point GetGlyphEnd(const til::point pos, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
@ -153,9 +153,9 @@ public:
const std::vector<SMALL_RECT> GetTextRects(COORD start, COORD end, bool blockSelection, bool bufferCoordinates) const;
void AddHyperlinkToMap(std::wstring_view uri, uint16_t id);
void AddHyperlinkToMap(const std::wstring_view& uri, uint16_t id);
std::wstring GetHyperlinkUriFromId(uint16_t id) const;
uint16_t GetHyperlinkId(std::wstring_view uri, std::wstring_view id);
uint16_t GetHyperlinkId(const std::wstring_view& uri, const std::wstring_view& id);
void RemoveHyperlinkFromMap(uint16_t id) noexcept;
std::wstring GetCustomIdFromId(uint16_t id) const;
void CopyHyperlinkMaps(const TextBuffer& OtherBuffer);
@ -176,12 +176,12 @@ public:
static std::string GenHTML(const TextAndColor& rows,
const int fontHeightPoints,
const std::wstring_view fontFaceName,
const std::wstring_view& fontFaceName,
const COLORREF backgroundColor);
static std::string GenRTF(const TextAndColor& rows,
const int fontHeightPoints,
const std::wstring_view fontFaceName,
const std::wstring_view& fontFaceName,
const COLORREF backgroundColor);
struct PositionInformation
@ -195,60 +195,49 @@ public:
const std::optional<Microsoft::Console::Types::Viewport> lastCharacterViewport,
std::optional<std::reference_wrapper<PositionInformation>> positionInfo);
const size_t AddPatternRecognizer(const std::wstring_view regexString);
const size_t AddPatternRecognizer(const std::wstring_view& regexString);
void ClearPatternRecognizers() noexcept;
void CopyPatterns(const TextBuffer& OtherBuffer);
interval_tree::IntervalTree<til::point, size_t> GetPatterns(const size_t firstRow, const size_t lastRow) const;
private:
static wil::unique_virtualalloc_ptr<CharRowCell> _AllocateCharBuffer(const COORD size);
void _UpdateSize();
Microsoft::Console::Types::Viewport _size;
std::vector<ROW> _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;
std::unordered_map<uint16_t, std::wstring> _hyperlinkMap;
std::unordered_map<std::wstring, uint16_t> _hyperlinkCustomIdMap;
uint16_t _currentHyperlinkId;
void _RefreshRowIDs(std::optional<SHORT> newRowWidth);
Microsoft::Console::Render::IRenderTarget& _renderTarget;
void _RefreshRowIDs(SHORT width);
void _RefreshRowWidth(CharRowCell* data, size_t width) noexcept;
void _SetFirstRowIndex(const SHORT FirstRowIndex) noexcept;
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);
void _ExpandTextRow(SMALL_RECT& selectionRow) const;
const DelimiterClass _GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const;
const COORD _GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const;
const COORD _GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const;
const COORD _GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
const DelimiterClass _GetDelimiterClassAt(const COORD pos, const std::wstring_view& wordDelimiters) const;
const COORD _GetWordStartForAccessibility(const COORD target, const std::wstring_view& wordDelimiters) const;
const COORD _GetWordStartForSelection(const COORD target, const std::wstring_view& wordDelimiters) const;
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view& wordDelimiters, const COORD limit) const;
const COORD _GetWordEndForSelection(const COORD target, const std::wstring_view& wordDelimiters) const;
void _PruneHyperlinks();
Microsoft::Console::Render::IRenderTarget& _renderTarget;
wil::unique_virtualalloc_ptr<CharRowCell> _charBuffer;
std::vector<ROW> _storage;
std::unordered_map<uint16_t, std::wstring> _hyperlinkMap;
std::unordered_map<std::wstring, uint16_t> _hyperlinkCustomIdMap;
std::unordered_map<uint16_t, std::wstring> _hyperlinkCustomIdMapReverse;
std::unordered_map<size_t, std::wstring> _idsAndPatterns;
size_t _currentPatternId;
TextAttribute _currentAttributes;
UnicodeStorage _unicodeStorage;
Cursor _cursor;
Microsoft::Console::Types::Viewport _size;
uint16_t _currentHyperlinkId{ 1 };
size_t _currentPatternId{ 0 };
SHORT _firstRow{ 0 }; // indexes top row (not necessarily 0)
#ifdef UNIT_TESTING
friend class TextBufferTests;

View file

@ -28,25 +28,6 @@ static constexpr bool _IsMouseMessage(UINT uMsg)
uMsg == WM_MOUSEMOVE || uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEHWHEEL;
}
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
// See microsoft/terminal#2066 for more info.
static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */) noexcept
{
return false; // glyph is not wide.
}
static bool _EnsureStaticInitialization()
{
// use C++11 magic statics to make sure we only do this once.
static bool initialized = []() {
// *** THIS IS A SINGLETON ***
SetGlyphWidthFallback(_IsGlyphWideForceNarrowFallback);
return true;
}();
return initialized;
}
LRESULT CALLBACK HwndTerminal::HwndTerminalWndProc(
HWND hwnd,
UINT uMsg,
@ -176,8 +157,6 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
_pfnWriteCallback{ nullptr },
_multiClickTime{ 500 } // this will be overwritten by the windows system double-click time
{
_EnsureStaticInitialization();
HINSTANCE hInstance = wil::GetModuleInstanceHandle();
if (RegisterTermClass(hInstance))
@ -220,7 +199,6 @@ HRESULT HwndTerminal::Initialize()
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
RETURN_IF_FAILED(dxEngine->SetHwnd(_hwnd.get()));
RETURN_IF_FAILED(dxEngine->Enable());
_renderer->AddRenderEngine(dxEngine.get());
_UpdateFont(USER_DEFAULT_SCREEN_DPI);

View file

@ -35,25 +35,6 @@ constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(
namespace winrt::Microsoft::Terminal::Control::implementation
{
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
// See microsoft/terminal#2066 for more info.
static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */)
{
return false; // glyph is not wide.
}
static bool _EnsureStaticInitialization()
{
// use C++11 magic statics to make sure we only do this once.
static bool initialized = []() {
// *** THIS IS A SINGLETON ***
SetGlyphWidthFallback(_IsGlyphWideForceNarrowFallback);
return true;
}();
return initialized;
}
ControlCore::ControlCore(IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
_connection{ connection },
@ -61,8 +42,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
{
_EnsureStaticInitialization();
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
// Subscribe to the connection's disconnected event and call our connection closed handlers.

View file

@ -19,6 +19,7 @@
#include "ControlCore.g.h"
#include "../../renderer/base/Renderer.hpp"
#include "../../renderer/dx/DxRenderer.hpp"
#include "../../renderer/atlas/AtlasEngine.h"
#include "../../renderer/uia/UiaRenderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../buffer/out/search.h"

View file

@ -147,6 +147,7 @@
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\renderer\atlas\atlas.vcxproj" />
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj" />
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />

View file

@ -51,6 +51,10 @@
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
#include <winrt/Microsoft.Terminal.Core.h>
#include <d3d11_1.h>
#include <dxgi1_3.h>
#include <dcomp.h>
#include <windows.ui.xaml.media.dxinterop.h>
#include <TraceLoggingProvider.h>

View file

@ -37,6 +37,9 @@
<ProjectReference Include="$(OpenConsoleDir)src\terminal\parser\lib\parser.vcxproj">
<Project>{3ae13314-1939-4dfa-9c14-38ca0834050c}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\renderer\atlas\atlas.vcxproj">
<Project>{21d07cec-24b8-458f-bc34-0866833c60b6}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>

View file

@ -112,7 +112,7 @@
<SDLCheck>true</SDLCheck>
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\dep\Win32K;$(SolutionDir)\oss\boost\boost_1_73_0;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\interval_tree;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\pcg\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\dep\Win32K;$(SolutionDir)\oss\boost\boost_1_73_0;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\interval_tree;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\pcg\include;$(SolutionDir)\oss\robin-hood-hashing;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
@ -174,6 +174,11 @@
<!-- For Win32 (x86) ONLY ... we use all defaults for AMD64. No def for those. -->
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<!--
KB4103718 dropped support for x86 CPUs without SSE2 on Windows 7 in 2018.
But this only affects Pentium III and older, which I'm sure can't even run VS 2019.
-->
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '15.0'">
<VisualStudioVersion>15.0</VisualStudioVersion>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x86">
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x86">
<Configuration>Release</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|AnyCPU">
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|AnyCPU">
<Configuration>Release</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
</PropertyGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
<PropertyGroup>
<ProjectGuid>44d35904-4dc6-4eec-86f2-6e3e341c95be</ProjectGuid>
<TargetPlatformVersion>10.0.20348.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.20348.0</TargetPlatformMinVersion>
<DefaultLanguage>en-US</DefaultLanguage>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
<EntryPointProjectUniqueName>..\exe\Host.EXE.vcxproj</EntryPointProjectUniqueName>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
<PackageCertificateKeyFile>HostPackage_TemporaryKey.pfx</PackageCertificateKeyFile>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Images\Square150x150Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.scale-200.png" />
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22414.2000-preview.rs-prerelease" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\exe\Host.EXE.vcxproj" />
<ProjectReference Include="..\ShellExtension\OpenConsoleShellExt.vcxproj" />
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
IgnorableNamespaces="uap rescap uap3">
<Identity
Name="OpenConsole"
Publisher="CN=lhecker"
Version="1.0.0.0" />
<Properties>
<DisplayName>OpenConsole</DisplayName>
<PublisherDisplayName>lhecker</PublisherDisplayName>
<Logo></Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="OpenConsole"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png" Description="OpenConsole">
</uap:VisualElements>
<Extensions>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="OpenConsoleShellExt">
<com:Class Id="74cd627e-aad1-4ee4-9427-7c4db186ee59" Path="OpenConsoleShellExt\OpenConsoleShellExt.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="OpenTerminalHere" Clsid="74cd627e-aad1-4ee4-9427-7c4db186ee59" />
</desktop5:ItemType>
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="OpenTerminalHere" Clsid="74cd627e-aad1-4ee4-9427-7c4db186ee59" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View file

@ -0,0 +1,4 @@
EXPORTS
DllCanUnloadNow PRIVATE
DllGetActivationFactory PRIVATE
DllGetClassObject PRIVATE

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD}</ProjectGuid>
<ProjectName>OpenConsoleShellExt</ProjectName>
<RootNamespace>OpenConsole.ShellExtension</RootNamespace>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
<ConfigurationType>DynamicLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<!-- suppress a bunch of Windows Universal properties from cppwinrt.props -->
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="$(SolutionDir)src\cppwinrt.build.pre.props" />
<ItemGroup>
<ClInclude Include="OpenTerminalHere.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="OpenTerminalHere.cpp" />
<ClCompile Include="dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="$(ProjectName).def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<Import Project="$(SolutionDir)src\cppwinrt.build.post.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemDefinitionGroup>
<!-- Override GetPackagingOutputs to roll up our DLL.
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
-->
<PropertyGroup>
<_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true</_ContinueOnError>
<_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false</_ContinueOnError>
</PropertyGroup>
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
<CallTarget Targets="BuiltProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="_BuiltProjectOutputGroupOutput" />
</CallTarget>
<ItemGroup>
<_PackagingOutputsUnexpanded Include="%(_BuiltProjectOutputGroupOutput.FinalOutputPath)">
<TargetPath>%(_BuiltProjectOutputGroupOutput.TargetPath)</TargetPath>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<ProjectName>$(ProjectName)</ProjectName>
</_PackagingOutputsUnexpanded>
</ItemGroup>
<CallTarget Targets="DebugSymbolsProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="_DebugSymbolsProjectOutputGroupOutput" />
</CallTarget>
<ItemGroup>
<_PackagingOutputsUnexpanded Include="%(_DebugSymbolsProjectOutputGroupOutput.FinalOutputPath)">
<OutputGroup>DebugSymbolsProjectOutputGroup</OutputGroup>
<ProjectName>$(ProjectName)</ProjectName>
</_PackagingOutputsUnexpanded>
</ItemGroup>
<ItemGroup>
<PackagingOutputs Include="@(_PackagingOutputsUnexpanded)">
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
</Project>

View file

@ -0,0 +1,217 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "OpenTerminalHere.h"
#include <filesystem>
#include <wil/common.h>
#include <wil/stl.h>
#include <wil/win32_helpers.h>
#include <ShlObj_core.h>
#include <shlwapi.h>
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray, IBindCtx* /*pBindContext*/)
try
{
std::wstring path;
if (psiItemArray == nullptr)
{
path = _GetPathFromExplorer();
if (path.empty())
{
return S_FALSE;
}
}
else
{
DWORD count;
psiItemArray->GetCount(&count);
winrt::com_ptr<IShellItem> psi;
wil::unique_cotaskmem_string pszName;
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
path = std::wstring{ pszName.get() };
}
// Append a "\." to the given path, so that this will work in "C:\"
path.append(L"\\.");
std::filesystem::path applicationName{ wil::GetModuleFileNameW<std::wstring>(wil::GetModuleInstanceHandle()) };
applicationName.replace_filename(L"..\\Host.EXE\\OpenConsole.exe");
std::wstring commandLine;
commandLine.push_back(L'"');
commandLine.append(applicationName);
commandLine.append(L"\" pwsh.exe");
wil::unique_process_information _piClient;
STARTUPINFOEX siEx{ 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
applicationName.c_str(), // lpApplicationName
commandLine.data(),
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
false, // bInheritHandles
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
nullptr, // lpEnvironment
path.data(),
&siEx.StartupInfo, // lpStartupInfo
&_piClient // lpProcessInformation
));
return S_OK;
}
CATCH_RETURN()
HRESULT OpenTerminalHere::GetToolTip(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszInfoTip)
{
*ppszInfoTip = nullptr;
return E_NOTIMPL;
}
HRESULT OpenTerminalHere::GetTitle(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszName)
{
return SHStrDupW(L"Open in OpenConsole", ppszName);
}
HRESULT OpenTerminalHere::GetState(IShellItemArray* /*psiItemArray*/, BOOL /*fOkToBeSlow*/, EXPCMDSTATE* pCmdState)
{
*pCmdState = ECS_ENABLED;
return S_OK;
}
HRESULT OpenTerminalHere::GetIcon(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszIcon)
try
{
std::filesystem::path path{ wil::GetModuleFileNameW<std::wstring>(wil::GetModuleInstanceHandle()) };
path.replace_filename(L"..\\Host.EXE\\OpenConsole.exe,0");
return SHStrDupW(path.c_str(), ppszIcon);
}
CATCH_RETURN();
HRESULT OpenTerminalHere::GetFlags(EXPCMDFLAGS* pFlags)
{
*pFlags = ECF_DEFAULT;
return S_OK;
}
HRESULT OpenTerminalHere::GetCanonicalName(GUID* pguidCommandName)
{
*pguidCommandName = __uuidof(this);
return S_OK;
}
HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum)
{
*ppEnum = nullptr;
return E_NOTIMPL;
}
std::wstring OpenTerminalHere::_GetPathFromExplorer() const
{
using namespace std;
using namespace winrt;
wstring path;
HRESULT hr = NOERROR;
auto hwnd = ::GetForegroundWindow();
if (hwnd == nullptr)
{
return path;
}
TCHAR szName[MAX_PATH] = { 0 };
::GetClassName(hwnd, szName, MAX_PATH);
if (0 == StrCmp(szName, L"WorkerW") ||
0 == StrCmp(szName, L"Progman"))
{
//special folder: desktop
hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
if (FAILED(hr))
{
return path;
}
path = szName;
return path;
}
if (0 != StrCmp(szName, L"CabinetWClass"))
{
return path;
}
com_ptr<IShellWindows> shell;
try
{
shell = create_instance<IShellWindows>(CLSID_ShellWindows, CLSCTX_ALL);
}
catch (...)
{
//look like try_create_instance is not available no more
}
if (shell == nullptr)
{
return path;
}
com_ptr<IDispatch> disp;
wil::unique_variant variant;
variant.vt = VT_I4;
com_ptr<IWebBrowserApp> browser;
// look for correct explorer window
for (variant.intVal = 0;
shell->Item(variant, disp.put()) == S_OK;
variant.intVal++)
{
com_ptr<IWebBrowserApp> tmp;
if (FAILED(disp->QueryInterface(tmp.put())))
{
disp = nullptr; // get rid of DEBUG non-nullptr warning
continue;
}
HWND tmpHWND = NULL;
hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
if (hwnd == tmpHWND)
{
browser = tmp;
disp = nullptr; // get rid of DEBUG non-nullptr warning
break; //found
}
disp = nullptr; // get rid of DEBUG non-nullptr warning
}
if (browser)
{
wil::unique_bstr url;
hr = browser->get_LocationURL(&url);
if (FAILED(hr))
{
return path;
}
wstring sUrl(url.get(), SysStringLen(url.get()));
DWORD size = MAX_PATH;
hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
if (SUCCEEDED(hr))
{
path = szName;
}
}
return path;
}

View file

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <string>
#include <wrl.h>
#include <ShlObj.h>
using namespace Microsoft::WRL;
struct __declspec(uuid("74cd627e-aad1-4ee4-9427-7c4db186ee59")) OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand>
{
#pragma region IExplorerCommand
STDMETHODIMP Invoke(IShellItemArray* psiItemArray, IBindCtx* pBindContext);
STDMETHODIMP GetToolTip(IShellItemArray* psiItemArray, LPWSTR* ppszInfoTip);
STDMETHODIMP GetTitle(IShellItemArray* psiItemArray, LPWSTR* ppszName);
STDMETHODIMP GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState);
STDMETHODIMP GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon);
STDMETHODIMP GetFlags(EXPCMDFLAGS* pFlags);
STDMETHODIMP GetCanonicalName(GUID* pguidCommandName);
STDMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum);
#pragma endregion
private:
std::wstring _GetPathFromExplorer() const;
};
CoCreatableClass(OpenTerminalHere);

View file

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include <wrl/module.h>
using namespace Microsoft::WRL;
__control_entrypoint(DllExport) STDAPI DllCanUnloadNow()
{
return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
}
STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory)
{
return Module<InProc>::GetModule().GetActivationFactory(activatableClassId, factory);
}
_Check_return_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv)
{
return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
}
STDAPI_(BOOL)
DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*)
{
if (reason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hinst);
}
return TRUE;
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View file

@ -46,6 +46,9 @@
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\gdi\lib\gdi.vcxproj">
<Project>{1c959542-bac2-4e55-9a6d-13251914cbb9}</Project>
</ProjectReference>

View file

@ -274,8 +274,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
const FontInfo& fontInfo = activeScreenInfo.GetCurrentFont();
consoleFontInfoEx.FontFamily = fontInfo.GetFamily();
consoleFontInfoEx.FontWeight = fontInfo.GetWeight();
RETURN_IF_FAILED(fontInfo.FillLegacyNameBuffer(gsl::make_span(consoleFontInfoEx.FaceName)));
fontInfo.FillLegacyNameBuffer(consoleFontInfoEx.FaceName);
return S_OK;
}

View file

@ -22,10 +22,7 @@ Revision History:
#include "ConsoleArguments.hpp"
#include "ApiRoutines.h"
#include "../renderer/inc/IRenderData.hpp"
#include "../renderer/inc/IRenderEngine.hpp"
#include "../renderer/inc/IRenderer.hpp"
#include "../renderer/inc/IFontDefaultList.hpp"
#include "../renderer/base/Renderer.hpp"
#include "../server/DeviceComm.h"
#include "../server/ConDrvDeviceComm.h"
@ -62,7 +59,7 @@ public:
std::vector<wchar_t> WordDelimiters;
Microsoft::Console::Render::IRenderer* pRender;
Microsoft::Console::Render::Renderer* pRender;
Microsoft::Console::Render::IFontDefaultList* pFontDefaultList;

View file

@ -58,7 +58,7 @@ Settings::Settings() :
_fInterceptCopyPaste(0),
_DefaultForeground(INVALID_COLOR),
_DefaultBackground(INVALID_COLOR),
_fUseDx(false),
_fUseDx(0),
_fCopyColor(false)
{
_dwScreenBufferSize.X = 80;
@ -816,7 +816,7 @@ void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcep
// - This is based on user preference and velocity hold back state.
// Return Value:
// - True means use DirectX renderer. False means use GDI renderer.
bool Settings::GetUseDx() const noexcept
DWORD Settings::GetUseDx() const noexcept
{
return _fUseDx;
}

View file

@ -186,7 +186,7 @@ public:
bool IsTerminalScrolling() const noexcept;
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;
bool GetUseDx() const noexcept;
DWORD GetUseDx() const noexcept;
bool GetCopyColor() const noexcept;
private:
@ -230,7 +230,7 @@ private:
bool _fAutoReturnOnNewline;
bool _fRenderGridWorldwide;
bool _fScreenReversed;
bool _fUseDx;
DWORD _fUseDx;
bool _fCopyColor;
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;

View file

@ -771,8 +771,9 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand,
// Set up the renderer to be used to calculate the width of a glyph,
// should we be unable to figure out its width another way.
auto pfn = std::bind(&Renderer::IsGlyphWideByFont, static_cast<Renderer*>(g.pRender), std::placeholders::_1);
SetGlyphWidthFallback(pfn);
SetGlyphWidthFallback([renderer = g.pRender](const std::wstring_view& glyph) -> bool {
return renderer->IsGlyphWideByFont(glyph);
});
}
catch (...)
{

View file

@ -62,7 +62,7 @@ class CodepointWidthDetectorTests
}
}
static bool FallbackMethod(const std::wstring_view glyph)
static bool FallbackMethod(const std::wstring_view& glyph)
{
if (glyph.size() < 1)
{

View file

@ -73,7 +73,8 @@
// Chromium Numerics (safe math)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced parameter
#pragma warning(disable : 4100) // '...': unreferenced formal parameter
#pragma warning(disable : 26812) // The enum type '...' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#include <base/numerics/safe_math.h>
#pragma warning(pop)
@ -84,16 +85,15 @@
#define ENABLE_INTSAFE_SIGNED_FUNCTIONS
#include <intsafe.h>
// LibPopCnt - Fast C/C++ bit population count library (on bits in an array)
#include <libpopcnt.h>
// Dynamic Bitset (optional dependency on LibPopCnt for perf at bit counting)
// Variable-size compressed-storage header-only bit flag storage library.
#pragma warning(push)
#pragma warning(disable:4702) // unreachable code
#pragma warning(disable : 4702) // unreachable code
#include <dynamic_bitset.hpp>
#pragma warning(pop)
#include <robin_hood.h>
// {fmt}, a C++20-compatible formatting library
#include <fmt/format.h>
#include <fmt/compile.h>

View file

@ -15,11 +15,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
class _bitmap_const_iterator
{
public:
using iterator_category = typename std::input_iterator_tag;
using value_type = typename const til::rectangle;
using difference_type = typename ptrdiff_t;
using pointer = typename const til::rectangle*;
using reference = typename const til::rectangle&;
using iterator_category = std::input_iterator_tag;
using value_type = const til::rectangle;
using difference_type = ptrdiff_t;
using pointer = const til::rectangle*;
using reference = const til::rectangle&;
_bitmap_const_iterator(const dynamic_bitset<unsigned long long, Allocator>& values, til::rectangle rc, ptrdiff_t pos) :
_values(values),

60
src/inc/til/pair.h Normal file
View file

@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
// pair is a simple clone of std::pair, with one difference:
// copy and move constructors and operators are explicitly defaulted.
// This allows pair to be std::is_trivially_copyable, if both T and S are.
// --> pair can be used with memcpy(), unlike std::pair.
template<typename T, typename S>
struct pair
{
using first_type = T;
using second_type = S;
pair() = default;
pair(const pair&) = default;
pair& operator=(const pair&) = default;
pair(pair&&) = default;
pair& operator=(pair&&) = default;
constexpr pair(const T& first, const S& second) noexcept(std::is_nothrow_copy_constructible_v<T>&& std::is_nothrow_copy_constructible_v<S>) :
first(first), second(second)
{
}
constexpr pair(T&& first, S&& second) noexcept(std::is_nothrow_constructible_v<T>&& std::is_nothrow_constructible_v<S>) :
first(std::forward<T>(first)), second(std::forward<S>(second))
{
}
constexpr void swap(pair& other) noexcept(std::is_nothrow_swappable_v<T>&& std::is_nothrow_swappable_v<S>)
{
if (this != std::addressof(other))
{
std::swap(first, other.first);
std::swap(second, other.second);
}
}
first_type first{};
second_type second{};
};
template<typename T, typename S>
[[nodiscard]] constexpr bool operator==(const pair<T, S>& lhs, const pair<T, S>& rhs)
{
return lhs.first == rhs.first && lhs.second == rhs.second;
}
template<typename T, typename S>
[[nodiscard]] constexpr bool operator!=(const pair<T, S>& lhs, const pair<T, S>& rhs)
{
return !(lhs == rhs);
}
};

View file

@ -253,12 +253,6 @@ BgfxEngine::BgfxEngine(PVOID SharedViewBase, LONG DisplayHeight, LONG DisplayWid
return S_OK;
}
[[nodiscard]] HRESULT BgfxEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const pResult) noexcept
{
*pResult = false;
return S_OK;
}
// Method Description:
// - Updates the window's title string.
// Does nothing for BGFX.

View file

@ -70,7 +70,6 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override;

View file

@ -30,6 +30,7 @@
#include "../../renderer/gdi/gdirenderer.hpp"
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
#include "../../renderer/atlas/AtlasEngine.h"
#include "../../renderer/dx/DxRenderer.hpp"
#endif
@ -209,16 +210,18 @@ void Window::_UpdateSystemMetrics() const
// Ensure we have appropriate system metrics before we start constructing the window.
_UpdateSystemMetrics();
const bool useDx = pSettings->GetUseDx();
const auto useDx = pSettings->GetUseDx();
GdiEngine* pGdiEngine = nullptr;
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
[[maybe_unused]] DxEngine* pDxEngine = nullptr;
DxEngine* pDxEngine = nullptr;
AtlasEngine* pAtlasEngine = nullptr;
#endif
try
{
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
if (useDx)
switch (useDx)
{
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
case 1:
pDxEngine = new DxEngine();
// TODO: MSFT:21255595 make this less gross
// Manually set the Dx Engine to Hwnd mode. When we're trying to
@ -227,12 +230,16 @@ void Window::_UpdateSystemMetrics() const
// math in the hwnd mode, not the Composition mode.
THROW_IF_FAILED(pDxEngine->SetHwnd(nullptr));
g.pRender->AddRenderEngine(pDxEngine);
}
else
break;
case 2:
pAtlasEngine = new AtlasEngine();
g.pRender->AddRenderEngine(pAtlasEngine);
break;
#endif
{
default:
pGdiEngine = new GdiEngine();
g.pRender->AddRenderEngine(pGdiEngine);
break;
}
}
catch (...)
@ -242,10 +249,6 @@ void Window::_UpdateSystemMetrics() const
if (NT_SUCCESS(status))
{
SCREEN_INFORMATION& siAttached = GetScreenInfo();
siAttached.RefreshFontWithRenderer();
// Save reference to settings
_pSettings = pSettings;
@ -324,7 +327,7 @@ void Window::_UpdateSystemMetrics() const
_hWnd = hWnd;
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
if (useDx)
if (pDxEngine)
{
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->SetHwnd(hWnd))));
@ -333,6 +336,10 @@ void Window::_UpdateSystemMetrics() const
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->Enable())));
}
}
else if (pAtlasEngine)
{
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pAtlasEngine->SetHwnd(hWnd))));
}
else
#endif
{
@ -362,6 +369,7 @@ void Window::_UpdateSystemMetrics() const
// Post a window size update so that the new console window will size itself correctly once it's up and
// running. This works around chicken & egg cases involving window size calculations having to do with font
// sizes, DPI, and non-primary monitors (see MSFT #2367234).
SCREEN_INFORMATION& siAttached = GetScreenInfo();
siAttached.PostUpdateWindowSize();
// Locate window theming modules and try to set the dark mode.

View file

@ -28,6 +28,7 @@ USE_NATIVE_EH = 1
# Compiler Settings
# -------------------------------------
MSC_OPTIMIZATION = /O2
MSC_WARNING_LEVEL = /W4 /WX
USER_C_FLAGS = $(USER_C_FLAGS) /utf-8
@ -43,12 +44,13 @@ INCLUDES= \
$(INCLUDES); \
$(CONSOLE_SRC_PATH)\inc; \
$(CONSOLE_SRC_PATH)\..\..\inc; \
$(CONSOLE_SRC_PATH)\..\oss\dynamic_bitset; \
$(CONSOLE_SRC_PATH)\..\oss\libpopcnt; \
$(CONSOLE_SRC_PATH)\..\oss\boost\boost_1_73_0; \
$(CONSOLE_SRC_PATH)\..\oss\chromium; \
$(CONSOLE_SRC_PATH)\..\oss\dynamic_bitset; \
$(CONSOLE_SRC_PATH)\..\oss\fmt\include; \
$(CONSOLE_SRC_PATH)\..\oss\interval_tree; \
$(CONSOLE_SRC_PATH)\..\oss\boost\boost_1_73_0; \
$(CONSOLE_SRC_PATH)\..\oss\libpopcnt; \
$(CONSOLE_SRC_PATH)\..\oss\robin-hood-hashing; \
$(MINWIN_INTERNAL_PRIV_SDK_INC_PATH_L); \
$(MINWIN_RESTRICTED_PRIV_SDK_INC_PATH_L); \
$(MINCORE_INTERNAL_PRIV_SDK_INC_PATH_L); \

View file

@ -188,12 +188,13 @@ DWORD GetRegistryValues(
if (pStateInfo == nullptr)
{
Status = RegistrySerialization::s_QueryValue(hConsoleKey,
CONSOLE_REGISTRY_CURRENTPAGE,
sizeof(dwValue),
REG_DWORD,
(PBYTE)&dwValue,
nullptr);
Status = RegistrySerialization::s_QueryValue(
hConsoleKey,
CONSOLE_REGISTRY_CURRENTPAGE,
sizeof(dwValue),
REG_DWORD,
(PBYTE)&dwValue,
nullptr);
if (NT_SUCCESS(Status))
{
dwRet = dwValue;
@ -211,9 +212,10 @@ DWORD GetRegistryValues(
}
else
{
Status = RegistrySerialization::s_OpenKey(hConsoleKey,
pStateInfo->OriginalTitle,
&hTitleKey);
Status = RegistrySerialization::s_OpenKey(
hConsoleKey,
pStateInfo->OriginalTitle,
&hTitleKey);
if (!NT_SUCCESS(Status))
{
RegCloseKey(hConsoleKey);
@ -701,11 +703,12 @@ VOID SetRegistryValues(
//
// Save the current page.
//
LOG_IF_FAILED(RegistrySerialization::s_SetValue(hConsoleKey,
CONSOLE_REGISTRY_CURRENTPAGE,
REG_DWORD,
(BYTE*)&dwPage,
sizeof(dwPage)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(
hConsoleKey,
CONSOLE_REGISTRY_CURRENTPAGE,
REG_DWORD,
(BYTE*)&dwPage,
sizeof(dwPage)));
//
// Open the console title subkey unless we're changing the defaults.
@ -716,9 +719,10 @@ VOID SetRegistryValues(
}
else
{
Status = RegistrySerialization::s_CreateKey(hConsoleKey,
pStateInfo->OriginalTitle,
&hTitleKey);
Status = RegistrySerialization::s_CreateKey(
hConsoleKey,
pStateInfo->OriginalTitle,
&hTitleKey);
if (!NT_SUCCESS(Status))
{
RegCloseKey(hConsoleKey);
@ -732,30 +736,33 @@ VOID SetRegistryValues(
//
dwValue = pStateInfo->ScreenAttributes;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FILLATTR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FILLATTR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->PopupAttributes;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_POPUPATTR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_POPUPATTR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
for (i = 0; i < 16; i++)
{
dwValue = pStateInfo->ColorTable[i];
if (SUCCEEDED(StringCchPrintf(awchBuffer, ARRAYSIZE(awchBuffer), CONSOLE_REGISTRY_COLORTABLE, i)))
{
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
awchBuffer,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
awchBuffer,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
}
}
@ -764,30 +771,33 @@ VOID SetRegistryValues(
//
dwValue = pStateInfo->InsertMode;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_INSERTMODE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_INSERTMODE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->QuickEdit;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_QUICKEDIT,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_QUICKEDIT,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
FAIL_FAST_IF(!(OEMCP != 0));
if (g_fEastAsianSystem)
{
dwValue = (DWORD)pStateInfo->CodePage;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CODEPAGE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CODEPAGE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
}
//
@ -796,12 +806,13 @@ VOID SetRegistryValues(
dwValue = MAKELONG(pStateInfo->ScreenBufferSize.X,
pStateInfo->ScreenBufferSize.Y);
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_BUFFERSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_BUFFERSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
//
// Save window size
@ -809,12 +820,13 @@ VOID SetRegistryValues(
dwValue = MAKELONG(pStateInfo->WindowSize.X,
pStateInfo->WindowSize.Y);
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
//
// Save window position
@ -822,18 +834,19 @@ VOID SetRegistryValues(
if (pStateInfo->AutoPosition)
{
LOG_IF_FAILED(RegistrySerialization::s_DeleteValue(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_DeleteValue(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS));
}
else
{
dwValue = MAKELONG(pStateInfo->WindowPosX,
pStateInfo->WindowPosY);
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWPOS,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWPOS,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
}
//
@ -842,107 +855,120 @@ VOID SetRegistryValues(
dwValue = MAKELONG(pStateInfo->FontSize.X,
pStateInfo->FontSize.Y);
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->FontFamily;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTFAMILY,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTFAMILY,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->FontWeight;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTWEIGHT,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FACENAME,
REG_SZ,
(BYTE*)(pStateInfo->FaceName),
(DWORD)(wcslen(pStateInfo->FaceName) + 1) * sizeof(TCHAR)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FONTWEIGHT,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FACENAME,
REG_SZ,
(BYTE*)(pStateInfo->FaceName),
(DWORD)(wcslen(pStateInfo->FaceName) + 1) * sizeof(TCHAR)));
//
// Save cursor size
//
dwValue = pStateInfo->CursorSize;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
//
// Save history buffer size and number
//
dwValue = pStateInfo->HistoryBufferSize;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYSIZE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->NumberOfHistoryBuffers;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYBUFS,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYBUFS,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->HistoryNoDup;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYNODUP,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_HISTORYNODUP,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
// Save per-title V2 console state
dwValue = pStateInfo->fWrapText;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_LINEWRAP,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_LINEWRAP,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->fFilterOnPaste;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FILTERONPASTE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_FILTERONPASTE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->fCtrlKeyShortcutsDisabled;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CTRLKEYSHORTCUTS_DISABLED,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CTRLKEYSHORTCUTS_DISABLED,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->fLineSelection;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_LINESELECTION,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_LINESELECTION,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->bWindowTransparency;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWALPHA,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_WINDOWALPHA,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
SetGlobalRegistryValues();
@ -954,50 +980,56 @@ VOID SetRegistryValues(
{
// Save cursor type and color
dwValue = pStateInfo->CursorType;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORTYPE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORTYPE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->CursorColor;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORCOLOR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_CURSORCOLOR,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->InterceptCopyPaste;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_INTERCEPTCOPYPASTE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_INTERCEPTCOPYPASTE,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->TerminalScrolling;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_TERMINALSCROLLING,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_TERMINALSCROLLING,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->DefaultForeground;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_DEFAULTFOREGROUND,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_DEFAULTFOREGROUND,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
dwValue = pStateInfo->DefaultBackground;
LOG_IF_FAILED(RegistrySerialization::s_UpdateValue(hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_DEFAULTBACKGROUND,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
LOG_IF_NTSTATUS_FAILED(RegistrySerialization::s_UpdateValue(
hConsoleKey,
hTitleKey,
CONSOLE_REGISTRY_DEFAULTBACKGROUND,
REG_DWORD,
(BYTE*)&dwValue,
sizeof(dwValue)));
}
//

View file

@ -63,7 +63,7 @@ const RegistrySerialization::_RegPropertyMap RegistrySerialization::s_PropertyMa
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_DefaultForeground) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_DefaultBackground) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) }
};
@ -251,7 +251,8 @@ NTSTATUS RegistrySerialization::s_OpenKey(_In_opt_ HKEY const hKey, _In_ PCWSTR
[[nodiscard]]
NTSTATUS RegistrySerialization::s_DeleteValue(const HKEY hKey, _In_ PCWSTR const pwszValueName)
{
return NTSTATUS_FROM_WIN32(RegDeleteKeyValueW(hKey, nullptr, pwszValueName));
const auto result = RegDeleteKeyValueW(hKey, nullptr, pwszValueName);
return result == ERROR_FILE_NOT_FOUND ? S_OK : NTSTATUS_FROM_WIN32(result);
}
// Routine Description:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,344 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <d2d1.h>
#include <d3d11_1.h>
#include <dwrite.h>
#include <dxgi.h>
#include <robin_hood.h>
#include <til/pair.h>
#include "../../renderer/inc/IRenderEngine.hpp"
namespace Microsoft::Console::Render
{
class AtlasEngine final : public IRenderEngine
{
public:
explicit AtlasEngine();
AtlasEngine(const AtlasEngine&) = delete;
AtlasEngine& operator=(const AtlasEngine&) = delete;
// IRenderEngine
[[nodiscard]] HRESULT StartPaint() noexcept override;
[[nodiscard]] HRESULT EndPaint() noexcept override;
[[nodiscard]] bool RequiresContinuousRedraw() noexcept override;
void WaitUntilCanRender() noexcept override;
[[nodiscard]] HRESULT Present() noexcept override;
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override;
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
[[nodiscard]] HRESULT InvalidateTitle() noexcept override;
[[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override;
[[nodiscard]] HRESULT ResetLineTransform() noexcept override;
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition, const size_t targetRow, const size_t viewportLeft) noexcept override;
[[nodiscard]] HRESULT PaintBackground() noexcept override;
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLines lines, const COLORREF color, const size_t cchLine, const COORD coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept override;
[[nodiscard]] HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const SIZE cellSize, const size_t centeringHint) noexcept override;
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
[[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override;
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept override;
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept override;
[[nodiscard]] HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept override;
// Just for compatibility with DxEngine, but can be removed at some point.
HRESULT Enable()
{
return S_OK;
}
// DxRenderer - getter
[[nodiscard]] bool GetRetroTerminalEffect() const noexcept;
[[nodiscard]] float GetScaling() const noexcept;
[[nodiscard]] HANDLE GetSwapChainHandle();
[[nodiscard]] ::Microsoft::Console::Types::Viewport GetViewportInCharacters(const ::Microsoft::Console::Types::Viewport& viewInPixels) const noexcept;
[[nodiscard]] ::Microsoft::Console::Types::Viewport GetViewportInPixels(const ::Microsoft::Console::Types::Viewport& viewInCharacters) const noexcept;
// DxRenderer - setter
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept;
void SetCallback(std::function<void()> pfn);
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept;
void SetForceFullRepaintRendering(bool enable) noexcept;
[[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept;
void SetPixelShaderPath(std::wstring_view value) noexcept;
void SetRetroTerminalEffect(bool enable) noexcept;
void SetSelectionBackground(const COLORREF color, const float alpha = 0.5f) noexcept;
void SetSoftwareRendering(bool enable) noexcept;
void SetWarningCallback(std::function<void(const HRESULT)> pfn);
[[nodiscard]] HRESULT SetWindowSize(const SIZE pixels) noexcept;
void ToggleShaderEffects();
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept;
void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept;
// Some helper classes for the implementation.
// public because I don't want to sprinkle the code with friends.
public:
template<typename T>
struct aligned_buffer
{
constexpr aligned_buffer() noexcept = default;
explicit aligned_buffer(size_t size, size_t alignment) :
_data{ THROW_IF_NULL_ALLOC(static_cast<T*>(_aligned_malloc(size * sizeof(T), alignment))) },
_size{ size }
{
}
~aligned_buffer()
{
_aligned_free(_data);
}
aligned_buffer(aligned_buffer&& other) noexcept :
_data{ std::exchange(other._data, nullptr) },
_size{ std::exchange(other._size, 0) }
{
}
aligned_buffer& operator=(aligned_buffer&& other) noexcept
{
_aligned_free(_data);
_data = std::exchange(other._data, nullptr);
_size = std::exchange(other._size, 0);
return *this;
}
T* data()
{
return _data;
}
size_t size()
{
return _size;
}
private:
T* _data = nullptr;
size_t _size = 0;
};
template<typename T>
struct vec2
{
T x{};
T y{};
bool operator==(const vec2& other) const noexcept
{
return memcmp(this, &other, sizeof(vec2)) == 0;
}
bool operator!=(const vec2& other) const noexcept
{
return memcmp(this, &other, sizeof(vec2)) != 0;
}
vec2 operator*(const vec2& other) const noexcept
{
return { static_cast<T>(x * other.x), static_cast<T>(y * other.y) };
}
vec2 operator/(const vec2& other) const noexcept
{
return { static_cast<T>(x / other.x), static_cast<T>(y / other.y) };
}
template<typename U = T>
U area() const noexcept
{
return static_cast<U>(x) * static_cast<U>(y);
}
};
template<typename T>
struct vec4
{
T x{};
T y{};
T z{};
T w{};
};
using u8 = uint8_t;
using u16 = uint16_t;
using u16x2 = vec2<u16>;
using u32 = uint32_t;
using u32x2 = vec2<u32>;
using f32 = float;
using f32x2 = vec2<f32>;
using f32x4 = vec4<f32>;
union glyph_entry
{
uint32_t value;
struct
{
uint32_t codepoint : 20;
uint32_t wide : 1;
uint32_t bold : 1;
uint32_t italic : 1;
};
constexpr bool operator==(const glyph_entry& other) const noexcept
{
return value == other.value;
}
};
struct glyph_entry_hasher
{
constexpr size_t operator()(glyph_entry entry) const noexcept
{
uint64_t x = entry.value;
x ^= x >> 33;
x *= UINT64_C(0xff51afd7ed558ccd);
x ^= x >> 33;
return static_cast<size_t>(x);
}
};
private:
// D3D constant buffers sizes must be a multiple of 16 bytes.
struct alignas(16) const_buffer
{
f32x4 viewport;
u32x2 cellSize;
u32 cellCountX;
u32 backgroundColor;
u32 selectionColor;
#pragma warning(suppress : 4324) // structure was padded due to alignment specifier
};
struct cell
{
union
{
u32 glyphIndex;
u16x2 glyphIndex16;
};
u32 flags;
u32x2 color;
};
enum class invalidation_flags : u8
{
none = 0,
device = 1 << 0,
size = 1 << 1,
font = 1 << 2,
cbuffer = 1 << 3,
title = 1 << 4,
};
friend constexpr invalidation_flags operator~(invalidation_flags v) noexcept { return static_cast<invalidation_flags>(~static_cast<u8>(v)); }
friend constexpr invalidation_flags operator|(invalidation_flags lhs, invalidation_flags rhs) noexcept { return static_cast<invalidation_flags>(static_cast<u8>(lhs) | static_cast<u8>(rhs)); }
friend constexpr invalidation_flags operator&(invalidation_flags lhs, invalidation_flags rhs) noexcept { return static_cast<invalidation_flags>(static_cast<u8>(lhs) & static_cast<u8>(rhs)); }
friend constexpr void operator|=(invalidation_flags& lhs, invalidation_flags rhs) noexcept { lhs = lhs | rhs; }
friend constexpr void operator&=(invalidation_flags& lhs, invalidation_flags rhs) noexcept { lhs = lhs & rhs; }
// resource handling
[[nodiscard]] HRESULT _handleException(const wil::ResultException& exception) noexcept;
__declspec(noinline) void _createResources();
__declspec(noinline) void _recreateSizeDependentResources();
__declspec(noinline) void _recreateFontDependentResources();
void _setShaderResources() const;
void _updateConstantBuffer() const;
// text handling
IDWriteTextFormat* _getTextFormat(bool bold, bool italic) const noexcept { return _r.textFormats[italic][bold].get(); }
wil::com_ptr<IDWriteTextFormat> _createTextFormat(const wchar_t* fontFamilyName, DWRITE_FONT_WEIGHT fontWeight, DWRITE_FONT_STYLE fontStyle, float fontSize, const wchar_t* localeName) const;
u16x2 _allocateAtlasCell() noexcept;
void _drawGlyph(const til::pair<glyph_entry, std::array<u16x2, 2>>& pair) const;
void _drawCursor() const;
void _copyScratchpadCell(uint32_t scratchpadIndex, u16x2 target, uint32_t copyFlags = 0) const;
template<typename T1, typename T2>
cell* _getCell(T1 x, T2 y) noexcept
{
return _r.cells.data() + static_cast<size_t>(_api.cellCount.x) * y + x;
}
struct static_resources
{
wil::com_ptr<ID2D1Factory> d2dFactory;
wil::com_ptr<IDWriteFactory> dwriteFactory;
bool isWindows10OrGreater = true;
} _sr;
struct resources
{
// D3D resources
wil::com_ptr<ID3D11Device> device;
wil::com_ptr<ID3D11DeviceContext1> deviceContext;
wil::com_ptr<IDXGISwapChain1> swapChain;
wil::unique_handle swapChainHandle;
wil::unique_handle frameLatencyWaitableObject;
wil::com_ptr<ID3D11RenderTargetView> renderTargetView;
wil::com_ptr<ID3D11VertexShader> vertexShader;
wil::com_ptr<ID3D11PixelShader> pixelShader;
wil::com_ptr<ID3D11Buffer> constantBuffer;
wil::com_ptr<ID3D11Buffer> cellBuffer;
wil::com_ptr<ID3D11ShaderResourceView> cellView;
// D2D resources
wil::com_ptr<ID3D11Texture2D> glyphBuffer;
wil::com_ptr<ID3D11ShaderResourceView> glyphView;
wil::com_ptr<ID3D11Texture2D> glyphScratchpad;
wil::com_ptr<ID2D1RenderTarget> d2dRenderTarget;
wil::com_ptr<ID2D1Brush> brush;
wil::com_ptr<IDWriteTextFormat> textFormats[2][2];
// Resources dependent on _api.sizeInPixel
aligned_buffer<cell> cells;
// Resources dependent on _api.cellSize
robin_hood::unordered_flat_map<glyph_entry, std::array<u16x2, 2>, glyph_entry_hasher> glyphs;
std::vector<til::pair<glyph_entry, std::array<u16x2, 2>>> glyphQueue;
u16x2 atlasSizeInPixel;
u16x2 atlasPosition;
} _r;
struct api_state
{
f32x2 cellSizeDIP; // invalidation_flags::font
u16x2 cellSize; // invalidation_flags::size
u16x2 cellCount; // caches `sizeInPixel / cellSize`
u16x2 sizeInPixel; // invalidation_flags::size
std::wstring fontName; // invalidation_flags::font|size
u16 fontSize = 0; // invalidation_flags::font|size
u16 fontWeight = DWRITE_FONT_WEIGHT_NORMAL; // invalidation_flags::font
u16 dpi = USER_DEFAULT_SCREEN_DPI; // invalidation_flags::font|size
u16 antialiasingMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; // invalidation_flags::font
std::function<void()> swapChainChangedCallback;
HWND hwnd = nullptr;
} _api;
struct render_api_state
{
til::rectangle dirtyArea;
u32x2 currentColor{};
glyph_entry attributes{};
u32 backgroundColor = ~u32(0);
u32 selectionColor = 0x7fffffff;
} _rapi;
invalidation_flags _invalidations = invalidation_flags::device;
};
}

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>atlas</RootNamespace>
<ProjectName>RendererAtlas</ProjectName>
<TargetName>ConRenderAtlas</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="AtlasEngine.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="AtlasEngine.h" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="shader_ps.hlsl">
<ShaderType>Pixel</ShaderType>
<ShaderModel>4.1</ShaderModel>
<VariableName>shader_ps</VariableName>
<ObjectFileOutput />
<HeaderFileOutput>$(OutDir)$(ProjectName)\%(Filename).h</HeaderFileOutput>
<TreatWarningAsError>true</TreatWarningAsError>
<AdditionalOptions Condition="'$(Configuration)'=='Release'">/Qstrip_debug /Qstrip_reflect %(AdditionalOptions)</AdditionalOptions>
</FxCompile>
<FxCompile Include="shader_vs.hlsl">
<ShaderType>Vertex</ShaderType>
<ShaderModel>4.1</ShaderModel>
<VariableName>shader_vs</VariableName>
<ObjectFileOutput />
<HeaderFileOutput>$(OutDir)$(ProjectName)\%(Filename).h</HeaderFileOutput>
<TreatWarningAsError>true</TreatWarningAsError>
<AdditionalOptions Condition="'$(Configuration)'=='Release'">/Qstrip_debug /Qstrip_reflect %(AdditionalOptions)</AdditionalOptions>
</FxCompile>
</ItemGroup>
<Import Project="$(SolutionDir)src\common.build.post.props" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(OutDir)$(ProjectName)\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View file

@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

50
src/renderer/atlas/pch.h Normal file
View file

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <array>
#include <iomanip>
#include <optional>
#include <sstream>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <d2d1.h>
#include <d3d11_1.h>
#include <dwrite.h>
#include <dxgi1_3.h>
#include <dxgidebug.h>
#include <VersionHelpers.h>
#include <gsl/pointers>
#include <gsl/span>
#include <gsl/gsl_util>
#include <wil/com.h>
#include <wil/result_macros.h>
#include <wil/stl.h>
#include <wil/win32_helpers.h>
#include <robin_hood.h>
// Dynamic Bitset (optional dependency on LibPopCnt for perf at bit counting)
// Variable-size compressed-storage header-only bit flag storage library.
#pragma warning(push)
#pragma warning(disable : 4702) // unreachable code
#include <dynamic_bitset.hpp>
#pragma warning(pop)
// Chromium Numerics (safe math)
#pragma warning(push)
#pragma warning(disable : 4100) // '...': unreferenced formal parameter
#pragma warning(disable : 26812) // The enum type '...' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#include <base/numerics/safe_math.h>
#pragma warning(pop)
#include "til.h"
#include <til/pair.h>

View file

@ -0,0 +1,75 @@
// According to Nvidia's "Understanding Structured Buffer Performance" guide
// one should aim for structures with sizes divisible by 128 bits (16 bytes).
// This prevents elements from spanning cache lines.
struct Cell
{
uint glyphPos;
uint flags;
uint2 color;
};
cbuffer ConstantBuffer : register(b0)
{
float4 viewport;
uint2 cellSize;
uint cellCountX;
uint backgroundColor;
uint selectionColor;
};
StructuredBuffer<Cell> cells : register(t0);
Texture2D<float4> glyphs : register(t1);
float4 decodeRGB(uint i)
{
uint r = i & 0xff;
uint g = (i >> 8) & 0xff;
uint b = (i >> 16) & 0xff;
uint a = i >> 24;
return float4(r, g, b, a) / 255.0;
}
uint2 decodeU16x2(uint i)
{
return uint2(i & 0xffff, i >> 16);
}
float insideRect(float2 pos, float4 boundaries)
{
float2 v = step(boundaries.xy, pos) - step(boundaries.zw, pos);
return v.x * v.y;
}
float4 main(float4 pos: SV_Position): SV_Target
{
if (!insideRect(pos.xy, viewport))
{
return decodeRGB(backgroundColor);
}
uint2 cellIndex = pos.xy / cellSize;
uint2 cellPos = pos.xy % cellSize;
Cell cell = cells[cellIndex.y * cellCountX + cellIndex.x];
uint2 glyphPos = decodeU16x2(cell.glyphPos);
uint2 pixelPos = glyphPos + cellPos;
float4 alpha = glyphs[pixelPos];
float3 color = lerp(
decodeRGB(cell.color.y).rgb,
decodeRGB(cell.color.x).rgb,
alpha.rgb
);
if (cell.flags & 1)
{
color = abs(glyphs[cellPos].rgb - color);
}
if (cell.flags & 2)
{
float4 sc = decodeRGB(selectionColor);
color = lerp(color, sc.rgb, sc.a);
}
return float4(color, 1);
}

View file

@ -0,0 +1,12 @@
float4 main(uint id : SV_VERTEXID) : SV_POSITION
{
// The algorithm below is a fast way to generate a full screen triangle,
// published by Bill Bilodeau "Vertex Shader Tricks" at GDC14.
// It covers the entire viewport and is faster for the GPU than a quad/rectangle.
return float4(
float(id / 2) * 4.0 - 1.0,
float(id % 2) * 4.0 - 1.0,
0.0,
1.0
);
}

View file

@ -7,20 +7,7 @@
#include "../inc/FontInfoBase.hpp"
bool operator==(const FontInfoBase& a, const FontInfoBase& b)
{
return a._faceName == b._faceName &&
a._weight == b._weight &&
a._family == b._family &&
a._codePage == b._codePage &&
a._fDefaultRasterSetFromEngine == b._fDefaultRasterSetFromEngine;
}
FontInfoBase::FontInfoBase(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const unsigned int codePage) :
FontInfoBase::FontInfoBase(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont, const unsigned int codePage) noexcept :
_faceName(faceName),
_family(family),
_weight(weight),
@ -30,20 +17,16 @@ FontInfoBase::FontInfoBase(const std::wstring_view faceName,
ValidateFont();
}
FontInfoBase::FontInfoBase(const FontInfoBase& fibFont) :
FontInfoBase(fibFont.GetFaceName(),
fibFont.GetFamily(),
fibFont.GetWeight(),
fibFont.WasDefaultRasterSetFromEngine(),
fibFont.GetCodePage())
bool FontInfoBase::operator==(const FontInfoBase& other) noexcept
{
return _faceName == other._faceName &&
_weight == other._weight &&
_family == other._family &&
_codePage == other._codePage &&
_fDefaultRasterSetFromEngine == other._fDefaultRasterSetFromEngine;
}
FontInfoBase::~FontInfoBase()
{
}
unsigned char FontInfoBase::GetFamily() const
unsigned char FontInfoBase::GetFamily() const noexcept
{
return _family;
}
@ -51,22 +34,22 @@ unsigned char FontInfoBase::GetFamily() const
// When the default raster font is forced set from the engine, this is how we differentiate it from a simple apply.
// Default raster font is internally represented as a blank face name and zeros for weight, family, and size. This is
// the hint for the engine to use whatever comes back from GetStockObject(OEM_FIXED_FONT) (at least in the GDI world).
bool FontInfoBase::WasDefaultRasterSetFromEngine() const
bool FontInfoBase::WasDefaultRasterSetFromEngine() const noexcept
{
return _fDefaultRasterSetFromEngine;
}
unsigned int FontInfoBase::GetWeight() const
unsigned int FontInfoBase::GetWeight() const noexcept
{
return _weight;
}
const std::wstring_view FontInfoBase::GetFaceName() const noexcept
const std::wstring& FontInfoBase::GetFaceName() const noexcept
{
return _faceName;
}
unsigned int FontInfoBase::GetCodePage() const
unsigned int FontInfoBase::GetCodePage() const noexcept
{
return _codePage;
}
@ -77,21 +60,15 @@ unsigned int FontInfoBase::GetCodePage() const
// Arguments:
// - buffer: the buffer into which to copy characters
// - size: the size of buffer
HRESULT FontInfoBase::FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const
try
void FontInfoBase::FillLegacyNameBuffer(wchar_t (&buffer)[LF_FACESIZE]) const noexcept
{
auto toCopy = std::min<size_t>(buffer.size() - 1, _faceName.size());
auto last = std::copy(_faceName.cbegin(), _faceName.cbegin() + toCopy, buffer.begin());
std::fill(last, buffer.end(), L'\0');
return S_OK;
const auto toCopy = std::min(std::size(buffer) - 1, _faceName.size());
auto last = std::copy_n(_faceName.data(), toCopy, &buffer[0]);
*last = L'\0';
}
CATCH_RETURN();
// NOTE: this method is intended to only be used from the engine itself to respond what font it has chosen.
void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont)
void FontInfoBase::SetFromEngine(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont) noexcept
{
_faceName = faceName;
_family = family;
@ -101,12 +78,12 @@ void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
// Internally, default raster font is represented by empty facename, and zeros for weight, family, and size. Since
// FontInfoBase doesn't have sizing information, this helper checks everything else.
bool FontInfoBase::IsDefaultRasterFontNoSize() const
bool FontInfoBase::IsDefaultRasterFontNoSize() const noexcept
{
return (_weight == 0 && _family == 0 && _faceName.empty());
}
void FontInfoBase::ValidateFont()
void FontInfoBase::ValidateFont() noexcept
{
// If we were given a blank name, it meant raster fonts, which to us is always Terminal.
if (!IsDefaultRasterFontNoSize() && s_pFontDefaultList != nullptr)
@ -115,8 +92,7 @@ void FontInfoBase::ValidateFont()
if (_faceName == DEFAULT_TT_FONT_FACENAME)
{
std::wstring defaultFontFace;
if (SUCCEEDED(s_pFontDefaultList->RetrieveDefaultFontNameForCodepage(GetCodePage(),
defaultFontFace)))
if (SUCCEEDED(s_pFontDefaultList->RetrieveDefaultFontNameForCodepage(GetCodePage(), defaultFontFace)))
{
_faceName = defaultFontFace;
@ -128,14 +104,14 @@ void FontInfoBase::ValidateFont()
}
}
bool FontInfoBase::IsTrueTypeFont() const
bool FontInfoBase::IsTrueTypeFont() const noexcept
{
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}
Microsoft::Console::Render::IFontDefaultList* FontInfoBase::s_pFontDefaultList;
void FontInfoBase::s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList)
void FontInfoBase::s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList) noexcept
{
s_pFontDefaultList = pFontDefaultList;
}

View file

@ -5,13 +5,25 @@
#include "../inc/FontInfoDesired.hpp"
bool operator==(const FontInfoDesired& a, const FontInfoDesired& b)
FontInfoDesired::FontInfoDesired(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const COORD coordSizeDesired, const unsigned int codePage) noexcept :
FontInfoBase(faceName, family, weight, false, codePage),
_coordSizeDesired(coordSizeDesired)
{
return (static_cast<FontInfoBase>(a) == static_cast<FontInfoBase>(b) &&
a._coordSizeDesired == b._coordSizeDesired);
}
COORD FontInfoDesired::GetEngineSize() const
FontInfoDesired::FontInfoDesired(const FontInfo& fiFont) noexcept :
FontInfoBase(fiFont),
_coordSizeDesired(fiFont.GetUnscaledSize())
{
}
bool FontInfoDesired::operator==(const FontInfoDesired& other) noexcept
{
return FontInfoBase::operator==(other) &&
_coordSizeDesired == other._coordSizeDesired;
}
COORD FontInfoDesired::GetEngineSize() const noexcept
{
COORD coordSize = _coordSizeDesired;
if (IsTrueTypeFont())
@ -22,30 +34,12 @@ COORD FontInfoDesired::GetEngineSize() const
return coordSize;
}
FontInfoDesired::FontInfoDesired(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const COORD coordSizeDesired,
const unsigned int codePage) :
FontInfoBase(faceName, family, weight, false, codePage),
_coordSizeDesired(coordSizeDesired)
{
}
FontInfoDesired::FontInfoDesired(const FontInfo& fiFont) :
FontInfoBase(fiFont),
_coordSizeDesired(fiFont.GetUnscaledSize())
{
}
// This helper determines if this object represents the default raster font. This can either be because internally we're
// using the empty facename and zeros for size, weight, and family, or it can be because we were given explicit
// dimensions from the engine that were the result of loading the default raster font. See GdiEngine::_GetProposedFont().
bool FontInfoDesired::IsDefaultRasterFont() const
bool FontInfoDesired::IsDefaultRasterFont() const noexcept
{
// Either the raster was set from the engine...
// OR the face name is empty with a size of 0x0 or 8x12.
return WasDefaultRasterSetFromEngine() || (GetFaceName().empty() &&
((_coordSizeDesired.X == 0 && _coordSizeDesired.Y == 0) ||
(_coordSizeDesired.X == 8 && _coordSizeDesired.Y == 12)));
return WasDefaultRasterSetFromEngine() || (GetFaceName().empty() && (_coordSizeDesired == COORD{ 0, 0 } || _coordSizeDesired == COORD{ 8, 12 }));
}

View file

@ -7,38 +7,25 @@
using namespace Microsoft::Console;
using namespace Microsoft::Console::Render;
RenderEngineBase::RenderEngineBase() :
_titleChanged(false),
_lastFrameTitle(L"")
HRESULT RenderEngineBase::InvalidateTitle() noexcept
{
}
HRESULT RenderEngineBase::InvalidateTitle(const std::wstring_view proposedTitle) noexcept
{
if (proposedTitle != _lastFrameTitle)
{
_titleChanged = true;
}
_titleChanged = true;
return S_OK;
}
HRESULT RenderEngineBase::UpdateTitle(const std::wstring_view newTitle) noexcept
{
HRESULT hr = S_FALSE;
if (newTitle != _lastFrameTitle)
if (!_titleChanged)
{
RETURN_IF_FAILED(_DoUpdateTitle(newTitle));
_lastFrameTitle = newTitle;
_titleChanged = false;
hr = S_OK;
return S_FALSE;
}
return hr;
RETURN_IF_FAILED(_DoUpdateTitle(newTitle));
_titleChanged = false;
return S_OK;
}
HRESULT RenderEngineBase::UpdateSoftFont(const gsl::span<const uint16_t> /*bitPattern*/,
const SIZE /*cellSize*/,
const size_t /*centeringHint*/) noexcept
HRESULT RenderEngineBase::UpdateSoftFont(const gsl::span<const uint16_t> /*bitPattern*/, const SIZE /*cellSize*/, const size_t /*centeringHint*/) noexcept
{
return S_FALSE;
}
@ -53,9 +40,7 @@ HRESULT RenderEngineBase::ResetLineTransform() noexcept
return S_FALSE;
}
HRESULT RenderEngineBase::PrepareLineTransform(const LineRendition /*lineRendition*/,
const size_t /*targetRow*/,
const size_t /*viewportLeft*/) noexcept
HRESULT RenderEngineBase::PrepareLineTransform(const LineRendition /*lineRendition*/, const size_t /*targetRow*/, const size_t /*viewportLeft*/) noexcept
{
return S_FALSE;
}
@ -74,5 +59,13 @@ HRESULT RenderEngineBase::PrepareLineTransform(const LineRendition /*lineRenditi
// - Blocks until the engine is able to render without blocking.
void RenderEngineBase::WaitUntilCanRender() noexcept
{
// do nothing by default
Sleep(8);
}
// Routine Description:
// - Uses the currently selected font to determine how wide the given character will be when rendered.
[[nodiscard]] HRESULT RenderEngineBase::IsGlyphWideByFont(const std::wstring_view& /*glyph*/, _Out_ bool* const pResult) noexcept
{
*pResult = false;
return S_FALSE;
}

View file

@ -5,19 +5,7 @@
#include "../inc/FontInfo.hpp"
bool operator==(const FontInfo& a, const FontInfo& b)
{
return (static_cast<FontInfoBase>(a) == static_cast<FontInfoBase>(b) &&
a._coordSize == b._coordSize &&
a._coordSizeUnscaled == b._coordSizeUnscaled);
}
FontInfo::FontInfo(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const COORD coordSize,
const unsigned int codePage,
const bool fSetDefaultRasterFont /* = false */) :
FontInfo::FontInfo(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const COORD coordSize, const unsigned int codePage, const bool fSetDefaultRasterFont) noexcept :
FontInfoBase(faceName, family, weight, fSetDefaultRasterFont, codePage),
_coordSize(coordSize),
_coordSizeUnscaled(coordSize),
@ -26,39 +14,29 @@ FontInfo::FontInfo(const std::wstring_view faceName,
ValidateFont();
}
FontInfo::FontInfo(const FontInfo& fiFont) :
FontInfoBase(fiFont),
_coordSize(fiFont.GetSize()),
_coordSizeUnscaled(fiFont.GetUnscaledSize())
bool FontInfo::operator==(const FontInfo& other) noexcept
{
return FontInfoBase::operator==(other) &&
_coordSize == other._coordSize &&
_coordSizeUnscaled == other._coordSizeUnscaled;
}
COORD FontInfo::GetUnscaledSize() const
COORD FontInfo::GetUnscaledSize() const noexcept
{
return _coordSizeUnscaled;
}
COORD FontInfo::GetSize() const
COORD FontInfo::GetSize() const noexcept
{
return _coordSize;
}
void FontInfo::SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
const COORD coordSizeUnscaled)
void FontInfo::SetFromEngine(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont, const COORD coordSize, const COORD coordSizeUnscaled) noexcept
{
FontInfoBase::SetFromEngine(faceName,
family,
weight,
fSetDefaultRasterFont);
FontInfoBase::SetFromEngine(faceName, family, weight, fSetDefaultRasterFont);
_coordSize = coordSize;
_coordSizeUnscaled = coordSizeUnscaled;
_ValidateCoordSize();
ValidateFont();
}
bool FontInfo::GetFallback() const noexcept
@ -71,12 +49,7 @@ void FontInfo::SetFallback(const bool didFallback) noexcept
_didFallback = didFallback;
}
void FontInfo::ValidateFont()
{
_ValidateCoordSize();
}
void FontInfo::_ValidateCoordSize()
void FontInfo::ValidateFont() noexcept
{
// a (0,0) font is okay for the default raster font, as we will eventually set the dimensions based on the font GDI
// passes back to us.

View file

@ -69,11 +69,6 @@ Renderer::~Renderer()
auto tries = maxRetriesForRenderEngine;
while (tries > 0)
{
if (_destructing)
{
return S_FALSE;
}
const auto hr = _PaintFrameForEngine(pEngine);
if (E_PENDING == hr)
{
@ -487,7 +482,7 @@ void Renderer::TriggerTitleChange()
const auto newTitle = _pData->GetConsoleTitle();
FOREACH_ENGINE(pEngine)
{
LOG_IF_FAILED(pEngine->InvalidateTitle(newTitle));
LOG_IF_FAILED(pEngine->InvalidateTitle());
}
_NotifyPaintFrame();
}
@ -593,7 +588,7 @@ bool Renderer::s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSo
// - glyph - the utf16 encoded codepoint to test
// Return Value:
// - True if the codepoint is full-width (two wide), false if it is half-width (one wide).
bool Renderer::IsGlyphWideByFont(const std::wstring_view glyph)
bool Renderer::IsGlyphWideByFont(const std::wstring_view& glyph)
{
bool fIsFullWidth = false;
@ -761,7 +756,7 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
// Retrieve the first pattern id
auto patternIds = _pData->GetPatternId(target);
// Determine whether we're using a soft font.
auto usingSoftFont = s_IsSoftFontChar(it->Chars(), _firstSoftFontChar, _lastSoftFontChar);
auto usingSoftFont = _isSoftFontChar(it->Chars());
// And hold the point where we should start drawing.
auto screenPoint = target;
@ -808,7 +803,7 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
{
COORD thisPoint{ screenPoint.X + gsl::narrow<SHORT>(cols), screenPoint.Y };
const auto thisPointPatterns = _pData->GetPatternId(thisPoint);
const auto thisUsingSoftFont = s_IsSoftFontChar(it->Chars(), _firstSoftFontChar, _lastSoftFontChar);
const auto thisUsingSoftFont = _isSoftFontChar(it->Chars());
const auto changedPatternOrFont = patternIds != thisPointPatterns || usingSoftFont != thisUsingSoftFont;
if (color != it->TextAttr() || changedPatternOrFont)
{

View file

@ -73,7 +73,7 @@ namespace Microsoft::Console::Render
const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo) override;
bool IsGlyphWideByFont(const std::wstring_view glyph) override;
bool IsGlyphWideByFont(const std::wstring_view& glyph) override;
void EnablePainting() override;
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override;
@ -108,6 +108,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
[[nodiscard]] std::optional<CursorOptions> _GetCursorInfo();
[[nodiscard]] HRESULT _PrepareRenderInfo(_In_ IRenderEngine* const pEngine);
bool _isSoftFontChar(const std::wstring_view& v) const noexcept;
std::array<IRenderEngine*, 2> _engines{};
IRenderData* _pData = nullptr; // Non-ownership pointer

View file

@ -61,7 +61,7 @@ RenderThread::~RenderThread()
// Return Value:
// - S_OK if we succeeded, else an HRESULT corresponding to a failure to create
// an Event or Thread.
[[nodiscard]] HRESULT RenderThread::Initialize(IRenderer* const pRendererParent) noexcept
[[nodiscard]] HRESULT RenderThread::Initialize(_In_ IRenderer* const pRendererParent) noexcept
{
_pRenderer = pRendererParent;
@ -213,12 +213,6 @@ DWORD WINAPI RenderThread::_ThreadProc()
LOG_IF_FAILED(_pRenderer->PaintFrame());
SetEvent(_hPaintCompletedEvent);
// extra check before we sleep since it's a "long" activity, relatively speaking.
if (_fKeepRunning)
{
Sleep(s_FrameLimitMilliseconds);
}
}
return S_OK;

View file

@ -37,8 +37,6 @@ namespace Microsoft::Console::Render
static DWORD WINAPI s_ThreadProc(_In_ LPVOID lpParameter);
DWORD WINAPI _ThreadProc();
static DWORD const s_FrameLimitMilliseconds = 8;
HANDLE _hThread;
HANDLE _hEvent;

View file

@ -1498,18 +1498,13 @@ CATCH_RETURN()
// - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains.
void DxEngine::WaitUntilCanRender() noexcept
{
if (!_swapChainFrameLatencyWaitableObject)
{
return;
}
// DxEngine isn't really performant and holds the console lock for at least 20ms per (full) frame.
// Sleeping 8ms per frame thus increases throughput of the concurrently running VtEngine.
Sleep(8);
const auto ret = WaitForSingleObjectEx(
_swapChainFrameLatencyWaitableObject.get(),
1000, // 1 second timeout (shouldn't ever occur)
true);
if (ret != WAIT_OBJECT_0)
if (_swapChainFrameLatencyWaitableObject)
{
LOG_WIN32_MSG(ret, "Waiting for swap chain frame latency waitable object returned error or timeout.");
WaitForSingleObjectEx(_swapChainFrameLatencyWaitableObject.get(), 1000, true);
}
}
@ -2135,7 +2130,7 @@ CATCH_RETURN();
// - pResult - True if it should take two columns. False if it should take one.
// Return Value:
// - S_OK or relevant DirectWrite error.
[[nodiscard]] HRESULT DxEngine::IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept
[[nodiscard]] HRESULT DxEngine::IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept
try
{
RETURN_HR_IF_NULL(E_INVALIDARG, pResult);

View file

@ -119,7 +119,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept override;
[[nodiscard]] ::Microsoft::Console::Types::Viewport GetViewportInCharacters(const ::Microsoft::Console::Types::Viewport& viewInPixels) noexcept;
[[nodiscard]] ::Microsoft::Console::Types::Viewport GetViewportInPixels(const ::Microsoft::Console::Types::Viewport& viewInCharacters) noexcept;

View file

@ -78,7 +78,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override;

View file

@ -38,7 +38,7 @@ using namespace Microsoft::Console::Render;
// - pResult - receives return value, True if it is full-width (2 wide). False if it is half-width (1 wide).
// Return Value:
// - S_OK
[[nodiscard]] HRESULT GdiEngine::IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept
[[nodiscard]] HRESULT GdiEngine::IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept
{
bool isFullWidth = false;

View file

@ -610,7 +610,7 @@ GdiEngine::~GdiEngine()
// NOTE: not using what GDI gave us because some fonts don't quite roundtrip (e.g. MS Gothic and VL Gothic)
lf.lfPitchAndFamily = (FIXED_PITCH | FF_MODERN);
RETURN_IF_FAILED(FontDesired.FillLegacyNameBuffer(gsl::make_span(lf.lfFaceName)));
FontDesired.FillLegacyNameBuffer(lf.lfFaceName);
// Create font.
hFont.reset(CreateFontIndirectW(&lf));

View file

@ -28,40 +28,21 @@ Author(s):
class FontInfo : public FontInfoBase
{
public:
FontInfo(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const COORD coordSize,
const unsigned int codePage,
const bool fSetDefaultRasterFont = false);
FontInfo(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const COORD coordSize, const unsigned int codePage, const bool fSetDefaultRasterFont = false) noexcept;
FontInfo(const FontInfo& fiFont);
COORD GetSize() const;
COORD GetUnscaledSize() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
const COORD coordSizeUnscaled);
bool operator==(const FontInfo& other) noexcept;
COORD GetSize() const noexcept;
COORD GetUnscaledSize() const noexcept;
void SetFromEngine(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont, const COORD coordSize, const COORD coordSizeUnscaled) noexcept;
bool GetFallback() const noexcept;
void SetFallback(const bool didFallback) noexcept;
void ValidateFont();
friend bool operator==(const FontInfo& a, const FontInfo& b);
void ValidateFont() noexcept;
private:
void _ValidateCoordSize();
COORD _coordSize;
COORD _coordSizeUnscaled;
bool _didFallback;
};
bool operator==(const FontInfo& a, const FontInfo& b);
// SET AND UNSET CONSOLE_OEMFONT_DISPLAY unless we can get rid of the stupid recoding in the conhost side.

View file

@ -26,40 +26,25 @@ static constexpr wchar_t DEFAULT_RASTER_FONT_FACENAME[]{ L"Terminal" };
class FontInfoBase
{
public:
FontInfoBase(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const unsigned int uiCodePage);
FontInfoBase(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont, const unsigned int uiCodePage) noexcept;
FontInfoBase(const FontInfoBase& fibFont);
bool operator==(const FontInfoBase& other) noexcept;
~FontInfoBase();
unsigned char GetFamily() const;
unsigned int GetWeight() const;
const std::wstring_view GetFaceName() const noexcept;
unsigned int GetCodePage() const;
HRESULT FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const;
bool IsTrueTypeFont() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont);
bool WasDefaultRasterSetFromEngine() const;
void ValidateFont();
unsigned char GetFamily() const noexcept;
unsigned int GetWeight() const noexcept;
const std::wstring& GetFaceName() const noexcept;
unsigned int GetCodePage() const noexcept;
void FillLegacyNameBuffer(wchar_t (&buffer)[LF_FACESIZE]) const noexcept;
bool IsTrueTypeFont() const noexcept;
void SetFromEngine(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const bool fSetDefaultRasterFont) noexcept;
bool WasDefaultRasterSetFromEngine() const noexcept;
void ValidateFont() noexcept;
static Microsoft::Console::Render::IFontDefaultList* s_pFontDefaultList;
static void s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList);
friend bool operator==(const FontInfoBase& a, const FontInfoBase& b);
static void s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList) noexcept;
protected:
bool IsDefaultRasterFontNoSize() const;
bool IsDefaultRasterFontNoSize() const noexcept;
private:
std::wstring _faceName;
@ -68,5 +53,3 @@ private:
unsigned int _codePage;
bool _fDefaultRasterSetFromEngine;
};
bool operator==(const FontInfoBase& a, const FontInfoBase& b);

View file

@ -24,21 +24,14 @@ Author(s):
class FontInfoDesired : public FontInfoBase
{
public:
FontInfoDesired(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const COORD coordSizeDesired,
const unsigned int uiCodePage);
FontInfoDesired(const std::wstring_view& faceName, const unsigned char family, const unsigned int weight, const COORD coordSizeDesired, const unsigned int uiCodePage) noexcept;
FontInfoDesired(const FontInfo& fiFont) noexcept;
FontInfoDesired(const FontInfo& fiFont);
bool operator==(const FontInfoDesired& other) noexcept;
COORD GetEngineSize() const;
bool IsDefaultRasterFont() const;
friend bool operator==(const FontInfoDesired& a, const FontInfoDesired& b);
COORD GetEngineSize() const noexcept;
bool IsDefaultRasterFont() const noexcept;
private:
COORD _coordSizeDesired;
};
bool operator==(const FontInfoDesired& a, const FontInfoDesired& b);

View file

@ -44,27 +44,22 @@ namespace Microsoft::Console::Render
};
using GridLineSet = til::enumset<GridLines>;
virtual ~IRenderEngine() = 0;
protected:
IRenderEngine() = default;
IRenderEngine(const IRenderEngine&) = default;
IRenderEngine(IRenderEngine&&) = default;
virtual ~IRenderEngine() = 0;
IRenderEngine& operator=(const IRenderEngine&) = default;
IRenderEngine& operator=(IRenderEngine&&) = default;
public:
[[nodiscard]] virtual HRESULT StartPaint() noexcept = 0;
[[nodiscard]] virtual HRESULT EndPaint() noexcept = 0;
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept = 0;
virtual void WaitUntilCanRender() noexcept = 0;
[[nodiscard]] virtual HRESULT Present() noexcept = 0;
[[nodiscard]] virtual HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept = 0;
[[nodiscard]] virtual HRESULT ScrollFrame() noexcept = 0;
[[nodiscard]] virtual HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept = 0;
@ -72,48 +67,24 @@ namespace Microsoft::Console::Render
[[nodiscard]] virtual HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateAll() noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept = 0;
[[nodiscard]] virtual HRESULT InvalidateTitle() noexcept = 0;
[[nodiscard]] virtual HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept = 0;
[[nodiscard]] virtual HRESULT ResetLineTransform() noexcept = 0;
[[nodiscard]] virtual HRESULT PrepareLineTransform(const LineRendition lineRendition,
const size_t targetRow,
const size_t viewportLeft) noexcept = 0;
[[nodiscard]] virtual HRESULT PrepareLineTransform(const LineRendition lineRendition, const size_t targetRow, const size_t viewportLeft) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintBackground() noexcept = 0;
[[nodiscard]] virtual HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters,
const COORD coord,
const bool fTrimLeft,
const bool lineWrapped) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintBufferGridLines(const GridLineSet lines,
const COLORREF color,
const size_t cchLine,
const COORD coordTarget) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintBufferGridLines(const GridLineSet lines, const COLORREF color, const size_t cchLine, const COORD coordTarget) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintSelection(const SMALL_RECT rect) noexcept = 0;
[[nodiscard]] virtual HRESULT PaintCursor(const CursorOptions& options) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
const gsl::not_null<IRenderData*> pData,
const bool usingSoftFont,
const bool isSettingDefaultBrushes) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const SIZE cellSize, const size_t centeringHint) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateDpi(const int iDpi) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept = 0;
[[nodiscard]] virtual HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo,
const int iDpi) noexcept = 0;
[[nodiscard]] virtual HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept = 0;
[[nodiscard]] virtual HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept = 0;
[[nodiscard]] virtual HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept = 0;
[[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept = 0;
[[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept = 0;
};

View file

@ -58,7 +58,7 @@ namespace Microsoft::Console::Render
const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo) = 0;
virtual bool IsGlyphWideByFont(const std::wstring_view glyph) = 0;
virtual bool IsGlyphWideByFont(const std::wstring_view& glyph) = 0;
virtual void EnablePainting() = 0;
virtual void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) = 0;

View file

@ -24,40 +24,27 @@ namespace Microsoft::Console::Render
class RenderEngineBase : public IRenderEngine
{
public:
RenderEngineBase() = default;
~RenderEngineBase() = 0;
protected:
RenderEngineBase();
RenderEngineBase(const RenderEngineBase&) = default;
RenderEngineBase(RenderEngineBase&&) = default;
RenderEngineBase& operator=(const RenderEngineBase&) = default;
RenderEngineBase& operator=(RenderEngineBase&&) = default;
public:
[[nodiscard]] HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept override;
[[nodiscard]] HRESULT InvalidateTitle() noexcept override;
[[nodiscard]] HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept override;
[[nodiscard]] HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
const SIZE cellSize,
const size_t centeringHint) noexcept override;
[[nodiscard]] HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const SIZE cellSize, const size_t centeringHint) noexcept override;
[[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override;
[[nodiscard]] HRESULT ResetLineTransform() noexcept override;
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition,
const size_t targetRow,
const size_t viewportLeft) noexcept override;
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition, const size_t targetRow, const size_t viewportLeft) noexcept override;
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept override;
void WaitUntilCanRender() noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view& glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept = 0;
bool _titleChanged;
std::wstring _lastFrameTitle;
bool _titleChanged = false;
};
inline Microsoft::Console::Render::RenderEngineBase::~RenderEngineBase() {}

View file

@ -261,6 +261,13 @@ CATCH_RETURN();
return S_OK;
}
// RenderEngineBase defines a WaitUntilCanRender() that sleeps for 8ms to throttle rendering.
// But UiaEngine is never the only the engine running. Overriding this function prevents
// us from sleeping 16ms per frame, when the other engine also sleeps for 8ms.
void UiaEngine::WaitUntilCanRender() noexcept
{
}
// Routine Description:
// - Used to perform longer running presentation steps outside the lock so the
// other threads can continue.
@ -453,18 +460,6 @@ CATCH_RETURN();
return S_FALSE;
}
// Routine Description:
// - Currently unused by this renderer.
// Arguments:
// - glyph - The glyph run to process for column width.
// - pResult - True if it should take two columns. False if it should take one.
// Return Value:
// - S_OK or relevant DirectWrite error.
[[nodiscard]] HRESULT UiaEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const /*pResult*/) noexcept
{
return S_FALSE;
}
// Method Description:
// - Updates the window's title string.
// - Currently unused by this renderer.

View file

@ -36,12 +36,10 @@ namespace Microsoft::Console::Render
// IRenderEngine Members
[[nodiscard]] HRESULT StartPaint() noexcept override;
[[nodiscard]] HRESULT EndPaint() noexcept override;
void WaitUntilCanRender() noexcept override;
[[nodiscard]] HRESULT Present() noexcept override;
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override;
@ -49,30 +47,18 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
[[nodiscard]] HRESULT PaintBackground() noexcept override;
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters,
COORD const coord,
bool const fTrimLeft,
const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, COORD const coord, bool const fTrimLeft, const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(GridLineSet const lines, COLORREF const color, size_t const cchLine, COORD const coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
const gsl::not_null<IRenderData*> pData,
const bool usingSoftFont,
const bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo) noexcept override;
[[nodiscard]] HRESULT UpdateDpi(int const iDpi) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept override;
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
[[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override;
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept override;
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept override;

View file

@ -23,20 +23,6 @@ using namespace Microsoft::Console::Types;
return S_OK;
}
// Routine Description:
// - Uses the currently selected font to determine how wide the given character will be when rendered.
// - NOTE: Only supports determining half-width/full-width status for CJK-type languages (e.g. is it 1 character wide or 2. a.k.a. is it a rectangle or square.)
// Arguments:
// - glyph - utf16 encoded codepoint to check
// - pResult - receives return value, True if it is full-width (2 wide). False if it is half-width (1 wide).
// Return Value:
// - S_FALSE: This is unsupported by the VT Renderer and should use another engine's value.
[[nodiscard]] HRESULT VtEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const pResult) noexcept
{
*pResult = false;
return S_FALSE;
}
// Routine Description:
// - Performs a "CombineRect" with the "OR" operation.
// - Basically extends the existing rect outward to also encompass the passed-in region.

View file

@ -88,7 +88,6 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
[[nodiscard]] HRESULT SuppressResizeRepaint() noexcept;

View file

@ -402,12 +402,6 @@ RECT WddmConEngine::GetDisplaySize()
return S_OK;
}
[[nodiscard]] HRESULT WddmConEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const pResult) noexcept
{
*pResult = false;
return S_OK;
}
// Method Description:
// - Updates the window's title string.
// Does nothing for WddmCon.

View file

@ -62,7 +62,6 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override;

View file

@ -1325,7 +1325,8 @@ void StateMachine::_EventCsiParam(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventOscParam(const wchar_t wch) noexcept
#pragma warning(suppress : 26440) // Function ... can be declared 'noexcept' (f.6).
void StateMachine::_EventOscParam(const wchar_t wch)
{
_trace.TraceOnEvent(L"OscParam");
if (_isOscTerminator(wch))
@ -1577,7 +1578,8 @@ void StateMachine::_EventDcsEntry(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventDcsIgnore() noexcept
#pragma warning(suppress : 26440) // Function ... can be declared 'noexcept' (f.6).
void StateMachine::_EventDcsIgnore(const wchar_t /*wch*/)
{
_trace.TraceOnEvent(L"DcsIgnore");
_ActionIgnore();
@ -1697,7 +1699,8 @@ void StateMachine::_EventDcsPassThrough(const wchar_t wch)
// - wch - Character that triggered the event
// Return Value:
// - <none>
void StateMachine::_EventSosPmApcString(const wchar_t /*wch*/) noexcept
#pragma warning(suppress : 26440) // Function ... can be declared 'noexcept' (f.6).
void StateMachine::_EventSosPmApcString(const wchar_t /*wch*/)
{
_trace.TraceOnEvent(L"SosPmApcString");
_ActionIgnore();
@ -1738,52 +1741,34 @@ void StateMachine::ProcessCharacter(const wchar_t wch)
_ActionInterrupt();
_EnterEscape();
}
else
else if (_state < VTStates::TotalStates)
{
static constexpr alignas(64) void (StateMachine::*funcs[])(wchar_t) = {
&StateMachine::_EventGround, // VTStates::Ground
&StateMachine::_EventEscape, // VTStates::Escape
&StateMachine::_EventEscapeIntermediate, // VTStates::EscapeIntermediate
&StateMachine::_EventCsiEntry, // VTStates::CsiEntry
&StateMachine::_EventCsiIntermediate, // VTStates::CsiIntermediate
&StateMachine::_EventCsiIgnore, // VTStates::CsiIgnore
&StateMachine::_EventCsiParam, // VTStates::CsiParam
&StateMachine::_EventOscParam, // VTStates::OscParam
&StateMachine::_EventOscString, // VTStates::OscString
&StateMachine::_EventOscTermination, // VTStates::OscTermination
&StateMachine::_EventSs3Entry, // VTStates::Ss3Entry
&StateMachine::_EventSs3Param, // VTStates::Ss3Param
&StateMachine::_EventVt52Param, // VTStates::Vt52Param
&StateMachine::_EventDcsEntry, // VTStates::DcsEntry
&StateMachine::_EventDcsIgnore, // VTStates::DcsIgnore
&StateMachine::_EventDcsIntermediate, // VTStates::DcsIntermediate
&StateMachine::_EventDcsParam, // VTStates::DcsParam
&StateMachine::_EventDcsPassThrough, // VTStates::DcsPassThrough
&StateMachine::_EventSosPmApcString, // VTStates::SosPmApcString
};
// Then pass to the current state as an event
switch (_state)
{
case VTStates::Ground:
return _EventGround(wch);
case VTStates::Escape:
return _EventEscape(wch);
case VTStates::EscapeIntermediate:
return _EventEscapeIntermediate(wch);
case VTStates::CsiEntry:
return _EventCsiEntry(wch);
case VTStates::CsiIntermediate:
return _EventCsiIntermediate(wch);
case VTStates::CsiIgnore:
return _EventCsiIgnore(wch);
case VTStates::CsiParam:
return _EventCsiParam(wch);
case VTStates::OscParam:
return _EventOscParam(wch);
case VTStates::OscString:
return _EventOscString(wch);
case VTStates::OscTermination:
return _EventOscTermination(wch);
case VTStates::Ss3Entry:
return _EventSs3Entry(wch);
case VTStates::Ss3Param:
return _EventSs3Param(wch);
case VTStates::Vt52Param:
return _EventVt52Param(wch);
case VTStates::DcsEntry:
return _EventDcsEntry(wch);
case VTStates::DcsIgnore:
return _EventDcsIgnore();
case VTStates::DcsIntermediate:
return _EventDcsIntermediate(wch);
case VTStates::DcsParam:
return _EventDcsParam(wch);
case VTStates::DcsPassThrough:
return _EventDcsPassThrough(wch);
case VTStates::SosPmApcString:
return _EventSosPmApcString(wch);
default:
return;
}
// Invalid _state values will jump to address 0, which is fine I guess.
#pragma warning(suppress : 26482) // Only index into arrays using constant expressions (bounds.2).
(this->*funcs[WI_EnumValue(_state)])(wch);
}
}
// Method Description:

View file

@ -100,22 +100,22 @@ namespace Microsoft::Console::VirtualTerminal
void _EventCsiIntermediate(const wchar_t wch);
void _EventCsiIgnore(const wchar_t wch);
void _EventCsiParam(const wchar_t wch);
void _EventOscParam(const wchar_t wch) noexcept;
void _EventOscParam(const wchar_t wch);
void _EventOscString(const wchar_t wch);
void _EventOscTermination(const wchar_t wch);
void _EventSs3Entry(const wchar_t wch);
void _EventSs3Param(const wchar_t wch);
void _EventVt52Param(const wchar_t wch);
void _EventDcsEntry(const wchar_t wch);
void _EventDcsIgnore() noexcept;
void _EventDcsIgnore(const wchar_t wch);
void _EventDcsIntermediate(const wchar_t wch);
void _EventDcsParam(const wchar_t wch);
void _EventDcsPassThrough(const wchar_t wch);
void _EventSosPmApcString(const wchar_t wch) noexcept;
void _EventSosPmApcString(const wchar_t wch);
void _AccumulateTo(const wchar_t wch, size_t& value) noexcept;
enum class VTStates
enum class VTStates : uint_fast8_t
{
Ground,
Escape,
@ -135,7 +135,8 @@ namespace Microsoft::Console::VirtualTerminal
DcsIntermediate,
DcsParam,
DcsPassThrough,
SosPmApcString
SosPmApcString,
TotalStates
};
Microsoft::Console::VirtualTerminal::ParserTracing _trace;

View file

@ -9,12 +9,12 @@ namespace
// used to store range data in CodepointWidthDetector's internal map
struct UnicodeRange final
{
unsigned int lowerBound;
unsigned int upperBound;
uint32_t lowerBound;
uint32_t upperBound;
CodepointWidth width;
};
static bool operator<(const UnicodeRange& range, const unsigned int searchTerm) noexcept
static bool operator<(const UnicodeRange& range, const uint32_t searchTerm) noexcept
{
return range.upperBound < searchTerm;
}
@ -323,56 +323,46 @@ namespace
};
}
// Routine Description:
// - Constructs an instance of the CodepointWidthDetector class
CodepointWidthDetector::CodepointWidthDetector() noexcept :
_fallbackCache{},
_pfnFallbackMethod{}
{
}
// Routine Description:
// - returns the width type of codepoint as fast as we can by using quick lookup table and fallback cache.
// Arguments:
// - glyph - the utf16 encoded codepoint to search for
// Return Value:
// - the width type of the codepoint
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) const
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view& glyph) const noexcept
try
{
THROW_HR_IF(E_INVALIDARG, glyph.empty());
if (glyph.size() == 1)
#pragma warning(suppress : 26494) // Variable 'codepoint' is uninitialized. Always initialize an object (type.5).
uint32_t codepoint;
switch (glyph.size())
{
// We first attempt to look at our custom quick lookup table of char width preferences.
const auto width = GetQuickCharWidth(glyph.front());
case 1:
codepoint = til::at(glyph, 0);
break;
case 2:
codepoint = (til::at(glyph, 0) & 0x3FF) << 10;
codepoint |= til::at(glyph, 1) & 0x3FF;
codepoint += 0x10000;
break;
default:
throw std::invalid_argument("invalid UTF16 scalar value pair");
}
// If it's invalid, the quick width had no opinion, so go to the lookup table.
if (width == CodepointWidth::Invalid)
{
return _lookupGlyphWidthWithCache(glyph);
}
// If it's ambiguous, the quick width wanted us to ask the font directly, try that if we can.
// If not, go to the lookup table.
else if (width == CodepointWidth::Ambiguous)
{
if (_pfnFallbackMethod)
{
return _checkFallbackViaCache(glyph) ? CodepointWidth::Wide : CodepointWidth::Ambiguous;
}
else
{
return _lookupGlyphWidthWithCache(glyph);
}
}
// Otherwise, return Width as it is.
else
{
return width;
}
}
else
auto width = _lookupGlyphWidth(codepoint);
if (width == CodepointWidth::Ambiguous && _pfnFallbackMethod)
{
return _lookupGlyphWidthWithCache(glyph);
width = _checkFallbackViaCache(codepoint, glyph) ? CodepointWidth::Wide : CodepointWidth::Ambiguous;
}
return width;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
// If we got this far, we couldn't figure it out.
// It's better to be too wide than too narrow.
return glyph.empty() ? CodepointWidth::Ambiguous : CodepointWidth::Wide;
}
// Routine Description:
@ -383,13 +373,7 @@ CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) c
// - true if wch is wide
bool CodepointWidthDetector::IsWide(const wchar_t wch) const noexcept
{
try
{
return IsWide({ &wch, 1 });
}
CATCH_LOG();
return true;
return IsWide({ &wch, 1 });
}
// Routine Description:
@ -398,7 +382,7 @@ bool CodepointWidthDetector::IsWide(const wchar_t wch) const noexcept
// - glyph - the utf16 encoded codepoint to check width of
// Return Value:
// - true if codepoint is wide
bool CodepointWidthDetector::IsWide(const std::wstring_view glyph) const
bool CodepointWidthDetector::IsWide(const std::wstring_view& glyph) const noexcept
{
return GetWidth(glyph) == CodepointWidth::Wide;
}
@ -409,64 +393,24 @@ bool CodepointWidthDetector::IsWide(const std::wstring_view glyph) const
// - glyph - the utf16 encoded codepoint to search for
// Return Value:
// - the width type of the codepoint
CodepointWidth CodepointWidthDetector::_lookupGlyphWidth(const std::wstring_view glyph) const
CodepointWidth CodepointWidthDetector::_lookupGlyphWidth(uint32_t codepoint) const
{
if (glyph.empty())
// No need to check ASCII
if (codepoint >= 0x80)
{
return CodepointWidth::Invalid;
}
const auto it = std::lower_bound(s_wideAndAmbiguousTable.begin(), s_wideAndAmbiguousTable.end(), codepoint);
const auto codepoint = _extractCodepoint(glyph);
const auto it = std::lower_bound(s_wideAndAmbiguousTable.begin(), s_wideAndAmbiguousTable.end(), codepoint);
// For characters that are not _in_ the table, lower_bound will return the nearest item that is.
// We must check its bounds to make sure that our hit was a true hit.
if (it != s_wideAndAmbiguousTable.end() && codepoint >= it->lowerBound && codepoint <= it->upperBound)
{
return it->width;
// For characters that are not _in_ the table, lower_bound will return the nearest item that is.
// We must check its bounds to make sure that our hit was a true hit.
if (it != s_wideAndAmbiguousTable.end() && codepoint >= it->lowerBound && codepoint <= it->upperBound)
{
return it->width;
}
}
return CodepointWidth::Narrow;
}
// Routine Description:
// - returns the width type of codepoint using fallback methods.
// Arguments:
// - glyph - the utf16 encoded codepoint to check width of
// Return Value:
// - the width type of the codepoint
CodepointWidth CodepointWidthDetector::_lookupGlyphWidthWithCache(const std::wstring_view glyph) const noexcept
{
try
{
// Use our generated table to try to lookup the width based on the Unicode standard.
const CodepointWidth width = _lookupGlyphWidth(glyph);
// If it's ambiguous, then ask the font if we can.
if (width == CodepointWidth::Ambiguous)
{
if (_pfnFallbackMethod)
{
return _checkFallbackViaCache(glyph) ? CodepointWidth::Wide : CodepointWidth::Ambiguous;
}
else
{
return CodepointWidth::Ambiguous;
}
}
// If it's not ambiguous, it should say wide or narrow.
else
{
return width;
}
}
CATCH_LOG();
// If we got this far, we couldn't figure it out.
// It's better to be too wide than too narrow.
return CodepointWidth::Wide;
}
// Routine Description:
// - Checks the fallback function but caches the results until the font changes
// because the lookup function is usually very expensive and will return the same results
@ -474,47 +418,18 @@ CodepointWidth CodepointWidthDetector::_lookupGlyphWidthWithCache(const std::wst
// Arguments:
// - glyph - the utf16 encoded codepoint to check width of
// - true if codepoint is wide or false if it is narrow
bool CodepointWidthDetector::_checkFallbackViaCache(const std::wstring_view glyph) const
bool CodepointWidthDetector::_checkFallbackViaCache(uint32_t codepoint, const std::wstring_view& glyph) const
{
const std::wstring findMe{ glyph };
// TODO: Cache needs to be emptied when font changes.
const auto it = _fallbackCache.find(findMe);
if (it == _fallbackCache.end())
{
auto result = _pfnFallbackMethod(glyph);
_fallbackCache.insert_or_assign(findMe, result);
return result;
}
else
const auto it = _fallbackCache.find(codepoint);
if (it != _fallbackCache.end())
{
return it->second;
}
}
// Routine Description:
// - extract unicode codepoint from utf16 encoding
// Arguments:
// - glyph - the utf16 encoded codepoint convert
// Return Value:
// - the codepoint being stored
unsigned int CodepointWidthDetector::_extractCodepoint(const std::wstring_view glyph) noexcept
{
if (glyph.size() == 1)
{
return static_cast<unsigned int>(glyph.front());
}
else
{
const unsigned int mask = 0x3FF;
// leading bits, shifted over to make space for trailing bits
unsigned int codepoint = (glyph.at(0) & mask) << 10;
// trailing bits
codepoint |= (glyph.at(1) & mask);
// 0x10000 is subtracted from the codepoint to encode a surrogate pair, add it back
codepoint += 0x10000;
return codepoint;
}
const auto result = _pfnFallbackMethod(glyph);
_fallbackCache.insert_or_assign(codepoint, result);
return result;
}
// Method Description:
@ -527,9 +442,9 @@ unsigned int CodepointWidthDetector::_extractCodepoint(const std::wstring_view g
// - pfnFallback - the function to use as the fallback method.
// Return Value:
// - <none>
void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wstring_view)> pfnFallback)
void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wstring_view&)> pfnFallback) noexcept
{
_pfnFallbackMethod = pfnFallback;
_pfnFallbackMethod = std::move(pfnFallback);
}
// Method Description:
@ -542,5 +457,6 @@ void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wst
// - <none>
void CodepointWidthDetector::NotifyFontChanged() const noexcept
{
#pragma warning(suppress : 26447) // The function is declared 'noexcept' but calls function 'clear()' which may throw exceptions (f.6).
_fallbackCache.clear();
}

View file

@ -12,7 +12,7 @@ static CodepointWidthDetector widthDetector;
// Function Description:
// - determines if the glyph represented by the string of characters should be
// wide or not. See CodepointWidthDetector::IsWide
bool IsGlyphFullWidth(const std::wstring_view glyph)
bool IsGlyphFullWidth(const std::wstring_view& glyph) noexcept
{
return widthDetector.IsWide(glyph);
}
@ -35,7 +35,7 @@ bool IsGlyphFullWidth(const wchar_t wch) noexcept
// - pfnFallback - the function to use as the fallback method.
// Return Value:
// - <none>
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view)> pfnFallback)
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view&)> pfnFallback)
{
widthDetector.SetFallbackMethod(pfnFallback);
}

View file

@ -134,7 +134,7 @@ void TermControlUiaTextRange::_TranslatePointFromScreen(LPPOINT screenPoint) con
screenPoint->y = includeOffsets(screenPoint->y, boundingRect.top, padding.top, scaleFactor);
}
const COORD TermControlUiaTextRange::_getScreenFontSize() const
const COORD TermControlUiaTextRange::_getScreenFontSize() const noexcept
{
// Do NOT get the font info from IRenderData. It is a dummy font info.
// Instead, the font info is saved in the TermControl. So we have to

View file

@ -57,6 +57,6 @@ namespace Microsoft::Terminal
protected:
void _TranslatePointToScreen(LPPOINT clientPoint) const override;
void _TranslatePointFromScreen(LPPOINT screenPoint) const override;
const COORD _getScreenFontSize() const override;
const COORD _getScreenFontSize() const noexcept override;
};
}

View file

@ -1313,7 +1313,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetChildren(_Outptr_result_maybenull_ SAFEARRAY
#pragma endregion
const COORD UiaTextRangeBase::_getScreenFontSize() const
const COORD UiaTextRangeBase::_getScreenFontSize() const noexcept
{
COORD coordRet = _pData->GetFontInfo().GetSize();

View file

@ -146,7 +146,7 @@ namespace Microsoft::Console::Types
RECT _getTerminalRect() const;
virtual const COORD _getScreenFontSize() const;
virtual const COORD _getScreenFontSize() const noexcept;
const unsigned int _getViewportHeight(const SMALL_RECT viewport) const noexcept;
const Viewport _getOptimizedBufferSize() const noexcept;

View file

@ -16,24 +16,21 @@ Author:
#include "convert.hpp"
#include <functional>
static_assert(sizeof(unsigned int) == sizeof(wchar_t) * 2,
"UnicodeRange expects to be able to store a unicode codepoint in an unsigned int");
// use to measure the width of a codepoint
class CodepointWidthDetector final
{
public:
CodepointWidthDetector() noexcept;
CodepointWidthDetector() noexcept = default;
CodepointWidthDetector(const CodepointWidthDetector&) = delete;
CodepointWidthDetector(CodepointWidthDetector&&) = delete;
~CodepointWidthDetector() = default;
CodepointWidthDetector& operator=(const CodepointWidthDetector&) = delete;
CodepointWidthDetector& operator=(CodepointWidthDetector&&) = delete;
CodepointWidth GetWidth(const std::wstring_view glyph) const;
bool IsWide(const std::wstring_view glyph) const;
CodepointWidth GetWidth(const std::wstring_view& glyph) const noexcept;
bool IsWide(const std::wstring_view& glyph) const noexcept;
bool IsWide(const wchar_t wch) const noexcept;
void SetFallbackMethod(std::function<bool(const std::wstring_view)> pfnFallback);
void SetFallbackMethod(std::function<bool(const std::wstring_view&)> pfnFallback) noexcept;
void NotifyFontChanged() const noexcept;
#ifdef UNIT_TESTING
@ -41,11 +38,9 @@ public:
#endif
private:
CodepointWidth _lookupGlyphWidth(const std::wstring_view glyph) const;
CodepointWidth _lookupGlyphWidthWithCache(const std::wstring_view glyph) const noexcept;
bool _checkFallbackViaCache(const std::wstring_view glyph) const;
static unsigned int _extractCodepoint(const std::wstring_view glyph) noexcept;
CodepointWidth _lookupGlyphWidth(uint32_t codepoint) const;
bool _checkFallbackViaCache(uint32_t codepoint, const std::wstring_view& glyph) const;
mutable std::unordered_map<std::wstring, bool> _fallbackCache;
std::function<bool(std::wstring_view)> _pfnFallbackMethod;
mutable robin_hood::unordered_flat_map<uint32_t, bool> _fallbackCache;
std::function<bool(const std::wstring_view&)> _pfnFallbackMethod;
};

View file

@ -12,7 +12,7 @@ Abstract:
#include <functional>
#include <string_view>
bool IsGlyphFullWidth(const std::wstring_view glyph);
bool IsGlyphFullWidth(const std::wstring_view& glyph) noexcept;
bool IsGlyphFullWidth(const wchar_t wch) noexcept;
void SetGlyphWidthFallback(std::function<bool(std::wstring_view)> pfnFallback);
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view&)> pfnFallback);
void NotifyGlyphWidthFontChanged() noexcept;