├── .editorconfig ├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── Changelog.md ├── Gemfile ├── Gemfile.lock ├── Makefile ├── README.md └── spec ├── refs.bib └── terminal-unicode-core.tex /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | insert_final_newline = true 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | 11 | [Makefile] 12 | indent_style = tab 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - wip 7 | - master 8 | - preview 9 | - release 10 | pull_request: 11 | branches: 12 | - master 13 | 14 | jobs: 15 | compile_pdf: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v1 19 | - name: "install dependencies" 20 | run: | 21 | set -ex 22 | sudo apt -q update 23 | sudo apt install -y texlive-latex-base texlive-latex-extra latexmk texlive-bibtex-extra biber 24 | - name: "Compile PDF" 25 | run: | 26 | set -ex 27 | cd spec 28 | latexmk -pdflatex terminal-unicode-core 29 | - name: "Uploading PDF" 30 | uses: actions/upload-artifact@v2 31 | with: 32 | name: spec 33 | path: spec/terminal-unicode-core.pdf 34 | if-no-files-found: error 35 | 36 | compile_md: 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@v1 40 | - name: "install dependencies" 41 | run: | 42 | set -ex 43 | sudo apt -q update 44 | sudo apt install -y pandoc 45 | - name: "Compile markdown" 46 | run: | 47 | set -ex 48 | cd spec 49 | pandoc -s terminal-unicode-core.tex -o terminal-unicode-core.md 50 | - name: "Uploading markdown" 51 | uses: actions/upload-artifact@v2 52 | with: 53 | name: spec 54 | path: spec/terminal-unicode-core.md 55 | if-no-files-found: error 56 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - preview 7 | - release 8 | 9 | jobs: 10 | compile_pdf: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: "install dependencies" 15 | run: | 16 | set -ex 17 | sudo apt -q update 18 | sudo apt install -y texlive-latex-base texlive-latex-extra latexmk texlive-bibtex-extra biber 19 | - name: "Compile PDF" 20 | run: | 21 | set -ex 22 | cd spec 23 | latexmk -pdflatex terminal-unicode-core 24 | - name: "Uploading PDF" 25 | uses: actions/upload-artifact@v2 26 | with: 27 | name: spec 28 | path: spec/terminal-unicode-core.pdf 29 | if-no-files-found: error 30 | 31 | compile_md: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v1 35 | - name: "install dependencies" 36 | run: | 37 | set -ex 38 | sudo apt -q update 39 | sudo apt install -y pandoc 40 | - name: "Compile markdown" 41 | run: | 42 | set -ex 43 | cd spec 44 | pandoc -s terminal-unicode-core.tex -o terminal-unicode-core.md 45 | - name: "Uploading markdown" 46 | uses: actions/upload-artifact@v2 47 | with: 48 | name: spec 49 | path: spec/terminal-unicode-core.md 50 | if-no-files-found: error 51 | 52 | do_release: 53 | name: Create Github release 54 | runs-on: ubuntu-latest 55 | needs: [compile_pdf, compile_md] 56 | steps: 57 | - uses: actions/checkout@v1 58 | # ------------------------------------------------------------- 59 | - name: fetch release artifacts 60 | uses: actions/download-artifact@v2 61 | with: 62 | name: spec 63 | # ------------------------------------------------------------- 64 | - name: Set Output Variables 65 | id: set_env_var 66 | env: 67 | REPOSITORY: ${{ github.event.repository.name }} 68 | run: | 69 | VERSION=$(grep '^### ' Changelog.md | head -n1 | awk '{print $2}') 70 | SUFFIX=$(grep '^### ' Changelog.md | head -n1 | awk '{print $3}' | tr -d '()') 71 | if [ $REPOSITORY = "master" ]; then IS_PRE='false'; else IS_PRE='true'; fi 72 | if [ $REPOSITORY = "master" ]; then SUFFIX='' ; else SUFFIX='prerelease'; fi 73 | if [ $REPOSITORY != "master" ]; then 74 | TAG_SUFFIX="_prerelease_${GITHUB_RUN_NUMBER}" 75 | else 76 | TAG_SUFFIX="" 77 | fi 78 | RELEASEBODY=$(awk -v RS='^### ' '/^'$VERSION'/ {print $0}' Changelog.md | tail -n+3) 79 | RELEASEBODY="${RELEASEBODY//'%'/'%25'}" 80 | RELEASEBODY="${RELEASEBODY//$'\n'/'%0A'}" 81 | RELEASEBODY="${RELEASEBODY//$'\r'/'%0D'}" 82 | echo "::set-output name=version::${VERSION}" 83 | echo "::set-output name=tag_suffix::${TAG_SUFFIX}" 84 | echo "::set-output name=RUN_ID::${GITHUB_RUN_NUMBER}" 85 | echo "::set-output name=IS_PRERELEASE::${IS_PRE}" 86 | echo "::set-output name=RELEASENAME_SUFFIX::${SUFFIX}" 87 | echo "::set-output name=RELEASEBODY::${RELEASEBODY}" 88 | # ------------------------------------------------------------- 89 | - name: Create Github release page 90 | id: create_release 91 | uses: actions/create-release@v1 92 | env: 93 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 94 | with: 95 | tag_name: v${{ steps.set_env_var.outputs.version }}${{ steps.set_env_var.outputs.tag_suffix}} 96 | release_name: Terminal Unicode Core ${{ steps.set_env_var.outputs.version }}-${{ steps.set_env_var.outputs.RUN_ID }} ${{ steps.set_env_var.outputs.RELEASENAME_SUFFIX}} 97 | body: | 98 | ${{ steps.set_env_var.outputs.RELEASEBODY }} 99 | draft: true 100 | prerelease: ${{ steps.set_env_var.outputs.IS_PRERELEASE }} 101 | # ------------------------------------------------------------- 102 | - name: Upload PDF 103 | id: upload-release-pdf 104 | uses: actions/upload-release-asset@v1 105 | env: 106 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 107 | with: 108 | upload_url: ${{ steps.create_release.outputs.upload_url }} 109 | asset_path: terminal-unicode-core.pdf 110 | asset_name: terminal-unicode-core-${{ steps.set_env_var.outputs.version }}-${{ steps.set_env_var.outputs.RUN_ID }}.pdf 111 | asset_content_type: application/pdf 112 | # ------------------------------------------------------------- 113 | - name: Upload markdown 114 | id: upload-release-md 115 | uses: actions/upload-release-asset@v1 116 | env: 117 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 118 | with: 119 | upload_url: ${{ steps.create_release.outputs.upload_url }} 120 | asset_path: terminal-unicode-core.md 121 | asset_name: terminal-unicode-core-${{ steps.set_env_var.outputs.version }}-${{ steps.set_env_var.outputs.RUN_ID }}.md 122 | asset_content_type: text/markdown 123 | 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tmp 2 | *.aux 3 | *.log 4 | *.toc 5 | *.pdf 6 | *.out 7 | *.fls 8 | *.fdb_latexmk 9 | *.synctex.gz 10 | .fake 11 | .ionide 12 | /out 13 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | ### 0.1.0 (unreleased) 2 | 3 | - initial draft 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # gem "rails" 8 | gem 'jekyll' 9 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.0) 5 | public_suffix (>= 2.0.2, < 5.0) 6 | colorator (1.1.0) 7 | concurrent-ruby (1.1.9) 8 | em-websocket (0.5.2) 9 | eventmachine (>= 0.12.9) 10 | http_parser.rb (~> 0.6.0) 11 | eventmachine (1.2.7) 12 | ffi (1.15.4) 13 | forwardable-extended (2.6.0) 14 | http_parser.rb (0.6.0) 15 | i18n (1.8.10) 16 | concurrent-ruby (~> 1.0) 17 | jekyll (4.2.0) 18 | addressable (~> 2.4) 19 | colorator (~> 1.0) 20 | em-websocket (~> 0.5) 21 | i18n (~> 1.0) 22 | jekyll-sass-converter (~> 2.0) 23 | jekyll-watch (~> 2.0) 24 | kramdown (~> 2.3) 25 | kramdown-parser-gfm (~> 1.0) 26 | liquid (~> 4.0) 27 | mercenary (~> 0.4.0) 28 | pathutil (~> 0.9) 29 | rouge (~> 3.0) 30 | safe_yaml (~> 1.0) 31 | terminal-table (~> 2.0) 32 | jekyll-sass-converter (2.1.0) 33 | sassc (> 2.0.1, < 3.0) 34 | jekyll-watch (2.2.1) 35 | listen (~> 3.0) 36 | kramdown (2.3.1) 37 | rexml 38 | kramdown-parser-gfm (1.1.0) 39 | kramdown (~> 2.0) 40 | liquid (4.0.3) 41 | listen (3.7.0) 42 | rb-fsevent (~> 0.10, >= 0.10.3) 43 | rb-inotify (~> 0.9, >= 0.9.10) 44 | mercenary (0.4.0) 45 | pathutil (0.16.2) 46 | forwardable-extended (~> 2.6) 47 | public_suffix (4.0.6) 48 | rb-fsevent (0.11.0) 49 | rb-inotify (0.10.1) 50 | ffi (~> 1.0) 51 | rexml (3.2.5) 52 | rouge (3.26.0) 53 | safe_yaml (1.0.5) 54 | sassc (2.4.0) 55 | ffi (~> 1.9) 56 | terminal-table (2.0.0) 57 | unicode-display_width (~> 1.1, >= 1.1.1) 58 | unicode-display_width (1.7.0) 59 | 60 | PLATFORMS 61 | ruby 62 | 63 | DEPENDENCIES 64 | jekyll 65 | 66 | BUNDLED WITH 67 | 2.1.4 68 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # vim:noet 2 | 3 | BASENAME = terminal-unicode-core 4 | SOURCE_FILES = spec/$(BASENAME).tex spec/refs.bib 5 | TARGET_DIR = out 6 | 7 | all: ${TARGET_DIR}/${BASENAME}.pdf 8 | 9 | clean: 10 | @rm -vf ${TARGET_DIR}/* 11 | @rm ${BASENAME}.bbl 12 | 13 | ${TARGET_DIR}/${BASENAME}.pdf: $(SOURCE_FILES) 14 | @mkdir -p ${TARGET_DIR} 15 | pdflatex -aux_directory=${TARGET_DIR} -output-directory=${TARGET_DIR} $^ 16 | biber --input-directory $(shell pwd)/spec --output-directory . ${TARGET_DIR}/${BASENAME}.bcf 17 | pdflatex -aux_directory=${TARGET_DIR} -output-directory=${TARGET_DIR} $^ 18 | pdflatex -aux_directory=${TARGET_DIR} -output-directory=${TARGET_DIR} $^ 19 | 20 | .PHONY: all clean 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terminal Unicode Core Specification 2 | 3 | **IMPORTANT: THIS PROJECT IS IN ALPHA STAGE & ACTIVE DEVELOPMENT** 4 | 5 | Let's make Unicode support in terminal emulators better -not perfect- but better. 6 | 7 | For that I'd like to introduce a small spec that at least tries to tackle **some** 8 | basics that would greatly help user experience. 9 | 10 | Of course, the terminal emulator is not enough, terminal applications have 11 | to catch up, too. But without support from terminals, the applications 12 | cannot even start doing so. This project tries to fix that. 13 | 14 | ## Goal of this project repository 15 | 16 | It would be nice if this repository serves as a communication hub for 17 | improving this spec that ideally enough terminal emulators will adopt, 18 | so we could call this the future extension for terminals. 19 | 20 | ## How to contribute 21 | 22 | Everybodies point of view is valuable, whether terminal emulator developer, 23 | terminal application or toolkit developer, or a user. 24 | 25 | While getting this spec in shape, I'd like to get your feedback to find 26 | a common concensus that most of us can agree on with the goal to get 27 | an adoption as broad as possible. 28 | 29 | Sure, this won't happen in a day or in a year. 30 | But someone has to start at some point, so more can follow. 31 | 32 | ## This spec is NOT 33 | 34 | - attempting to bring full Unicode support to the terminal 35 | - planning to get Unicode BiDi support formalized (mlterm could be doing that much better :) ) 36 | - tackle every other niche aspect of Unicode. 37 | 38 | ## This spec will 39 | 40 | - enable users to make use of programming ligatures and Emoji without sacrifice. 41 | - have legacy applications as well as newer ones respecting this spec compatible in one terminal. 42 | 43 | ## Roadmap 44 | 45 | - [x] create CI job for auto-generating PDF/markdown of the latest draft to be downloadable 46 | - [x] create CI job for providing prereleases of the draft specification. 47 | - [ ] Move Changelog into .tex file and let CI's release.yml extract it from there 48 | - [ ] Create Github pages that have an auto-generated PDF/markdown version of this specification. 49 | - [ ] Hopefully get enough terminal and TUI app devs attracted to collaborate in a positive, friendly, and productive manner. 50 | 51 | ## FAQ 52 | 53 | - **Why LaTeX and not Markdown?** Expressivity and the fact that you can convert to Markdown: https://pandoc.org/demos.html 54 | - **Why GitHub and not GitLab on freedesktop?** Better reachability. 55 | 56 | -------------------------------------------------------------------------------- /spec/refs.bib: -------------------------------------------------------------------------------- 1 | @online{RIS, 2 | author = "DEC", 3 | title = "Hard Terminal Reset", 4 | label = "RIS", 5 | url = "https://vt100.net/docs/vt510-rm/RIS.html", 6 | addendum = "(accessed: 01.09.2021)", 7 | keywords = "RIS" 8 | } 9 | 10 | @online{DECSTR, 11 | author = "DEC", 12 | title = "Soft Terminal Reset", 13 | label = "DECSTR", 14 | url = "https://vt100.net/docs/vt510-rm/DECSTR.html", 15 | addendum = "(accessed: 01.09.2021)", 16 | keywords = "DECSTR" 17 | } 18 | 19 | @online{RM, 20 | author = "DEC", 21 | title = "Set Mode", 22 | label = "RM", 23 | url = "https://vt100.net/docs/vt510-rm/RM.html", 24 | addendum = "(accessed: 01.09.2021)", 25 | keywords = "RM" 26 | } 27 | 28 | @online{SM, 29 | author = "DEC", 30 | title = "Set Mode", 31 | label = "SM", 32 | url = "https://vt100.net/docs/vt510-rm/SM.html", 33 | addendum = "(accessed: 01.09.2021)", 34 | keywords = "SM" 35 | } 36 | 37 | @online{DECRQM, 38 | author = "DEC", 39 | title = "Request Mode", 40 | label = "DECRQM", 41 | url = "https://vt100.net/docs/vt510-rm/DECRQM.html", 42 | addendum = "(accessed: 01.09.2021)", 43 | keywords = "DECRQM" 44 | } 45 | 46 | @online{DECAWM, 47 | author = "DEC", 48 | title = "AutoWrap Mode", 49 | label = "DECAWM", 50 | url = "https://vt100.net/docs/vt510-rm/DECAWM.html", 51 | addendum = "(accessed: 01.09.2021)", 52 | keywords = "DECAWM" 53 | } 54 | 55 | @online{UTS-11, 56 | author = "Unicode Consortium", 57 | title = "East Asian Width", 58 | label = "UTS 11", 59 | url = "https://unicode.org/reports/tr11/", 60 | addendum = "(accessed: 01.09.2021)", 61 | keywords = "UTS 11" 62 | } 63 | 64 | @online{UTS-29, 65 | author = "Unicode Consortium", 66 | title = "UTS 29, Unicode Grapheme segmentation algorithm", 67 | label = "UTS 29", 68 | url = "https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules", 69 | addendum = "(accessed: 01.09.2021)", 70 | keywords = "UTS 29" 71 | } 72 | 73 | @online{UTS-51, 74 | author = "Unicode Consortium", 75 | title = "UTS 51, Unicode Emoji", 76 | label = "UTS 51", 77 | url = "https://unicode.org/reports/tr51/#Display", 78 | addendum = "(accessed: 01.09.2021)", 79 | keywords = "UTS 51" 80 | } 81 | -------------------------------------------------------------------------------- /spec/terminal-unicode-core.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[utf8]{inputenc} 3 | \usepackage[english]{babel} 4 | 5 | \usepackage{colortbl} 6 | \usepackage{epigraph} 7 | \usepackage{fancyhdr} 8 | \usepackage{graphicx} 9 | \usepackage{hhline} 10 | \usepackage{todonotes} 11 | 12 | \usepackage{csquotes} 13 | \usepackage[backend=biber,style=alphabetic,sorting=anyt]{biblatex} 14 | \addbibresource{refs.bib} 15 | 16 | \usepackage[hidelinks]{hyperref} 17 | \hypersetup{ 18 | colorlinks=true, 19 | hypertexnames=true 20 | citecolor=red, 21 | linkcolor=blue, 22 | filecolor=magenta, 23 | citecolor=orange, 24 | urlcolor=cyan 25 | } 26 | 27 | \usepackage{draftwatermark} 28 | \SetWatermarkText{Draft} 29 | \SetWatermarkScale{4} 30 | 31 | \usepackage{geometry} 32 | \geometry{legalpaper, margin=1in} 33 | 34 | \usepackage{xcolor} 35 | \definecolor{light-gray}{gray}{0.95} 36 | 37 | \title{Unicode in Terminals \\ 38 | a proposal to standardizing basic Unicode features} 39 | \author{Christian Parpart} 40 | \date{2021-09-06 (draft, revision 1)} 41 | 42 | \newcommand{\code}[1]{\colorbox{light-gray}{\texttt{#1}}} 43 | 44 | \newcommand{\Unicode}{\textbf{Unicode 13}} 45 | 46 | \newcommand{\DECRQM}[1]{\code{CSI ? #1 \$ p} } 47 | \newcommand{\DECSET}[1]{\code{CSI ? #1 h} } 48 | \newcommand{\DECRST}[1]{\code{CSI ? #1 l} } 49 | 50 | \newcommand\VtModeNum{2027} % mode Id that is used by this specification 51 | \newcommand{\UCON}{\DECSET{\VtModeNum{}}} % DECSM for enabling grapheme cluster processing 52 | \newcommand{\UCOFF}{\DECRST{\VtModeNum{}}} % DECRM for disabling grapheme cluster processing 53 | \newcommand{\UCTEST}{\DECRQM{\VtModeNum{}}} % DECRQM for requesting current grapheme cluster processing mode 54 | 55 | \begin{document} 56 | 57 | \maketitle 58 | 59 | \tableofcontents 60 | 61 | \section{History and current state} 62 | 63 | Historically, only 7-bit characters with C0 control codes 64 | were supported by terminals and different languages 65 | by selecting their respective code pages. 66 | 67 | Later on this was extended to 8-bit ASCII and along with C1 control codes. 68 | 69 | With the introduction of Unicode there were no need to have codepages anymore, 70 | but the Unicode spec was not explicitly designed to also cover terminals, 71 | except that C0 and C1 codepoints were preserved. 72 | 73 | With Unicode UTF-8 it was possible to at least pass Unicode characters to the 74 | terminal, but rendering of a few characters as well as their respective 75 | cursor placement is not defined in the Unicode standard. 76 | 77 | Also, Unicode introduced codepoint sequences that are mapping to 78 | a single user perceived character - so called grapheme clusters. 79 | The terminal has never attempted any formalization on how to deal with 80 | grapheme clusters, variation selectors, their east asian width, nor 81 | emoji and emoji presentation handling. 82 | 83 | This spec tries to address some of the problems terminals are suffering 84 | with Unicode today. 85 | 86 | \section{Backwards Compatibility} 87 | 88 | Backwards compatibility is retained by leaving everything as undefined 89 | as it used to be without this specification when this mode is not enabled. 90 | 91 | The application can test for the availability of this feature mode 92 | and has to explicitly enable it in order to get the set of properties 93 | as defined in this document guaranteed. 94 | 95 | \section{Future Compatibility and Stability} 96 | 97 | Unicode itself had a major breakage at version between version 8 and 9 98 | with regards to some codepoints having their east asian width changed. 99 | 100 | While this may happen any time again, we do not expect that to happen 101 | that soon nor that frequent to address future incompatibilities 102 | as of this spec and leave this for a later point. 103 | 104 | \section{Feature and Mode State Detection} 105 | 106 | \UCTEST \cite{DECRQM} can be used for testing the availability of this 107 | feature as well as the current mode the terminal is in with regards 108 | to this specification, the \UCTEST reply will indigate each state 109 | acurately enough not not need any new VT sequence introduced. 110 | 111 | \section{Mode Switching} 112 | 113 | \begin{itemize} 114 | \item \UCON{} \cite{SM} for ensuring conformance to all rules as defined by this specification 115 | \item \UCOFF{} \cite{RM} for undefined behavior 116 | \end{itemize} 117 | 118 | \section{Semantics} 119 | 120 | The following set of semantics \textbf{MUST} be adhered to if this 121 | VT mode \code{\VtModeNum} is enabled. 122 | If the VT mode \code{\VtModeNum} is not set, then the behavior is as undefined 123 | as if this specification was not implemented at all in order to retain 124 | behavior of current terminals and their legacy applications. 125 | 126 | \subsection{Grapheme Cluster} 127 | 128 | \paragraph*{} 129 | With this mode enabled, the terminal \textbf{MUST} support grapheme clusters 130 | in conformance to algorithm as described in \cite{UTS-29}. 131 | 132 | \paragraph*{} 133 | This implies that every consecutively written character on the terminal 134 | stream that is non-breakable as per \cite{UTS-29} will 135 | always end up in the same terminal's grid cell. 136 | 137 | \paragraph*{} 138 | Therefore, extending a grapheme cluster with consecutively added codepoints 139 | will not move the cursor except for variation selector 16 (VS16) that may 140 | have caused the width of the grapheme cluster to change to wide (2 grid cells). 141 | 142 | \paragraph*{} 143 | When the cursor moves to a grid cell that contains a complete or incomplete 144 | grapheme cluster, this grid cell's contents will be erased and overwritten 145 | rather then textually concatinated. 146 | 147 | \paragraph*{} 148 | Therefore cursor movement semantics of the terminal remain unchanged. 149 | 150 | \subsection{Emoji} 151 | 152 | \paragraph*{} 153 | Emoji symbols are always rendered in square aspect ratio 154 | (as proposed by \cite{UTS-51}), 155 | implying a East Asian Width \cite{UTS-11} of Wide, 2 grid cells. 156 | 157 | \paragraph*{} 158 | ZWJ emoji are required to be displayed as a single image with a width of 2 grid cells. 159 | 160 | The alternate display of ZWJ emoji in a decomposed sequence of sub-images 161 | must not be used as a fallback as it will break cursor movemeent guarantees. 162 | 163 | \paragraph*{} 164 | If a ZWJ emoji cannot be rendered the display behavior is undefined - 165 | for example, a Unicode replacement character \code{U+FFFD} could be 166 | displayed instead. 167 | 168 | \paragraph*{} 169 | In emoji emoji presentation, the cursor will always move by 2 grid cells wide. 170 | 171 | \paragraph*{} 172 | SGR attributes applied to a grid cell containing an emoji symbol are 173 | not strictly defined and it is left to the terminal emulator author to have 174 | sensible and meaningful semantics with regards to emoji symbols. 175 | 176 | \subsection{Variation Selector 16} 177 | 178 | VS16 promotes the grapheme cluster to emoji emoji presentation, 179 | implying that this will force the grapheme cluster's width to be 2, 180 | which may possibly cause reflowing of that symbol to the next line 181 | if on right margin with AutoWrap mode is set. 182 | 183 | \subsection{Variation Selector 15} 184 | 185 | \paragraph*{} 186 | VS15 forces the grapheme cluster to emoji text presentation. 187 | This will \textbf{NOT} change the underlying width 188 | but only change the display to prefer textual non-colored presentation. 189 | 190 | \paragraph*{} 191 | This matches the behavior of todays web browsers and should thus 192 | feel most intuitive to users. 193 | 194 | \paragraph*{} 195 | The cursor will move by columns if the symbol has the default presentation of emoji. 196 | 197 | \subsection{Margins and AutoWrap with Emoji} 198 | 199 | Emoji written at the right margin with \cite{DECAWM} AutoWrap mode disabled 200 | may or may not be rendered in half or not be displayed at all. 201 | This behavior is undefined to ease implementation and adoption 202 | of this specification. 203 | 204 | \subsection{Terminal Reset} 205 | 206 | Both, Soft reset \cite{DECSTR} as well as hard reset \cite{RIS} 207 | will reset the mode back to undefined behavior. 208 | 209 | \printbibliography[heading=bibintoc,title={References}] 210 | 211 | \end{document} 212 | --------------------------------------------------------------------------------