Compare commits

...

2 Commits

Author SHA1 Message Date
Dustin L. Howett
f4327f32f6 Migrate spelling-0.0.21 changes from main 2022-08-10 23:42:07 +02:00
Leonard Hecker
296e1834fd wip 2022-08-10 23:42:07 +02:00
29 changed files with 1293 additions and 873 deletions

View File

@@ -6,6 +6,7 @@ File | Purpose | Format | Info
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)

View File

@@ -21,7 +21,7 @@ See the `README.md` in each directory for more information.
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
<details><summary>:clamp: If the flagged items are false positives</summary>
<details><summary>If the flagged items are :exploding_head: false positives</summary>
If items relate to a ...
* binary file (or some other file you wouldn't want to check at all).

View File

@@ -1,7 +1,7 @@
admins
allcolors
apc
Apc
apc
breadcrumb
breadcrumbs
bsd
@@ -14,8 +14,8 @@ CMMI
copyable
cybersecurity
dalet
dcs
Dcs
dcs
dialytika
dje
downside
@@ -34,10 +34,12 @@ gantt
gcc
geeksforgeeks
ghe
github
gje
godbolt
hostname
hostnames
https
hyperlink
hyperlinking
hyperlinks
@@ -54,9 +56,11 @@ Llast
llvm
Lmid
locl
lol
lorem
Lorigin
maxed
minimalistic
mkmk
mnt
mru
@@ -80,6 +84,7 @@ runtimes
shcha
slnt
Sos
ssh
timeline
timelines
timestamped
@@ -88,6 +93,7 @@ tokenizes
tonos
toolset
tshe
ubuntu
uiatextrange
UIs
und
@@ -96,5 +102,7 @@ versioned
vsdevcmd
We'd
wildcards
XBox
YBox
yeru
zhe

View File

@@ -32,10 +32,10 @@ DERR
dlldata
DNE
DONTADDTORECENT
DWMWA
DWORDLONG
DWMSBT
DWMWA
DWMWA
DWORDLONG
endfor
ENDSESSION
enumset
@@ -92,6 +92,7 @@ istream
IStringable
ITab
ITaskbar
itow
IUri
IVirtual
KEYSELECT
@@ -103,13 +104,14 @@ lround
Lsa
lsass
LSHIFT
LTGRAY
MAINWINDOW
memchr
memicmp
MENUCOMMAND
MENUDATA
MENUITEMINFOW
MENUINFO
MENUITEMINFOW
mmeapi
MOUSELEAVE
mov
@@ -146,6 +148,7 @@ OUTLINETEXTMETRICW
overridable
PACL
PAGESCROLL
PATINVERT
PEXPLICIT
PICKFOLDERS
pmr
@@ -155,8 +158,8 @@ rcx
REGCLS
RETURNCMD
rfind
roundf
ROOTOWNER
roundf
RSHIFT
SACL
schandle
@@ -208,6 +211,7 @@ UPDATEINIFILE
userenv
USEROBJECTFLAGS
Viewbox
virtualalloc
wcsstr
wcstoui
winmain

View File

@@ -0,0 +1,523 @@
# marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$
# marker for ignoring a comment to the end of the line
// #no-spell-check.*$
# patch hunk comments
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
# git index header
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
# cid urls
(['"])cid:.*?\g{-1}
# data url in parens
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
# data url in quotes
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
# data url
data:[-a-zA-Z=;:/0-9+]*,\S*
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# magnet urls
magnet:[?=:\w]+
# magnet urls
"magnet:[^"]+"
# obs:
"obs:[^"]*"
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
# In this examples content, I'm using a number of different ways to match things to show various approaches
# asciinema
\basciinema\.org/a/[0-9a-zA-Z]+
# apple
\bdeveloper\.apple\.com/[-\w?=/]+
# Apple music
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
# appveyor api
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
# appveyor project
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
# Amazon
# Amazon
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
# AWS S3
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
# AWS execute-api
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
# AWS ELB
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
# AWS SNS
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
# AWS VPC
vpc-\w+
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
# YouTube url
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
# YouTube music
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
# YouTube tag
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
# YouTube image
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
# Google Accounts
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
# Google Analytics
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
# Google APIs
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
# Google Storage
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
# Google Calendar
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
\w+\@group\.calendar\.google\.com\b
# Google DataStudio
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
# The leading `/` here is as opposed to the `\b` above
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
# Google Docs
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
# Google Drive
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
# Google Groups
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
# Google Maps
\bmaps\.google\.com/maps\?[\w&;=]*
# Google themes
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
# Google CDN
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
# Goo.gl
/goo\.gl/[a-zA-Z0-9]+
# Google Chrome Store
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
# Google Books
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
# Google Fonts
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
# Google Forms
\bforms\.gle/\w+
# Google Scholar
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
# Google Colab Research Drive
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
# GitHub SHAs (api)
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
# GitHub SHAs (markdown)
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
# GitHub SHAs
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
# GitHub wiki
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
# githubusercontent
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
# githubassets
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
# gist github
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
# git.io
\bgit\.io/[0-9a-zA-Z]+
# GitHub JSON
"node_id": "[-a-zA-Z=;:/0-9+]*"
# Contributor
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
# GHSA
GHSA(?:-[0-9a-z]{4}){3}
# GitLab commit
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
# GitLab merge requests
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
# GitLab uploads
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
# GitLab commits
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
# binanace
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# bitbucket diff
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
# bitbucket repositories commits
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bitbucket commits
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bit.ly
\bbit\.ly/\w+
# bitrise
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
# bootstrapcdn.com
\bbootstrapcdn\.com/[-./\w]+
# cdn.cloudflare.com
\bcdnjs\.cloudflare\.com/[./\w]+
# circleci
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
# gitter
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
# gravatar
\bgravatar\.com/avatar/[0-9a-f]+
# ibm
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
# imgur
\bimgur\.com/[^.]+
# Internet Archive
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
# discord
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
# Disqus
\bdisqus\.com/[-\w/%.()!?&=_]*
# medium link
\blink\.medium\.com/[a-zA-Z0-9]+
# medium
\bmedium\.com/\@?[^/\s"]+/[-\w]+
# microsoft
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
# powerbi
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
# vs devops
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
# microsoft store
\bmicrosoft\.com/store/apps/\w+
# mvnrepository.com
\bmvnrepository\.com/[-0-9a-z./]+
# now.sh
/[0-9a-z-.]+\.now\.sh\b
# oracle
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
# chromatic.com
/\S+.chromatic.com\S*[")]
# codacy
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
# compai
\bcompai\.pub/v1/png/[0-9a-f]+
# mailgun api
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
# mailgun
\b[0-9a-z]+.mailgun.org
# /message-id/
/message-id/[-\w@./%]+
# Reddit
\breddit\.com/r/[/\w_]*
# requestb.in
\brequestb\.in/[0-9a-z]+
# sched
\b[a-z0-9]+\.sched\.com\b
# Slack url
slack://[a-zA-Z0-9?&=]+
# Slack
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
# Slack edge
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
# Slack images
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
# shields.io
\bshields\.io/[-\w/%?=&.:+;,]*
# stackexchange -- https://stackexchange.com/feeds/sites
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
# Sentry
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
# Twitter markdown
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
# Twitter hashtag
\btwitter\.com/hashtag/[\w?_=&]*
# Twitter status
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
# Twitter profile images
\btwimg\.com/profile_images/[_\w./]*
# Twitter media
\btwimg\.com/media/[-_\w./?=]*
# Twitter link shortened
\bt\.co/\w+
# facebook
\bfburl\.com/[0-9a-z_]+
# facebook CDN
\bfbcdn\.net/[\w/.,]*
# facebook watch
\bfb\.watch/[0-9A-Za-z]+
# dropbox
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
# ipfs protocol
ipfs://[0-9a-z]*
# ipfs url
/ipfs/[0-9a-z]*
# w3
\bw3\.org/[-0-9a-zA-Z/#.]+
# loom
\bloom\.com/embed/[0-9a-f]+
# regex101
\bregex101\.com/r/[^/\s"]+/\d+
# figma
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
# freecodecamp.org
\bfreecodecamp\.org/[-\w/.]+
# image.tmdb.org
\bimage\.tmdb\.org/[/\w.]+
# mermaid
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
# Wikipedia
\ben\.wikipedia\.org/wiki/[-\w%.#]+
# gitweb
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
# HyperKitty lists
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
# lists
/thread\.html/[^"\s]+
# list-management
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
# kubectl.kubernetes.io/last-applied-configuration
"kubectl.kubernetes.io/last-applied-configuration": ".*"
# pgp
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
# Spotify
\bopen\.spotify\.com/embed/playlist/\w+
# Mastodon
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
# scastie
\bscastie\.scala-lang\.org/[^/]+/\w+
# images.unsplash.com
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
# pastebin
\bpastebin\.com/[\w/]+
# heroku
\b\w+\.heroku\.com/source/archive/\w+
# quip
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
# badgen.net
\bbadgen\.net/badge/[^")\]'\s]+
# statuspage.io
\w+\.statuspage\.io\b
# media.giphy.com
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
# tinyurl
\btinyurl\.com/\w+
# getopts
\bgetopts\s+(?:"[^"]+"|'[^']+')
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
# URL escaped characters
\%[0-9A-F][A-F]
# IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
# c99 hex digits (not the full format, just one I've seen)
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
# Punycode
\bxn--[-0-9a-z]+
# sha
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
# sha-... -- uses a fancy capture
(['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs
\b[0-9a-fA-F]{16,}\b
# hex in url queries
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
# ssh
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
# PGP
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
# GPG keys
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
# Well known gpg keys
.well-known/openpgpkey/[\w./]+
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
# integrity
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
# https://www.gnu.org/software/groff/manual/groff.html
# man troff content
\\f[BCIPR]
# '
\\\(aq
# .desktop mime types
^MimeTypes?=.*$
# .desktop localized entries
^[A-Z][a-z]+\[[a-z]+\]=.*$
# Localized .desktop content
Name\[[^\]]+\]=.*
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# crypt
"\$2[ayb]\$.{56}"
# scrypt / argon
\$(?:scrypt|argon\d+[di]*)\$\S+
# Input to GitHub JSON
content: "[-a-zA-Z=;:/0-9+]*="
# Python stringprefix / binaryprefix
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+
# JavaScript regular expressions
# javascript test regex
/.*/[gim]*\.test\(
# javascript match regex
\.match\(/[^/\s"]*/[gim]*\s*
# javascript match regex
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
# javascript regex
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
# javascript replace regex
\.replace\(/[^/\s"]*/[gim]*\s*,
# Go regular expressions
regexp?\.MustCompile\(`[^`]*`\)
# sed regular expressions
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+
# kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
# kubectl - pods in CrashLoopBackOff
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
# kubernetes object suffix
-[0-9a-f]{10}-\w{5}\s
# posthog secrets
posthog\.init\((['"])phc_[^"',]+\g{-1},
# xcode
# xcodeproject scenes
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
# xcode api botches
customObjectInstantitationMethod
# font awesome classes
\.fa-[-a-z0-9]+
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
## You could manually change `(?i)X...` to use `[Xx]...`
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
# Lorem
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
# ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b
# Note that the next example is no longer necessary if you are using
# to match a string starting with a `#`, use a character-class:
[#]backwards
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# Compiler flags (Scala)
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (linker)
,-B
# curl arguments
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# set arguments
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# macOS temp folders
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/

View File

@@ -2,14 +2,14 @@
(?:(?i)\.png$)
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)3rdparty/
(?:^|/)dirs$
(?:^|/)go\.mod$
(?:^|/)go\.sum$
(?:^|/)package(?:-lock|)\.json$
(?:^|/)sources(?:|\.dep)$
(?:^|/)vendor/
ignore$
SUMS$
\.a$
\.ai$
\.avi$
\.bmp$
@@ -20,6 +20,8 @@ SUMS$
\.crt$
\.csr$
\.dll$
\.docx?$
\.drawio$
\.DS_Store$
\.eot$
\.eps$
@@ -31,6 +33,7 @@ SUMS$
\.icns$
\.ico$
\.jar$
\.jks$
\.jpeg$
\.jpg$
\.key$
@@ -41,6 +44,7 @@ SUMS$
\.mod$
\.mp3$
\.mp4$
\.o$
\.ocf$
\.otf$
\.pbxproj$
@@ -48,22 +52,41 @@ SUMS$
\.pem$
\.png$
\.psd$
\.pyc$
\.runsettings$
\.s$
\.sig$
\.so$
\.svg$
\.svgz$
\.svgz?$
\.tar$
\.tgz$
\.tiff?$
\.ttf$
\.vsdx$
\.wav$
\.webm$
\.webp$
\.woff
\.woff2?$
\.xcf$
\.xls
\.xlsx?$
\.xpm$
\.yml$
\.zip$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.git-blame-ignore-revs\E$
^\Q.github/workflows/spelling.yml\E$
^\Qdoc/reference/windows-terminal-logo.ans\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
^build/config/
^consolegit2gitfilters\.json$
^dep/
@@ -90,12 +113,5 @@ SUMS$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ut_types/UtilsTests.cpp$
^tools/ReleaseEngineering/ServicingPipeline.ps1$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.github/workflows/spelling.yml\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
ignore$
SUMS$

View File

@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
AAAAABBBBBBCCC
abcd
abcd
abcde
abcdef
ABCDEFG
ABCDEFGH
ABCDEFGHIJ
abcdefghijk
ABCDEFGHIJKLMNO
abcdefghijklmnop
ABCDEFGHIJKLMNOPQRST
abcdefghijklmnopqrstuvwxyz
ABCG
ABE
abf
BBBBB
BBBBBBBB
BBBBBBBBBBBBBBDDDD
BBBBBCCC
BBBBCCCCC
BBGGRR
CCE
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
http
www
WCAG
winui
appshellintegration

View File

@@ -1,3 +1,11 @@
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
# \bm_data\b
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
# to use this:
#\bfit\(
# s.b. GitHub
\bGithub\b
@@ -16,6 +24,12 @@
# s.b. greater than
\bgreater then\b
# s.b. into
#\sin to\s
# s.b. opt-in
\sopt in\s
# s.b. less than
\bless then\b
@@ -27,10 +41,22 @@
\b[Nn]o[nt][- ]existent\b
# s.b. preexisting
[Pp]re-existing
[Pp]re[- ]existing
# s.b. preempt
[Pp]re[- ]empt\b
# s.b. preemptively
[Pp]re-emptively
[Pp]re[- ]emptively
# s.b. reentrancy
[Rr]e[- ]entrancy
# s.b. reentrant
[Rr]e[- ]entrant
# s.b. workaround(s)
#\bwork[- ]arounds?\b
# Reject duplicate words
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s

View File

@@ -27,13 +27,68 @@ ROY\sG\.\sBIV
# Python stringprefix / binaryprefix
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
# Automatically suggested patterns
# hit-count: 3831 file-count: 582
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# hit-count: 71 file-count: 35
# Compiler flags
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 41 file-count: 28
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# hit-count: 20 file-count: 9
# hex runs
\b[0-9a-fA-F]{16,}\b
# hit-count: 10 file-count: 7
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hit-count: 4 file-count: 4
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# hit-count: 4 file-count: 1
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
# hit-count: 2 file-count: 1
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# hit-count: 1 file-count: 1
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
# hit-count: 1 file-count: 1
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
# hit-count: 1 file-count: 1
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# acceptable duplicates
# ls directory listings
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
# C/idl types + English ...
\s(Guid|long|LONG|that) \g{-1}\s
# javadoc / .net
(?:\@(?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
# Commit message -- Signed-off-by and friends
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
# Autogenerated revert commit message
^This reverts commit [0-9a-f]{40}\.$
# vtmode
--vtmode\s+(\w+)\s+\g{-1}\s

View File

@@ -1,31 +1,12 @@
benefitting
occurences?
Sorce
^attache$
^attacher$
^attachers$
benefitting
occurences?
^dependan.*
^oer$
^spae$
^spae-man$
^spaebook$
^spaecraft$
^spaed$
^spaedom$
^spaeing$
^spaeings$
^spaeman$
^spaer$
^Spaerobee$
^spaes$
^spaewife$
^spaewoman$
^spaework$
^spaewright$
Sorce
^[Ss]pae.*
^untill$
^untilling$
^wether$
^wether.*
^wethers$
^wetherteg$
^[Ss]pae.*

View File

@@ -1,10 +1,57 @@
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
name: Spell checking
# Comment management is handled through a secondary job, for details see:
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
#
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
# it needs `contents: write` in order to add a comment.
#
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
# it needs `pull-requests: write` in order to manipulate those comments.
# Updating pull request branches is managed via comment handling.
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
#
# These elements work together to make it happen:
#
# `on.issue_comment`
# This event listens to comments by users asking to update the metadata.
#
# `jobs.update`
# This job runs in response to an issue_comment and will push a new commit
# to update the spelling metadata.
#
# `with.experimental_apply_changes_via_bot`
# Tells the action to support and generate messages that enable it
# to make a commit to update the spelling metadata.
#
# `with.ssh_key`
# In order to trigger workflows when the commit is made, you can provide a
# secret (typically, a write-enabled github deploy key).
#
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
on:
pull_request_target:
push:
branches: ["**"]
tags-ignore: ["**"]
branches:
- "**"
tags-ignore:
- "**"
pull_request_target:
branches:
- "**"
tags-ignore:
- "**"
types:
- 'opened'
- 'reopened'
- 'synchronize'
issue_comment:
types:
- 'created'
jobs:
spelling:
@@ -24,23 +71,64 @@ jobs:
steps:
- name: check-spelling
id: spelling
uses: check-spelling/check-spelling@v0.0.20
uses: check-spelling/check-spelling@v0.0.21
with:
suppress_push_for_open_pull_request: 1
checkout: true
check_file_names: 1
spell_check_this: check-spelling/spell-check-this@prerelease
post_comment: 0
use_magic_file: 1
extra_dictionary_limit: 10
extra_dictionaries:
cspell:software-terms/src/software-terms.txt
cspell:python/src/python/python-lib.txt
cspell:node/node.txt
cspell:cpp/src/stdlib-c.txt
cspell:cpp/src/stdlib-cpp.txt
cspell:fullstack/fullstack.txt
cspell:filetypes/filetypes.txt
cspell:html/html.txt
cspell:cpp/src/compiler-msvc.txt
cspell:python/src/common/extra.txt
cspell:powershell/powershell.txt
cspell:aws/aws.txt
cspell:cpp/src/lang-keywords.txt
cspell:npm/npm.txt
cspell:dotnet/dotnet.txt
cspell:python/src/python/python.txt
cspell:css/css.txt
cspell:cpp/src/stdlib-cmath.txt
check_extra_dictionaries: ''
comment:
name: Report
comment-push:
name: Report (Push)
# If your workflow isn't running on push, you can remove this job
runs-on: ubuntu-latest
needs: spelling
permissions:
contents: write
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name != 'push'
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.20
uses: check-spelling/check-spelling@v0.0.21
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }}
comment-pr:
name: Report (PR)
# If you workflow isn't running on pull_request*, you can remove this job
runs-on: ubuntu-latest
needs: spelling
permissions:
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.21
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }}

View File

@@ -12,20 +12,8 @@
// Arguments:
// - ulSize - The height of the cursor within this buffer
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_parentBuffer{ parentBuffer },
_fHasMoved(false),
_fIsVisible(true),
_fIsOn(true),
_fIsDouble(false),
_fBlinkingAllowed(true),
_fDelay(false),
_fIsConversionArea(false),
_fIsPopupShown(false),
_fDelayedEolWrap(false),
_fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false),
_ulSize(ulSize),
_cursorType(CursorType::Legacy)
_parentBuffer{ &parentBuffer },
_ulSize(ulSize)
{
}
@@ -185,7 +173,7 @@ void Cursor::_RedrawCursorAlways() noexcept
{
try
{
_parentBuffer.TriggerRedrawCursor(_cPosition);
_parentBuffer->TriggerRedrawCursor(_cPosition);
}
CATCH_LOG();
}

View File

@@ -27,6 +27,7 @@ public:
// the following values are used to create the textmode cursor.
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
Cursor() noexcept = default;
Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept;
~Cursor();
@@ -84,7 +85,7 @@ public:
void SetType(const CursorType type) noexcept;
private:
TextBuffer& _parentBuffer;
TextBuffer* _parentBuffer = nullptr;
//TODO: separate the rendering and text placement
@@ -92,25 +93,25 @@ private:
til::point _cPosition; // current position on screen (in screen buffer coords).
bool _fHasMoved;
bool _fIsVisible; // whether cursor is visible (set only through the API)
bool _fIsOn; // whether blinking cursor is on or not
bool _fIsDouble; // whether the cursor size should be doubled
bool _fBlinkingAllowed; //Whether or not the cursor is allowed to blink at all. only set through VT (^[[?12h/l)
bool _fDelay; // don't blink scursor on next timer message
bool _fIsConversionArea; // is attached to a conversion area so it doesn't actually need to display the cursor.
bool _fIsPopupShown; // if a popup is being shown, turn off, stop blinking.
bool _fHasMoved = false;
bool _fIsVisible = true; // whether cursor is visible (set only through the API)
bool _fIsOn = true; // whether blinking cursor is on or not
bool _fIsDouble = false; // whether the cursor size should be doubled
bool _fBlinkingAllowed = true; //Whether or not the cursor is allowed to blink at all. only set through VT (^[[?12h/l)
bool _fDelay = false; // don't blink scursor on next timer message
bool _fIsConversionArea = false; // is attached to a conversion area so it doesn't actually need to display the cursor.
bool _fIsPopupShown = false; // if a popup is being shown, turn off, stop blinking.
bool _fDelayedEolWrap; // don't wrap at EOL till the next char comes in.
bool _fDelayedEolWrap = false; // don't wrap at EOL till the next char comes in.
til::point _coordDelayedAt; // coordinate the EOL wrap was delayed at.
bool _fDeferCursorRedraw; // whether we should defer redrawing the cursor or not
bool _fHaveDeferredCursorRedraw; // have we been asked to redraw the cursor while it was being deferred?
bool _fDeferCursorRedraw = false; // whether we should defer redrawing the cursor or not
bool _fHaveDeferredCursorRedraw = false; // have we been asked to redraw the cursor while it was being deferred?
ULONG _ulSize;
ULONG _ulSize = 0;
void _RedrawCursor() noexcept;
void _RedrawCursorAlways() noexcept;
CursorType _cursorType;
CursorType _cursorType = CursorType::Legacy;
};

View File

@@ -35,16 +35,10 @@ TextBuffer::TextBuffer(const til::size screenBufferSize,
const UINT cursorSize,
const bool isActiveBuffer,
Microsoft::Console::Render::Renderer& renderer) :
_firstRow{ 0 },
_currentAttributes{ defaultAttributes },
_cursor{ cursorSize, *this },
_storage{},
_unicodeStorage{},
_currentAttributes{ defaultAttributes },
_isActiveBuffer{ isActiveBuffer },
_renderer{ renderer },
_size{},
_currentHyperlinkId{ 1 },
_currentPatternId{ 0 }
_renderer{ &renderer }
{
// initialize ROWs
_storage.reserve(gsl::narrow<size_t>(screenBufferSize.Y));
@@ -56,6 +50,40 @@ TextBuffer::TextBuffer(const til::size screenBufferSize,
_UpdateSize();
}
// Routine Description:
// - Copies the viewport from another text buffer into this one.
// Arguments:
// - OtherBuffer - The text buffer to copy from
// Return Value:
// - <none>
void TextBuffer::CopyViewport(const TextBuffer& other, const Viewport& viewport)
{
const auto top = viewport.Top();
const auto dimensions = viewport.Dimensions();
auto self = this;
if (self->_size.Dimensions() != dimensions)
{
self->~TextBuffer();
try
{
self = new (this) TextBuffer{ dimensions, other.GetCurrentAttributes(), 0, true, *other._renderer };
}
catch (...)
{
self = new (this) TextBuffer{};
throw;
}
}
for (til::CoordType i = 0; i < dimensions.height; ++i)
{
self->GetRowByOffset(i) = other.GetRowByOffset(top + i);
}
self->CopyProperties(other);
}
// Routine Description:
// - Copies properties from another text buffer into this one.
// - This is primarily to copy properties that would otherwise not be specified during CreateInstance
@@ -558,7 +586,7 @@ bool TextBuffer::IncrementCircularBuffer(const bool inVtMode)
// to the logical position 0 in the window (cursor coordinates and all other coordinates).
if (_isActiveBuffer)
{
_renderer.TriggerFlush(true);
_renderer->TriggerFlush(true);
}
// Prune hyperlinks to delete obsolete references
@@ -968,14 +996,14 @@ bool TextBuffer::IsActiveBuffer() const noexcept
Microsoft::Console::Render::Renderer& TextBuffer::GetRenderer() noexcept
{
return _renderer;
return *_renderer;
}
void TextBuffer::TriggerRedraw(const Viewport& viewport)
{
if (_isActiveBuffer)
{
_renderer.TriggerRedraw(viewport);
_renderer->TriggerRedraw(viewport);
}
}
@@ -983,7 +1011,7 @@ void TextBuffer::TriggerRedrawCursor(const til::point position)
{
if (_isActiveBuffer)
{
_renderer.TriggerRedrawCursor(&position);
_renderer->TriggerRedrawCursor(&position);
}
}
@@ -991,7 +1019,7 @@ void TextBuffer::TriggerRedrawAll()
{
if (_isActiveBuffer)
{
_renderer.TriggerRedrawAll();
_renderer->TriggerRedrawAll();
}
}
@@ -999,7 +1027,7 @@ void TextBuffer::TriggerScroll()
{
if (_isActiveBuffer)
{
_renderer.TriggerScroll();
_renderer->TriggerScroll();
}
}
@@ -1007,7 +1035,7 @@ void TextBuffer::TriggerScroll(const til::point delta)
{
if (_isActiveBuffer)
{
_renderer.TriggerScroll(&delta);
_renderer->TriggerScroll(&delta);
}
}
@@ -1015,7 +1043,7 @@ void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText)
{
if (_isActiveBuffer)
{
_renderer.TriggerNewTextNotification(newText);
_renderer->TriggerNewTextNotification(newText);
}
}

View File

@@ -68,6 +68,7 @@ namespace Microsoft::Console::Render
class TextBuffer final
{
public:
TextBuffer() noexcept = default;
TextBuffer(const til::size screenBufferSize,
const TextAttribute defaultAttributes,
const UINT cursorSize,
@@ -76,6 +77,7 @@ public:
TextBuffer(const TextBuffer& a) = delete;
// Used for duplicating properties to another text buffer
void CopyViewport(const TextBuffer& OtherBuffer, const Microsoft::Console::Types::Viewport& viewport);
void CopyProperties(const TextBuffer& OtherBuffer) noexcept;
// row manipulation
@@ -220,19 +222,19 @@ private:
std::vector<ROW> _storage;
Cursor _cursor;
til::CoordType _firstRow; // indexes top row (not necessarily 0)
til::CoordType _firstRow = 0; // indexes top row (not necessarily 0)
TextAttribute _currentAttributes;
// storage location for glyphs that can't fit into the buffer normally
UnicodeStorage _unicodeStorage;
bool _isActiveBuffer;
Microsoft::Console::Render::Renderer& _renderer;
bool _isActiveBuffer = false;
Microsoft::Console::Render::Renderer* _renderer = nullptr;
std::unordered_map<uint16_t, std::wstring> _hyperlinkMap;
std::unordered_map<std::wstring, uint16_t> _hyperlinkCustomIdMap;
uint16_t _currentHyperlinkId;
uint16_t _currentHyperlinkId = 1;
void _RefreshRowIDs(std::optional<til::CoordType> newRowWidth);
@@ -263,7 +265,7 @@ private:
static void _AppendRTFText(std::ostringstream& contentBuilder, const std::wstring_view& text);
std::unordered_map<size_t, std::wstring> _idsAndPatterns;
size_t _currentPatternId;
size_t _currentPatternId = 0;
#ifdef UNIT_TESTING
friend class TextBufferTests;

View File

@@ -234,7 +234,7 @@ const std::vector<Microsoft::Console::Render::RenderOverlay> RenderData::GetOver
// (e.g. 0,0 is the origin of the text buffer above, not the placement within the visible viewport)
const auto used = Viewport::FromInclusive(composition.GetAreaBufferInfo().rcViewCaWindow);
overlays.emplace_back(Microsoft::Console::Render::RenderOverlay{ textBuffer, origin, used });
overlays.emplace_back(Microsoft::Console::Render::RenderOverlay{ &textBuffer, origin, used });
}
}
}

View File

@@ -370,14 +370,14 @@ try
{
for (const auto& ch : cluster.GetText())
{
_api.bufferLine.emplace_back(ch);
_api.bufferLineColumn.emplace_back(column);
_api.bufferLine.push_back(ch);
_api.bufferLineColumn.push_back(column);
}
column += gsl::narrow_cast<u16>(cluster.GetColumns());
}
_api.bufferLineColumn.emplace_back(column);
_api.bufferLineColumn.push_back(column);
const BufferLineMetadata metadata{ _api.currentColor, _api.flags };
std::fill_n(_api.bufferLineMetadata.data() + x, column - x, metadata);

View File

@@ -986,7 +986,7 @@ namespace Microsoft::Console::Render
// This structure is loosely sorted in chunks from "very often accessed together"
// to seldom accessed and/or usually not together.
std::vector<wchar_t> bufferLine;
std::wstring bufferLine;
std::vector<u16> bufferLineColumn;
Buffer<BufferLineMetadata> bufferLineMetadata;
std::vector<TextAnalysisSinkResult> analysisResults;

View File

@@ -48,5 +48,11 @@
#include <base/numerics/safe_math.h>
#pragma warning(pop)
#define USE_INTERVAL_TREE_NAMESPACE
#include <IntervalTree.h>
// Boost
#include <boost/container/small_vector.hpp>
#include <til.h>
#include <til/bit.h>

View File

@@ -0,0 +1,136 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "../inc/IRenderData.hpp"
#include "../buffer/out/textBuffer.hpp"
using namespace Microsoft::Console;
using namespace Microsoft::Console::Render;
__declspec(noinline) void RenderData::Snapshot(IRenderData* other)
{
viewport = other->GetViewport();
textBuffer.CopyViewport(other->GetTextBuffer(), viewport);
fontInfo = other->GetFontInfo();
selectionRects = other->GetSelectionRects();
cursorPosition = other->GetCursorPosition();
cursorVisible = other->IsCursorVisible();
cursorOn = other->IsCursorOn();
cursorHeight = other->GetCursorHeight();
cursorStyle = other->GetCursorStyle();
cursorPixelWidth = other->GetCursorPixelWidth();
cursorDoubleWidth = other->IsCursorDoubleWidth();
overlays = other->GetOverlays();
gridLineDrawingAllowed = other->IsGridLineDrawingAllowed();
consoleTitle = other->GetConsoleTitle();
assert(viewport.Top() == 0);
assert(viewport.Left() == 0);
viewport = viewport.ToOrigin();
}
Types::Viewport RenderData::GetViewport() noexcept
{
return viewport;
}
til::point RenderData::GetTextBufferEndPosition() const noexcept
{
std::terminate();
}
const TextBuffer& RenderData::GetTextBuffer() const noexcept
{
return textBuffer;
}
const FontInfo& RenderData::GetFontInfo() const noexcept
{
return fontInfo;
}
std::vector<Types::Viewport> RenderData::GetSelectionRects() noexcept
{
return selectionRects;
}
void RenderData::LockConsole() noexcept
{
std::terminate();
}
void RenderData::UnlockConsole() noexcept
{
std::terminate();
}
til::point RenderData::GetCursorPosition() const noexcept
{
return cursorPosition;
}
bool RenderData::IsCursorVisible() const noexcept
{
return cursorVisible;
}
bool RenderData::IsCursorOn() const noexcept
{
return cursorOn;
}
ULONG RenderData::GetCursorHeight() const noexcept
{
return cursorHeight;
}
CursorType RenderData::GetCursorStyle() const noexcept
{
return cursorStyle;
}
ULONG RenderData::GetCursorPixelWidth() const noexcept
{
return cursorPixelWidth;
}
bool RenderData::IsCursorDoubleWidth() const
{
return cursorDoubleWidth;
}
const std::vector<RenderOverlay> RenderData::GetOverlays() const noexcept
{
return overlays;
}
const bool RenderData::IsGridLineDrawingAllowed() noexcept
{
return gridLineDrawingAllowed;
}
const std::wstring_view RenderData::GetConsoleTitle() const noexcept
{
return consoleTitle;
}
const std::wstring RenderData::GetHyperlinkUri(uint16_t id) const noexcept
{
UNREFERENCED_PARAMETER(id);
std::terminate();
}
const std::wstring RenderData::GetHyperlinkCustomId(uint16_t id) const noexcept
{
UNREFERENCED_PARAMETER(id);
std::terminate();
}
const std::vector<size_t> RenderData::GetPatternId(const til::point location) const noexcept
{
UNREFERENCED_PARAMETER(location);
return {};
}

View File

@@ -15,6 +15,7 @@
<ClCompile Include="..\FontInfoBase.cpp" />
<ClCompile Include="..\FontInfoDesired.cpp" />
<ClCompile Include="..\FontResource.cpp" />
<ClCompile Include="..\IRenderData.cpp" />
<ClCompile Include="..\RenderEngineBase.cpp" />
<ClCompile Include="..\RenderSettings.cpp" />
<ClCompile Include="..\renderer.cpp" />
@@ -42,4 +43,4 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

View File

@@ -45,6 +45,9 @@
<ClCompile Include="..\RenderSettings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\IRenderData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\precomp.h">

View File

@@ -15,11 +15,14 @@ static constexpr auto maxRetriesForRenderEngine = 3;
// The renderer will wait this number of milliseconds * how many tries have elapsed before trying again.
static constexpr auto renderBackoffBaseTimeMilliseconds{ 150 };
#define FOREACH_ENGINE(var) \
for (auto var : _engines) \
if (!var) \
break; \
else
#define FOREACH_ENGINE(var) for (auto var : _engines)
// See Renderer::Renderer
BaseRenderer::BaseRenderer(const RenderSettings& renderSettings, std::unique_ptr<RenderThread> thread) noexcept :
_renderSettings(renderSettings),
_pThread{ std::move(thread) }
{
}
// Routine Description:
// - Creates a new renderer controller for a console.
@@ -33,9 +36,8 @@ Renderer::Renderer(const RenderSettings& renderSettings,
_In_reads_(cEngines) IRenderEngine** const rgpEngines,
const size_t cEngines,
std::unique_ptr<RenderThread> thread) :
_renderSettings(renderSettings),
_pData(pData),
_pThread{ std::move(thread) }
BaseRenderer{ renderSettings, std::move(thread) },
_pData(pData)
{
for (size_t i = 0; i < cEngines; i++)
{
@@ -49,7 +51,7 @@ Renderer::Renderer(const RenderSettings& renderSettings,
// - <none>
// Return Value:
// - <none>
Renderer::~Renderer()
BaseRenderer::~BaseRenderer()
{
// RenderThread blocks until it has shut down.
_destructing = true;
@@ -64,6 +66,23 @@ Renderer::~Renderer()
// - HRESULT S_OK, GDI error, Safe Math error, or state/argument errors.
[[nodiscard]] HRESULT Renderer::PaintFrame()
{
if (_destructing || _engines.empty())
{
return S_FALSE;
}
try
{
_pData->LockConsole();
auto unlock = wil::scope_exit([&]() {
_pData->UnlockConsole();
});
_snapshot.Snapshot(_pData);
}
CATCH_RETURN()
_pDataRef = _pData;
FOREACH_ENGINE(pEngine)
{
auto tries = maxRetriesForRenderEngine;
@@ -74,7 +93,14 @@ Renderer::~Renderer()
return S_FALSE;
}
const auto hr = _PaintFrameForEngine(pEngine);
#if 0
_pData->LockConsole();
const auto hr = _PaintFrameForEngine(pEngine, _pData);
_pData->UnlockConsole();
#else
const auto hr = _PaintFrameForEngine(pEngine, &_snapshot);
#endif
if (E_PENDING == hr)
{
if (--tries == 0)
@@ -104,18 +130,13 @@ Renderer::~Renderer()
return S_OK;
}
[[nodiscard]] HRESULT Renderer::_PaintFrameForEngine(_In_ IRenderEngine* const pEngine) noexcept
[[nodiscard]] HRESULT BaseRenderer::_PaintFrameForEngine(_In_ IRenderEngine* const pEngine, IRenderData* _pData) noexcept
try
{
FAIL_FAST_IF_NULL(pEngine); // This is a programming error. Fail fast.
_pData->LockConsole();
auto unlock = wil::scope_exit([&]() {
_pData->UnlockConsole();
});
// Last chance check if anything scrolled without an explicit invalidate notification since the last frame.
_CheckViewportAndScroll();
_CheckViewportAndScroll(_pData);
// Try to start painting a frame
const auto hr = pEngine->StartPaint();
@@ -142,38 +163,35 @@ try
});
// A. Prep Colors
RETURN_IF_FAILED(_UpdateDrawingBrushes(pEngine, {}, false, true));
RETURN_IF_FAILED(_UpdateDrawingBrushes(pEngine, _pData, {}, false, true));
// B. Perform Scroll Operations
RETURN_IF_FAILED(_PerformScrolling(pEngine));
// C. Prepare the engine with additional information before we start drawing.
RETURN_IF_FAILED(_PrepareRenderInfo(pEngine));
RETURN_IF_FAILED(_PrepareRenderInfo(pEngine, _pData));
// 1. Paint Background
RETURN_IF_FAILED(_PaintBackground(pEngine));
// 2. Paint Rows of Text
_PaintBufferOutput(pEngine);
_PaintBufferOutput(pEngine, _pData);
// 3. Paint overlays that reside above the text buffer
_PaintOverlays(pEngine);
_PaintOverlays(pEngine, _pData);
// 4. Paint Selection
_PaintSelection(pEngine);
_PaintSelection(pEngine, _pData);
// 5. Paint Cursor
_PaintCursor(pEngine);
_PaintCursor(pEngine, _pData);
// 6. Paint window title
RETURN_IF_FAILED(_PaintTitle(pEngine));
RETURN_IF_FAILED(_PaintTitle(pEngine, _pData));
// Force scope exit end paint to finish up collecting information and possibly painting
endPaint.reset();
// Force scope exit unlock to let go of global lock so other threads can run
unlock.reset();
// Trigger out-of-lock presentation for renderers that can support it
RETURN_IF_FAILED(pEngine->Present());
@@ -182,7 +200,7 @@ try
}
CATCH_RETURN()
void Renderer::NotifyPaintFrame() noexcept
void BaseRenderer::NotifyPaintFrame() const noexcept
{
// If we're running in the unittests, we might not have a render thread.
if (_pThread)
@@ -343,7 +361,9 @@ void Renderer::TriggerTeardown() noexcept
if (SUCCEEDED(hr) && fEngineRequestsRepaint)
{
LOG_IF_FAILED(_PaintFrameForEngine(pEngine));
_pData->LockConsole();
LOG_IF_FAILED(_PaintFrameForEngine(pEngine, _pData));
_pData->UnlockConsole();
}
}
}
@@ -359,7 +379,7 @@ void Renderer::TriggerSelection()
try
{
// Get selection rectangles
auto rects = _GetSelectionRects();
auto rects = _GetSelectionRects(_pData);
// Make a viewport representing the coordinates that are currently presentable.
const til::rect viewport{ _pData->GetViewport().Dimensions() };
@@ -389,7 +409,7 @@ void Renderer::TriggerSelection()
// - <none>
// Return Value:
// - True if something changed and we scrolled. False otherwise.
bool Renderer::_CheckViewportAndScroll()
bool BaseRenderer::_CheckViewportAndScroll(IRenderData* _pData)
{
const auto srOldViewport = _viewport.ToInclusive();
const auto srNewViewport = _pData->GetViewport().ToInclusive();
@@ -425,7 +445,7 @@ bool Renderer::_CheckViewportAndScroll()
// - <none>
void Renderer::TriggerScroll()
{
if (_CheckViewportAndScroll())
if (_CheckViewportAndScroll(_pData))
{
NotifyPaintFrame();
}
@@ -461,7 +481,7 @@ void Renderer::TriggerScroll(const til::point* const pcoordDelta)
// - <none>
void Renderer::TriggerFlush(const bool circling)
{
const auto rects = _GetSelectionRects();
const auto rects = _GetSelectionRects(_pData);
FOREACH_ENGINE(pEngine)
{
@@ -473,7 +493,9 @@ void Renderer::TriggerFlush(const bool circling)
if (SUCCEEDED(hr) && fEngineRequestsRepaint)
{
LOG_IF_FAILED(_PaintFrameForEngine(pEngine));
_pData->LockConsole();
LOG_IF_FAILED(_PaintFrameForEngine(pEngine, _pData));
_pData->UnlockConsole();
}
}
}
@@ -509,7 +531,7 @@ void Renderer::TriggerNewTextNotification(const std::wstring_view newText)
// - pEngine: the engine to update the title for.
// Return Value:
// - the HRESULT of the underlying engine's UpdateTitle call.
HRESULT Renderer::_PaintTitle(IRenderEngine* const pEngine)
HRESULT BaseRenderer::_PaintTitle(IRenderEngine* const pEngine, IRenderData* _pData)
{
const auto newTitle = _pData->GetConsoleTitle();
return pEngine->UpdateTitle(newTitle);
@@ -561,7 +583,7 @@ void Renderer::UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const
// We initially tried to have a "_isSoftFontChar" member function, but MSVC
// failed to inline it at _all_ call sites (check invocations inside loops).
// This issue strangely doesn't occur with static functions.
bool Renderer::s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSoftFontChar, const size_t lastSoftFontChar)
bool BaseRenderer::s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSoftFontChar, const size_t lastSoftFontChar)
{
return v.size() == 1 && v[0] >= firstSoftFontChar && v[0] <= lastSoftFontChar;
}
@@ -663,7 +685,7 @@ void Renderer::WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs)
// - <none>
// Return Value:
// - <none>
[[nodiscard]] HRESULT Renderer::_PaintBackground(_In_ IRenderEngine* const pEngine)
[[nodiscard]] HRESULT BaseRenderer::_PaintBackground(_In_ IRenderEngine* const pEngine)
{
return pEngine->PaintBackground();
}
@@ -676,7 +698,7 @@ void Renderer::WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs)
// - <none>
// Return Value:
// - <none>
void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
void BaseRenderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine, IRenderData* _pData)
{
// This is the subsection of the entire screen buffer that is currently being presented.
// It can move left/right or top/bottom depending on how the viewport is scrolled
@@ -747,7 +769,7 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
LOG_IF_FAILED(pEngine->PrepareLineTransform(lineRendition, screenPosition.Y, view.Left()));
// Ask the helper to paint through this specific line.
_PaintBufferOutputHelper(pEngine, it, screenPosition, lineWrapped);
_PaintBufferOutputHelper(pEngine, _pData, it, screenPosition, lineWrapped);
}
}
}
@@ -758,11 +780,21 @@ static bool _IsAllSpaces(const std::wstring_view v)
return v.find_first_not_of(L' ') == decltype(v)::npos;
}
void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
TextBufferCellIterator it,
const til::point target,
const bool lineWrapped)
void BaseRenderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
IRenderData* _pData,
TextBufferCellIterator it,
const til::point target,
const bool lineWrapped)
{
const auto& referenceBuffer = _pDataRef->GetTextBuffer();
const auto& actualBuffer = _pData->GetTextBuffer();
const auto reference = referenceBuffer.GetRowByOffset(0).GetText();
const auto actual = actualBuffer.GetRowByOffset(0).GetText();
if (reference != actual)
{
__debugbreak();
}
auto globalInvert{ _renderSettings.GetRenderMode(RenderSettings::Mode::ScreenReversed) };
// If we have valid data, let's figure out how to draw it.
@@ -797,7 +829,7 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
const auto currentPatternId = patternIds;
// Update the drawing brushes with our color and font usage.
THROW_IF_FAILED(_UpdateDrawingBrushes(pEngine, currentRunColor, usingSoftFont, false));
THROW_IF_FAILED(_UpdateDrawingBrushes(pEngine, _pData, currentRunColor, usingSoftFont, false));
// Advance the point by however many columns we've just outputted and reset the accumulator.
screenPoint.X += cols;
@@ -897,13 +929,13 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
for (til::CoordType colsPainted = 0; colsPainted < cols; ++colsPainted, ++lineIt, ++lineTarget.X)
{
auto lines = lineIt->TextAttr();
_PaintBufferOutputGridLineHelper(pEngine, lines, 1, lineTarget);
_PaintBufferOutputGridLineHelper(pEngine, _pData, lines, 1, lineTarget);
}
}
else
{
// If nothing exciting is going on, draw the lines in bulk.
_PaintBufferOutputGridLineHelper(pEngine, currentRunColor, cols, screenPoint);
_PaintBufferOutputGridLineHelper(pEngine, _pData, currentRunColor, cols, screenPoint);
}
}
}
@@ -917,7 +949,7 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
// - textAttribute: the TextAttribute to generate GridLines from.
// Return Value:
// - a GridLineSet containing all the gridline info from the TextAttribute
IRenderEngine::GridLineSet Renderer::s_GetGridlines(const TextAttribute& textAttribute) noexcept
IRenderEngine::GridLineSet BaseRenderer::s_GetGridlines(const TextAttribute& textAttribute) noexcept
{
// Convert console grid line representations into rendering engine enum representations.
IRenderEngine::GridLineSet lines;
@@ -974,13 +1006,14 @@ IRenderEngine::GridLineSet Renderer::s_GetGridlines(const TextAttribute& textAtt
// - coordTarget - The X/Y coordinate position in the buffer which we're attempting to start rendering from.
// Return Value:
// - <none>
void Renderer::_PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine,
const TextAttribute textAttribute,
const size_t cchLine,
const til::point coordTarget)
void BaseRenderer::_PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine,
IRenderData* _pData,
const TextAttribute textAttribute,
const size_t cchLine,
const til::point coordTarget)
{
// Convert console grid line representations into rendering engine enum representations.
auto lines = Renderer::s_GetGridlines(textAttribute);
auto lines = s_GetGridlines(textAttribute);
// For now, we dash underline patterns and switch to regular underline on hover
// Since we're only rendering pattern links on *hover*, there's no point in checking
@@ -1018,7 +1051,7 @@ void Renderer::_PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngin
// - <none>
// Return Value:
// - nullopt if the cursor is off or out-of-frame, otherwise a CursorOptions
[[nodiscard]] std::optional<CursorOptions> Renderer::_GetCursorInfo()
[[nodiscard]] std::optional<CursorOptions> BaseRenderer::_GetCursorInfo(IRenderData* _pData)
{
if (_pData->IsCursorVisible())
{
@@ -1078,9 +1111,9 @@ void Renderer::_PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngin
// - engine - The render engine that we're targeting.
// Return Value:
// - <none>
void Renderer::_PaintCursor(_In_ IRenderEngine* const pEngine)
void BaseRenderer::_PaintCursor(_In_ IRenderEngine* const pEngine, IRenderData* _pData)
{
const auto cursorInfo = _GetCursorInfo();
const auto cursorInfo = _GetCursorInfo(_pData);
if (cursorInfo.has_value())
{
LOG_IF_FAILED(pEngine->PaintCursor(cursorInfo.value()));
@@ -1098,10 +1131,10 @@ void Renderer::_PaintCursor(_In_ IRenderEngine* const pEngine)
// - engine - The render engine that we're targeting.
// Return Value:
// - S_OK if the engine prepared successfully, or a relevant error via HRESULT.
[[nodiscard]] HRESULT Renderer::_PrepareRenderInfo(_In_ IRenderEngine* const pEngine)
[[nodiscard]] HRESULT BaseRenderer::_PrepareRenderInfo(_In_ IRenderEngine* const pEngine, IRenderData* _pData)
{
RenderFrameInfo info;
info.cursorInfo = _GetCursorInfo();
info.cursorInfo = _GetCursorInfo(_pData);
return pEngine->PrepareRenderInfo(info);
}
@@ -1113,8 +1146,9 @@ void Renderer::_PaintCursor(_In_ IRenderEngine* const pEngine)
// - overlay - The overlay to draw.
// Return Value:
// - <none>
void Renderer::_PaintOverlay(IRenderEngine& engine,
const RenderOverlay& overlay)
void BaseRenderer::_PaintOverlay(IRenderEngine& engine,
IRenderData* _pData,
const RenderOverlay& overlay)
{
try
{
@@ -1137,9 +1171,9 @@ void Renderer::_PaintOverlay(IRenderEngine& engine,
const til::point target{ viewDirty.Left, iRow };
const auto source = target - overlay.origin;
auto it = overlay.buffer.GetCellLineDataAt(source);
auto it = overlay.buffer->GetCellLineDataAt(source);
_PaintBufferOutputHelper(&engine, it, target, false);
_PaintBufferOutputHelper(&engine, _pData, it, target, false);
}
}
}
@@ -1155,7 +1189,7 @@ void Renderer::_PaintOverlay(IRenderEngine& engine,
// - <none>
// Return Value:
// - <none>
void Renderer::_PaintOverlays(_In_ IRenderEngine* const pEngine)
void BaseRenderer::_PaintOverlays(_In_ IRenderEngine* const pEngine, IRenderData* _pData)
{
try
{
@@ -1163,7 +1197,7 @@ void Renderer::_PaintOverlays(_In_ IRenderEngine* const pEngine)
for (const auto& overlay : overlays)
{
_PaintOverlay(*pEngine, overlay);
_PaintOverlay(*pEngine, _pData, overlay);
}
}
CATCH_LOG();
@@ -1175,7 +1209,7 @@ void Renderer::_PaintOverlays(_In_ IRenderEngine* const pEngine)
// - <none>
// Return Value:
// - <none>
void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
void BaseRenderer::_PaintSelection(_In_ IRenderEngine* const pEngine, IRenderData* _pData)
{
try
{
@@ -1183,7 +1217,7 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
LOG_IF_FAILED(pEngine->GetDirtyArea(dirtyAreas));
// Get selection rectangles
const auto rectangles = _GetSelectionRects();
const auto rectangles = _GetSelectionRects(_pData);
for (const auto& rect : rectangles)
{
for (auto& dirtyRect : dirtyAreas)
@@ -1210,10 +1244,11 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
// (Usually only happens when the default is changed, not when each individual color is swapped in a multi-color run.)
// Return Value:
// - <none>
[[nodiscard]] HRESULT Renderer::_UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine,
const TextAttribute textAttributes,
const bool usingSoftFont,
const bool isSettingDefaultBrushes)
[[nodiscard]] HRESULT BaseRenderer::_UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine,
IRenderData* _pData,
const TextAttribute textAttributes,
const bool usingSoftFont,
const bool isSettingDefaultBrushes)
{
// The last color needs to be each engine's responsibility. If it's local to this function,
// then on the next engine we might not update the color.
@@ -1228,7 +1263,7 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
// - <none>
// Return Value:
// - <none>
[[nodiscard]] HRESULT Renderer::_PerformScrolling(_In_ IRenderEngine* const pEngine)
[[nodiscard]] HRESULT BaseRenderer::_PerformScrolling(_In_ IRenderEngine* const pEngine)
{
return pEngine->ScrollFrame();
}
@@ -1237,7 +1272,7 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
// - Helper to determine the selected region of the buffer.
// Return Value:
// - A vector of rectangles representing the regions to select, line by line.
std::vector<til::rect> Renderer::_GetSelectionRects() const
std::vector<til::rect> BaseRenderer::_GetSelectionRects(IRenderData* _pData) const
{
const auto& buffer = _pData->GetTextBuffer();
auto rects = _pData->GetSelectionRects();
@@ -1268,7 +1303,7 @@ std::vector<til::rect> Renderer::_GetSelectionRects() const
// - delta - The scroll delta
// Return Value:
// - <none> - Updates internal state instead.
void Renderer::_ScrollPreviousSelection(const til::point delta)
void BaseRenderer::_ScrollPreviousSelection(const til::point delta)
{
if (delta != til::point{ 0, 0 })
{
@@ -1291,17 +1326,7 @@ void Renderer::_ScrollPreviousSelection(const til::point delta)
void Renderer::AddRenderEngine(_In_ IRenderEngine* const pEngine)
{
THROW_HR_IF_NULL(E_INVALIDARG, pEngine);
for (auto& p : _engines)
{
if (!p)
{
p = pEngine;
return;
}
}
THROW_HR_MSG(E_UNEXPECTED, "engines array is full");
_engines.push_back(pEngine);
}
// Method Description:

View File

@@ -34,7 +34,55 @@ namespace TerminalCoreUnitTests
namespace Microsoft::Console::Render
{
class Renderer
class BaseRenderer
{
public:
BaseRenderer(const RenderSettings& renderSettings, std::unique_ptr<RenderThread> thread) noexcept;
~BaseRenderer();
void NotifyPaintFrame() const noexcept;
protected:
static IRenderEngine::GridLineSet s_GetGridlines(const TextAttribute& textAttribute) noexcept;
static bool s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSoftFontChar, const size_t lastSoftFontChar);
[[nodiscard]] HRESULT _PaintFrameForEngine(_In_ IRenderEngine* const pEngine, IRenderData* _pData) noexcept;
bool _CheckViewportAndScroll(IRenderData* _pData);
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine, IRenderData* _pData);
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, IRenderData* _pData, TextBufferCellIterator it, const til::point target, const bool lineWrapped);
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine, IRenderData* _pData, const TextAttribute textAttribute, const size_t cchLine, const til::point coordTarget);
void _PaintSelection(_In_ IRenderEngine* const pEngine, IRenderData* _pData);
void _PaintCursor(_In_ IRenderEngine* const pEngine, IRenderData* _pData);
void _PaintOverlays(_In_ IRenderEngine* const pEngine, IRenderData* _pData);
void _PaintOverlay(IRenderEngine& engine, IRenderData* _pData, const RenderOverlay& overlay);
[[nodiscard]] HRESULT _UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine, IRenderData* _pData, const TextAttribute attr, const bool usingSoftFont, const bool isSettingDefaultBrushes);
[[nodiscard]] HRESULT _PerformScrolling(_In_ IRenderEngine* const pEngine);
std::vector<til::rect> _GetSelectionRects(IRenderData* _pData) const;
void _ScrollPreviousSelection(const til::point delta);
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine, IRenderData* _pData);
[[nodiscard]] std::optional<CursorOptions> _GetCursorInfo(IRenderData* _pData);
[[nodiscard]] HRESULT _PrepareRenderInfo(_In_ IRenderEngine* const pEngine, IRenderData* _pData);
const RenderSettings& _renderSettings;
boost::container::small_vector<IRenderEngine*, 2> _engines;
std::unique_ptr<RenderThread> _pThread;
static constexpr size_t _firstSoftFontChar = 0xEF20;
size_t _lastSoftFontChar = 0;
std::optional<interval_tree::IntervalTree<til::point, size_t>::interval> _hoveredInterval;
Microsoft::Console::Types::Viewport _viewport;
std::vector<Cluster> _clusterBuffer;
std::vector<til::rect> _previousSelection;
std::function<void()> _pfnBackgroundColorChanged;
std::function<void()> _pfnFrameColorChanged;
std::function<void()> _pfnRendererEnteredErrorState;
bool _destructing = false;
bool _forceUpdateViewport = true;
IRenderData* _pDataRef = nullptr; // Non-ownership pointer
};
class Renderer : public BaseRenderer
{
public:
Renderer(const RenderSettings& renderSettings,
@@ -43,11 +91,8 @@ namespace Microsoft::Console::Render
const size_t cEngines,
std::unique_ptr<RenderThread> thread);
~Renderer();
[[nodiscard]] HRESULT PaintFrame();
void NotifyPaintFrame() noexcept;
void TriggerSystemRedraw(const til::rect* const prcDirtyClient);
void TriggerRedraw(const Microsoft::Console::Types::Viewport& region);
void TriggerRedraw(const til::point* const pcoord);
@@ -92,42 +137,8 @@ namespace Microsoft::Console::Render
void UpdateLastHoveredInterval(const std::optional<interval_tree::IntervalTree<til::point, size_t>::interval>& newInterval);
private:
static IRenderEngine::GridLineSet s_GetGridlines(const TextAttribute& textAttribute) noexcept;
static bool s_IsSoftFontChar(const std::wstring_view& v, const size_t firstSoftFontChar, const size_t lastSoftFontChar);
[[nodiscard]] HRESULT _PaintFrameForEngine(_In_ IRenderEngine* const pEngine) noexcept;
bool _CheckViewportAndScroll();
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine);
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, TextBufferCellIterator it, const til::point target, const bool lineWrapped);
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine, const TextAttribute textAttribute, const size_t cchLine, const til::point coordTarget);
void _PaintSelection(_In_ IRenderEngine* const pEngine);
void _PaintCursor(_In_ IRenderEngine* const pEngine);
void _PaintOverlays(_In_ IRenderEngine* const pEngine);
void _PaintOverlay(IRenderEngine& engine, const RenderOverlay& overlay);
[[nodiscard]] HRESULT _UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine, const TextAttribute attr, const bool usingSoftFont, const bool isSettingDefaultBrushes);
[[nodiscard]] HRESULT _PerformScrolling(_In_ IRenderEngine* const pEngine);
std::vector<til::rect> _GetSelectionRects() const;
void _ScrollPreviousSelection(const til::point delta);
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
[[nodiscard]] std::optional<CursorOptions> _GetCursorInfo();
[[nodiscard]] HRESULT _PrepareRenderInfo(_In_ IRenderEngine* const pEngine);
const RenderSettings& _renderSettings;
std::array<IRenderEngine*, 2> _engines{};
IRenderData* _pData = nullptr; // Non-ownership pointer
std::unique_ptr<RenderThread> _pThread;
static constexpr size_t _firstSoftFontChar = 0xEF20;
size_t _lastSoftFontChar = 0;
std::optional<interval_tree::IntervalTree<til::point, size_t>::interval> _hoveredInterval;
Microsoft::Console::Types::Viewport _viewport;
std::vector<Cluster> _clusterBuffer;
std::vector<til::rect> _previousSelection;
std::function<void()> _pfnBackgroundColorChanged;
std::function<void()> _pfnFrameColorChanged;
std::function<void()> _pfnRendererEnteredErrorState;
bool _destructing = false;
bool _forceUpdateViewport = true;
RenderData _snapshot;
#ifdef UNIT_TESTING
friend class ConptyOutputTests;

View File

@@ -28,6 +28,7 @@ Author(s):
class FontInfo : public FontInfoBase
{
public:
FontInfo() = default;
FontInfo(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
@@ -54,5 +55,5 @@ private:
til::size _coordSize;
til::size _coordSizeUnscaled;
bool _didFallback;
bool _didFallback = false;
};

View File

@@ -26,6 +26,7 @@ static constexpr wchar_t DEFAULT_RASTER_FONT_FACENAME[]{ L"Terminal" };
class FontInfoBase
{
public:
FontInfoBase() = default;
FontInfoBase(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
@@ -55,8 +56,8 @@ protected:
private:
std::wstring _faceName;
unsigned int _weight;
unsigned char _family;
unsigned int _codePage;
bool _fDefaultRasterSetFromEngine;
unsigned int _weight = 0;
unsigned char _family = 0;
unsigned int _codePage = 0;
bool _fDefaultRasterSetFromEngine = false;
};

View File

@@ -15,37 +15,29 @@ Author(s):
#pragma once
#include "../../host/conimeinfo.h"
#include "../../buffer/out/TextAttribute.hpp"
#include "../../buffer/out/textBuffer.hpp"
#include "../../types/IBaseData.h"
class Cursor;
namespace Microsoft::Console::Render
{
struct RenderOverlay final
{
// This is where the data is stored
const TextBuffer& buffer;
const TextBuffer* buffer;
// This is where the top left of the stored buffer should be overlaid on the screen
// (relative to the current visible viewport)
const til::point origin;
til::point origin;
// This is the area of the buffer that is actually used for overlay.
// Anything outside of this is considered empty by the overlay and shouldn't be used
// for painting purposes.
const Microsoft::Console::Types::Viewport region;
Microsoft::Console::Types::Viewport region;
};
class IRenderData : public Microsoft::Console::Types::IBaseData
{
public:
~IRenderData() = 0;
IRenderData(const IRenderData&) = default;
IRenderData(IRenderData&&) = default;
IRenderData& operator=(const IRenderData&) = default;
IRenderData& operator=(IRenderData&&) = default;
virtual til::point GetCursorPosition() const noexcept = 0;
virtual bool IsCursorVisible() const noexcept = 0;
virtual bool IsCursorOn() const noexcept = 0;
@@ -63,11 +55,48 @@ namespace Microsoft::Console::Render
virtual const std::wstring GetHyperlinkCustomId(uint16_t id) const noexcept = 0;
virtual const std::vector<size_t> GetPatternId(const til::point location) const noexcept = 0;
protected:
IRenderData() = default;
};
// See docs/virtual-dtors.md for an explanation of why this is weird.
inline IRenderData::~IRenderData() {}
struct RenderData : IRenderData
{
Types::Viewport viewport;
TextBuffer textBuffer;
FontInfo fontInfo;
std::vector<Types::Viewport> selectionRects;
til::point cursorPosition;
bool cursorVisible = false;
bool cursorOn = false;
ULONG cursorHeight = 0;
CursorType cursorStyle = CursorType::Legacy;
ULONG cursorPixelWidth = 0;
bool cursorDoubleWidth = false;
std::vector<RenderOverlay> overlays;
bool gridLineDrawingAllowed = false;
std::wstring consoleTitle;
void Snapshot(IRenderData* other);
Types::Viewport GetViewport() noexcept override;
til::point GetTextBufferEndPosition() const noexcept override;
const TextBuffer& GetTextBuffer() const noexcept override;
const FontInfo& GetFontInfo() const noexcept override;
std::vector<Types::Viewport> GetSelectionRects() noexcept override;
void LockConsole() noexcept override;
void UnlockConsole() noexcept override;
til::point GetCursorPosition() const noexcept override;
bool IsCursorVisible() const noexcept override;
bool IsCursorOn() const noexcept override;
ULONG GetCursorHeight() const noexcept override;
CursorType GetCursorStyle() const noexcept override;
ULONG GetCursorPixelWidth() const noexcept override;
bool IsCursorDoubleWidth() const override;
const std::vector<RenderOverlay> GetOverlays() const noexcept override;
const bool IsGridLineDrawingAllowed() noexcept override;
const std::wstring_view GetConsoleTitle() const noexcept override;
const std::wstring GetHyperlinkUri(uint16_t id) const noexcept override;
const std::wstring GetHyperlinkCustomId(uint16_t id) const noexcept override;
const std::vector<size_t> GetPatternId(const til::point location) const noexcept override;
};
}