In the early microcomputer days, MS-DOS editors like pmate and teco depended on hot keys for navigation and other tasks. With the great support for the mouse, touch, and graphical interface aids like ribbons incorporated into later personal computers, the need for navigation hot keys was greatly diminished. But there are other hot keys that can be incredibly handy, and some navigation keys are still used a lot.
This post summarizes the hot keys built into RichEdit. A previous post published a summary of all RichEdit hot keys as of 2013, but that post got truncated, it’s missing some hot keys that were added recently, and the hyperlinks need updating. Note that RichEdit clients, e.g., OneNote, often handle all hot keys with RichEdit never seeing the corresponding keyboard messages. Since the client receives the keyboard input, it can do whatever it wants to with that input. This flexibility is valuable particularly for localizing hot keys. RichEdit is “globalized”, but not localized. A number of the hot keys described in this post are English-centric and should be localized by the client. Other hot keys are global by nature and can be used in any locale.
Entering Unicode characters
The post Entering Unicode Characters explains several ways to enter arbitrary Unicode characters into applications. My favorite general-purpose way is via Alt+x, which works in Word, Outlook, OneNote, and RichEdit-based programs like WordPad and the Windows 11 Notepad. It ought to work in all editors! (Sadly, it doesn’t work in PowerPoint, Excel or Visual Studio, although it’d be easy for these programs to implement it ☹). It works by entering the Unicode hex code for the character followed by Alt+x. So, entering 2260 Alt+x enters ≠. Entering 1d44e Alt+x enters 𝑎, which is math-italic a. I use this hot key almost as often as I use Ctrl+c (copy) and Ctrl+v (paste). When I’m writing code in Visual Studio, I keep a program running RichEdit handy for entering Unicode symbols. Programs are easier to read with real Unicode characters instead of workarounds using the \xXXXX notation. You can also copy the symbols from appropriate web pages such as Mathematical operators and symbols in Unicode which has most math symbols. But if you know the Unicode code point, the Alt+x hot key is faster. It also lets you find out a character’s Unicode hex value from the character since Alt+x is a toggle: convert hex to character; convert character to hex. Try it, you will like it!
BiDi paragraph directionality
A pair of globalized hot keys set the BiDi directionality of a paragraph. These hot keys depend on knowing the difference between right and left. The WM_KEYDOWN message passes information in the message lparam that specifies right Shift or left Shift. Specifically, byte 2 of the lparam gives the key’s scan code and the value 0x36 is the scan code for the right-shift key ever since IBM shipped its first PC in August, 1981. This information lets RichEdit handle the Ctrl+RightShift hot key to switch the BiDi paragraph directionality to RTL (right to left). Similarly, Ctrl+LeftShift switches to LTR (left to right). RichEdit tracks which Alt, Shift, and Ctrl keys are depressed at any given time. This enables it to differentiate between left Alt for menus and right Alt (AltGr) for keyboard commands. But the most important use is for the Ctrl+RightShift and Ctrl+LeftShift hot keys. Lots of other Word hot keys are implemented in RichEdit.
Subscript, superscript, and math build up/down
RichEdit supports Word’s standard subscript and superscript hot keys: Ctrl+= and Ctrl+Shift+=, respectively. These hot keys toggle their respective states. For example, if you type some text, Ctrl+=, and some more text, the latter will be subscripted up until you type Ctrl+= again to go back on the base line. If you type one of these hot keys while some text is selected, that text’s script character will be toggled accordingly. In UnicodeMath, subscripts and superscripts are usually entered with the _ and ^ operators as in [La]TeX, or via the ribbon. But the standard hot keys can be handy provided the scripts are not nested. These hot keys have different meanings in a math zone: Ctrl+= builds up LaTeX or UnicodeMath into OfficeMath and Ctrl+Shift+= builds OfficeMath down into LaTeX or UnicodeMath.
Toggle end of bracketed expression
The Ctrl+} hot key is copied from the Visual Studio program editor. Ctrl+} moves the insertion point from one end of a bracketed expression (…), […], {…} to the other end. This is very handy for examining text with nested parentheses or curly braces (RTF, LaTeX, computer programs, JSON, etc.).
Navigation Keys
Arrow, PgUp/PgDn, and Home/End key behavior is summarized in the following table for ordinary text (behavior in math zones may differ). A depressed state of the Shift, Ctrl, and Alt keys is given by ✓; else the key isn’t depressed.
Key | Shift | Ctrl | Action |
← | Move left char | ||
← | ✓ | Move left word | |
← | ✓ | Select left char | |
← | ✓ | ✓ | Select left word |
↑ | Move up line | ||
↑ | ✓ | Move to start of paragraph | |
↑ | ✓ | Select up line | |
↑ | ✓ | ✓ | Select to start of paragraph |
→ | Move right char | ||
→ | ✓ | Move right word | |
→ | ✓ | Select right char | |
→ | ✓ | ✓ | Select right word |
↓ | Move down line | ||
↓ | ✓ | Move to end of paragraph | |
↓ | ✓ | Select down line | |
↓ | ✓ | ✓ | Select to end of paragraph |
PgUp | Move up one screen | ||
PgUp | ✓ | Move to start of screen | |
PgUp | ✓ | Select up one screen | |
PgUp | ✓ | ✓ | Select to start of screen |
PgDn | Move down one screen | ||
PgDn | ✓ | Move to end of screen | |
PgDn | ✓ | Select down one screen | |
PgDn | ✓ | ✓ | Select to end of screen |
Home | Move to start of line | ||
Home | ✓ | Move to start of story | |
Home | ✓ | Select to start of line | |
Home | ✓ | ✓ | Select to start of story |
End | Move to end of line | ||
End | ✓ | Move to end of story | |
End | ✓ | Select to end of line | |
End | ✓ | ✓ | Select to end of story |
Arrow-key behavior in vertical text corresponds to the different direction. For example, ↓ goes to the next character instead of going to the next line. See Math Selection for a discussion of how the navigation keys work in a math zone. An important point is that if you select a math structure character (start of object, end of object, or end of argument), the whole object is automatically selected.
Tab key
Typically typing the Tab key inserts a Tab character (U+0009). But depending on context, the Tab key may turn into a navigation key. For example, in a table cell, the Tab key goes to the next cell and Shift+Tab goes to the previous cell (if any). If the selection is in the last cell of a table, the Tab key inserts a new row after the last row with the insertion point in the first cell of the new row.
In math zones, the Tab key goes to the next argument of the current math function and the Shift+Tab key goes to the previous argument. This behavior was originally scheduled for Word as well, but got postponed.
In dialog window controls, Tab characters are ignored. This allows dialogs to use the Tab character to move from control to control.
Enter key
The Enter key usually inserts an end-of-paragraph character (U+000D—carriage return) and the Shift+Enter key inserts an end-of-line character (U+000B—VT). See Paragraphs and Paragraph Formatting for a discussion of the differences between these kinds of insertions. At the end of a table row, the Enter key inserts a new row after the current row. Inside a math object argument, an Enter key inserts an equation array. This is handy for the lower limit of n-ary objects like summations, which may have more than one subscript range. In a display math zone, Shift+Enter starts a new equation (see The Math Paragraph for details).
Delete key
If the current selection is nondegenerate (selects one or more characters), the Delete key deletes the selected characters. If the current selection is degenerate, i.e., an insertion point (IP), the Delete key usually deletes the character immediately following the IP. If the character is followed by one or more combining marks, the Delete key deletes the whole combining-mark sequence. Similarly if the character is followed by a variation selector, the Delete key deletes the whole variation-selector sequence. If the Ctrl key is pressed for an insertion point, the Delete key deletes the word following the IP. See Math Selection for a discussion of how the Delete and Backspace keys work in math zones. In particular, the math object is selected if you type Delete at the start of the object or Backspace at the end the object. A second Delete or Backspace then deletes the object. This behavior exists so that you don’t delete things by mistake. If you do so anyway, you can always undo your deletion by typing Ctrl+Z.
Backspace key
The Backspace key is similar to the Delete key but has some differences in addition to operating on the character preceding the insert point. If the current selection is nondegenerate, the Backspace key acts the same as the Delete key and deletes the selected characters. If the current selection is degenerate, i.e., an insertion point, the Backspace key usually deletes the character immediately preceding the insertion point. If that character is a combining mark, the Backspace key deletes that combining mark alone. This differs from the Delete key at the start of a combining-mark sequence, which deletes the whole combining-mark sequence. If the preceding character is a variation selector, the Backspace key deletes the whole variation-selector sequence. If the Ctrl key is pressed for an insertion point, the Backspace key deletes the word preceding the IP. See Math Selection for a discussion of how the Backspace key works in math zones. In particular, the math object is selected if you type Backspace at the end the object. A second Backspace then deletes the object. Alt+Backspace is an alias for Ctrl+Z (undo).
Hot Keys like Ctrl+C
The following table lists additional hot keys handled by RichEdit
Key | Shift | Ctrl | Alt | Action |
= | ✓ | Toggle subscript mode (not in math zone) Build up selected math text (in math zone) | ||
= | ✓ | ✓ | Toggle superscript mode (not in math zone) Build down selected math text (in math zone) | |
= | ✓ | Insert math zone | ||
= | ✓ | ✓ | Build down selected math text | |
= | ✓ | ✓ | ✓ | Build up selected math text (doesn’t have to be in math zone) |
– | ✓ | Insert soft hyphen (U+00AD) | ||
– | ✓ | ✓ | Insert nonbreaking hyphen (U+20✓✓) | |
, | ✓ | Cedilla accent dead key (English only) | ||
‘ | ✓ | Acute accent dead key (English only) | ||
“ | ✓ | ✓ | Smart quotes (English only) | |
~ | ✓ | ✓ | Tilde accent dead key (English only) | |
; | ✓ | Dieresis accent dead key (English only) | ||
` | ✓ | Grave accent dead key (English only) | ||
> | ✓ | ✓ | Make font bigger | |
< | ✓ | ✓ | Make font smaller | |
! | ✓ | ✓ | ✓ | Insert ¡ (inverted !, English only) |
? | ✓ | ✓ | ✓ | Insert ¿ (English only) |
} | ✓ | Move to other end of bracketed expression (…), […], {…} | ||
1 | ✓ | Single spacing | ||
2 | ✓ | Double spacing | ||
5 | ✓ | 1.5 spacing | ||
6 | ✓ | Caret accent dead key (English only) | ||
A | ✓ | Select All | ||
A | ✓ | ✓ | Toggle all caps | |
B | ✓ | Toggle bold | ||
C | ✓ | Copy selection (Ctrl+Insert is an alias) | ||
E | ✓ | Center selected paragraph(s) | ||
E | ✓ | ✓ | Insert € (except for languages noted below) | |
I | ✓ | Toggle italic | ||
J | ✓ | Justify selected paragraph(s) | ||
L | ✓ | Left align selected paragraph(s) | ||
L | ✓ | ✓ | Cycle through bullet/numbering types | |
Q | ✓ | Alias for alt+= | ||
R | ✓ | Right align selected paragraph(s) | ||
U | ✓ | Toggle underline | ||
V | ✓ | Paste (Shift+Insert is an alias) | ||
X | ✓ | Copy selection and delete it | ||
X | ✓ | Convert from hex to Unicode and vice versa | ||
Y | ✓ | Redo | ||
Z | ✓ | Undo | ||
F3 | ✓ | If first selected letter is lower-case, change to title case; else change to lower case | ||
F8 | ✓ | ✓ | ✓ | Turn on table autofit |
F12 | ✓ | ✓ | ✓ | Same as Alt+X |
The RichEdit client enables the Ctrl+B, Ctrl+I, and Ctrl+U hot keys by sending the EM_SETFORMATACCELERATORS message (WM_USER + 363) with LPARAM having nonzero bits for the effects CFE_BOLD, CFE_ITALIC, and CFE_UNDERLINE, respectively, effects defined in richedit.h, The Euro (€) isn’t inserted by Ctrl+Alt+E for the following languages: UK English, Eire English, Polish, Portuguese, Hungarian, Vietnamese, New Tai Lue, Ogham, Hawaiian, Gaelic, Sesotho, Twana, Kyrgyz, Igbo, Latvian, Georgian, Hebrew, Pashto, Latin, Maltese, Cherokee, Myanmar, Sinhalese, Syriac, Inuktitut, Khmer, Tibetan, and Hindi.
The Alt+x bit inspired me. This will add support for the same functionality in modern version of PowerShell.
Set-PSReadLineKeyHandler -Key 'Alt+x' -BriefDescription ToggleCharacterHexCode -LongDescription 'Toggle between Unicode hex digits and character.' -ScriptBlock {
$line = $cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
try {
...
Cool! One potential problem: if the character you want follows a valid hex digit, then that hex digit may be included in the conversion. To prevent this, RichEdit and Word convert what precedes an insertion point, but if text is selected, then they only convert what's selected. Alt+x also works with math-italic characters in the range U+1D434..U+1D467, that is, 𝐴..𝑧. This is handy if you want to use Alt+x in math zones.
I just looked into both of those issues, and it doesn't appear I can fix them for now:
PSReadLine currently chokes on anything that requires surrogate pairs to encode in UTF16, putting the math-italic range out of reach. Does RichEdit/Word special case just that range? Experimentally, Alt+x doesn't seem to toggle random emojis into their hex value in Word.
Also, PSReadLine doesn't seem to provide an API for setting the current selection. That prevents...