aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core-commands.c
AgeCommit message (Collapse)AuthorFilesLines
2025-07-22refactored =/==/=== command into stdio-commands.cRobin Haberkorn1-205/+2
There will be a lot more commands for terminal/message input and output soon.
2025-07-21discriminate against interactive-only codepaths in the imlementation of =/==/===Robin Haberkorn1-1/+2
Small slow downs will not be noticable for interactively executed commands, so we can well discriminate (G_UNLIKELY) against such code paths.
2025-07-21support <==> and <===> for printing octal and hexadecimal numbersRobin Haberkorn1-44/+180
* These are famously in DEC TECO-11, but also in Video TECO. * The implementation is tricky. They need to use lookahead states, but this would be inacceptable during interactive execution. Therefore only if executing from the end of the command line `==` and `===` are allowed to print multiple values. The number is therefore also not popped form the stack immediately but only peeked. It's popped only when it has been decided that the command has ended. * This may break existing macros that use multiple `=` in a row to print multiple values from the stack. You will now e.g. have to insert whitespace to separate such `=` commands.
2025-07-18revised command topicsRobin Haberkorn1-8/+8
* Added some keywords. * Consistently added command variants with all modifiers. In principle including modifiers in the topics is unnecessary - you can always strip the modifiers and look up the raw command. However, looking up a command with modifiers can speed up the process (compare looking up ?S<TAB> vs ?::S<TAB> * The `@` modifier is listed only for commands without string arguments.
2025-07-18<nEL> (set EOL mode) now sets the buffer's dirty flagRobin Haberkorn1-0/+7
* While it doesn't directly change the buffer's contents in bytes, a subsequent write would result in a different file on disk, so it is consequent to remind the user of saving or discarding changes. * Will also fix :EX after changing the EOL mode.
2025-07-18support <:]q> (pop Q-Register) for getting a success/failure booleanRobin Haberkorn1-1/+2
* Could be used to check whether the stack is currently empty, although peeking would be cumbersome: `:]q"S [q !...! | !...! '` * This is from DEC TECO-11.
2025-07-13implemented <ER> command for reading a file into the current bufferRobin Haberkorn1-0/+2
* This command exists in Video TECO. In Video TECO it also supports reading multiple files with a glob pattern -- we do not support that as I am not convinced of its usefulness. * teco_view_load() has been extended, so it can read into dot without discarding the existing document.
2025-07-11<EF> supports a numeric buffer id nowRobin Haberkorn1-1/+1
* ED hooks are not executed in this case * <EF> is now allowed even when editing a Q-Reg, unless you try to close the current buffer
2025-07-04implemented <^B> for returning the current dateRobin Haberkorn1-0/+42
* It is encoded with the same formula as on VAX/VMS on TECO-11, on TECOC and TECO-64. * As an extension, when colon-modified it returns the number of seconds since the epoch. It might be even more useful to return the microseconds since the epoch, but that would require 64-bit integers, which can theoretically be disabled at build time.
2025-06-08^S/^Y calculates the glyph offsets earlierRobin Haberkorn1-11/+18
* Previously, deleting text after a text match or insertion could result in wrong ^S/^Y results. In particular, the amount of characters deleted by <FD> at the end of a buffer couldn't be queried. * This also fixes the M#rf (reflow paragraph) macro.
2025-06-07added <FN> as a search-and-replace variant of <N>Robin Haberkorn1-0/+2
* This is not in Video TECO, but TECO-11 has a search-and-replace variant of <N>. <N> however is a search-over-page-boundary command in TECO-11, which has been repurposed as search-over-buffer-boundary in Video TECO and SciTECO. * <N> and <FN> no longer call the edit hook after *every* invocation, but only if the current buffer changes. This is not really relevant with the current default hook from fallback.teco_ini, but might be depending on the use case. * Added testcases both for <N> and <FN>.
2025-06-01<nA> and <nQq> now return -1 in case the index n is out of rangeRobin Haberkorn1-13/+6
* The old behavior of throwing an error was inherited from Video TECO. * The command is now more similar to TECO-11. * Since -1 is taken, invalid and incomplete UTF-8 byte sequences are now reported as -2/-3. I wasn't really able to provoke -3, though.
2025-05-24<EI> has been repurposed and is the macro file inclusion (indirect file) ↵Robin Haberkorn1-19/+13
command now * Improves DEC TECO-11 compatibility. * <EM> is still supported as a synonym, but considered deprecated and is no longer documented. A warning is printed when invoked. It can be repurposed at any time in the future. * `EI$` is not yet supported. I am unsure whether this makes any sense.
2025-05-23<^C> is a plain "return" command now, while <^C^C> exits from the programRobin Haberkorn1-97/+178
* This may break existing macros! ^C is now essentially a synonym for $$ and may not terminate the program when called from a non-toplevel macro frame. However it improves compatibility with TECO-11. * In contrast to TECO-11, ^C^C (exit) can be typed completely in upcaret mode. Otherwise it wouldn't have been possible to use the exit command in ASCII-only scripts. * The implementation of ^C^C uses a lookahead state similar to ^[ (escape). ^C does not return immediately, but the following character determines whether it will perform a return or exit. It's one of the rare cases in SciTECO where this is possible and safe since ^C is also disallowed on the command-line to avoid undesired command-line terminations after ^C interruptions. (You can only use $$ to terminate the command-line interactively.)
2025-05-18allow process exit status to be determined by macrosRobin Haberkorn1-1/+8
* Any value left on the numeric stack now determines the exit code. This ensures you can call n^C as the SciTECO version of exit(n). It will also work with n$$ in the top level macro. But you don't necessarily need any of these commands. * Could be useful in shell scripting as in `sciteco -e "@EB/file/ :@S/foo/\"F1'"` to fail `foo` is not found.
2025-05-03disallow command-line termination ($$) while editing the command-line ↵Robin Haberkorn1-0/+12
replacement register (after `{`) I found that terminating the command-line while editing the replacement register, leaves you in a hard-to-recover state. You can/should no longer call `}`, so you would have to go back to the last buffer (Q*U*). Instead, this is now checked against and a test case has also been added.
2025-04-13fixed undoing bitfields on WindowsRobin Haberkorn1-64/+64
* It turns out that `bool` (_Bool) in bitfields may cause padding to the next 32-bit word. This was only observed on MinGW. I am not entirely sure why, although the C standard does not guarantee much with regard to bitfield memory layout and there are 64-bit available due to passing anyway. Actually, they could also be layed out in a different order. * I am now consistently using guint instead of `bool` in bitfields to prevent any potential surprises. * The way that guint was aliased with bitfield structs for undoing teco_machine_main_t and teco_machine_qregspec_t flags was therefore insecure. It was not guaranteed that the __flags field really "captures" all of the bit field. Even with `guint v : 1` fields, this was not guaranteed. We would have required a static assertion for robustness. Alternatively, we could have declared a `gsize __flags` variable as well. This __should__ be safe since gsize should always be pointer sized and correspond to the platform's alignment. However, it's also not 100% guaranteed. Using classic ANSI C enums with bit operations to encode multiple fields and flags into a single integer also doesn't look very attractive. * Instead, we now define scalar types with their own teco_undo_push() shortcuts for the bitfield structs. This is in one way simpler and much more robust, but on the other hand complicates access to the flag variables. * It's a good question whether a `struct __attribute__((packed))` bitfield with guint fields would be a reliable replacement for flag enums, that are communicated with the "outside" (TECO) world. I am not going to risk it until GCC gives any guarantees, though. For the time being, bitfields are only used internally where the concrete memory layout (bit positions) is not crucial. * This fixes the test suite and therefore probably CI and nightly builds on Windows. * Test case: Rub out `@I//` or `@Xq` until before the `@`. The parser doesn't know that `@` is still set and allows all sorts of commands where `@` should be forbidden. * It's unknown how long this has been broken on Windows - quite possibly since v2.0.
2025-04-09fixup: <EI> command can be at-modified as in `@EI/foo/`Robin Haberkorn1-1/+2
2025-04-09tightened rules for specifying modifiersRobin Haberkorn1-47/+129
* Instead of separate stand-alone commands, they are now allowed only immediately in front of the commands that accept them. * The order is still insignificant if both `@` and `:` are accepted. * The number of colon modifiers is now also checked. We basically get this for free. * `@` has syntactic significance, so it could not be set conditionally anyway. Still, it was possible to provoke bugs were `@` was interpreted conditionally as in `@ 2<I/foo/$>`. * Even when not causing bugs, a mistyped `@` would often influence the __next__ command, causing unexpected behavior, for instance when typing `@(233C)W`. * While it was theoretically possible to set `:` conditionally, it could also be "passed through" accidentally to some command where it wasn't expected as in `:Ifoo$ C`. I do not know of any real useful application or idiom of a conditionally set `:`. If there would happen to be some kind of useful application, `:'` and `:|` could be re-allowed easily, though. * I was condidering introducing a common parser state for modified commands, but that would have been tricky and introduce a lot of redundant command lists. So instead, we now simply everywhere check for excess modifiers. To simplify this task, teco_machine_main_transition_t now contains flags signaling whether the transition is allowed with `@` or `:` modifiers set. It currently only has to be checked in the start state, after `E` and `F`.
2025-04-08improved rubbing out commands with modifiersRobin Haberkorn1-16/+27
* This was actually broken if the command is preceded by `@` and `:` characters, which are __not__ modifiers. E.g. `Q:@I/foo^W` would have rubbed out the `:` register as well. * Also, since it was all done in teco_state_process_edit_cmd(), it would also rub out modifier characters from within string arguments, E.g. `@I/::^EQ^W` * Real commands now have their own ^W rubout implementation, while the generic fallback just rubs out until the start state is re-established. This fails to rub out modifiers as in `@I/^W`, though. * Real command characters now use the common TECO_DEFINE_STATE_COMMAND(). * Added test cases for CTRL+W rub out. A few control characters are now portably available to tests via environment variables `$ESCAPE`, `$RUBOUT` and `$RUBOUT_WORD`.
2025-03-29added `@W`, `@P`, `@V` and `@Y` command variantsRobin Haberkorn1-5/+15
* They swap the default order of skipping characters. For positive arguments: first non-word chars, then word chars. * This is especially useful after executing the non-at-modified versions. For instance, at the beginning of a word, `@W` jumps to its end. `@V` would delete the remainder of the word. * Since they have to evaluate the at-modifier, which has syntactic significance, the command implementations can no longer use transition tables, so they are in the switch-statements instead.
2025-03-23the ^W immediate editing command now mimics `Y` more closely and also rubs ↵Robin Haberkorn1-1/+1
out no-op commands (whitespace) * In string arguments, ^W first rubs out non-word chars (usually whitespace), so it makes sense if ^W would work analogously at the command level. A non-command would be one of the no-ops.
2025-03-22added `P` command as a reverse form of `W`Robin Haberkorn1-1/+2
* All the movement commands have shortcuts for their negative forms: `R` instead of `-C`, `B` instead of `-L`. Therefore there was always the need for a `-W` shortcut as well. * `P` is a good choice because it is a file IO command in TECO-11, that does not make sense supporting. In Video TECO it toggles between display windows (ie. split screens) and I do not plan to support multiple windows in SciTECO. * Added to the cheat sheet.
2025-03-22factored out all cursor movement and deletion commands into the new ↵Robin Haberkorn1-599/+1
compilation unit move-commands.c * This made sense to include both `W` and `V`, so we also included `D` and `K`. `^Q` is included since it converts between lines and glyphs. * These are all single-letter commands, so they aren't complete parser states but callbacks to be referenced in teco_machine_main_transition_t.
2025-03-22harmonized all word-movement and deletion commands: they move/delete until ↵Robin Haberkorn1-20/+89
the beginning of words now * All commands and their documentations were inconsistent. * ^W rubbed out to the beginning of words. * Shift+Right (fnkeys.tes) moved to the beginning of the next word if invoked at the beginning of a word and to the end of the next word otherwise. * <W> (and <V> and <Y> by extension) moved to the end of the next word. * The cheat sheet would claim that <W> moves to the beginning of the next word. * Video TECO's <W> command would differ again from everything else. With positive arguments, it moved to the beginning of words, while with negative it moved to end of words. I decided not to copy this behavior. * It has been decided to adopt a consistent beginning-of-words policy. -W therefore differs from Video TECO in moving to the beginning of the current or previous word. * teco_find_words() is now based on parsing the document pointer, instead of relying on SCI_WORDENDPOSITION, since the latter cannot actually be used to skip strictly non-word characters. This requires a constant amount of Scintilla messages but will require fewer messages only when moving for more than 3 words. * The semantics of <W> are therefore now consistent with Vim and Emacs as well. * Shift+Right/Left is still based on SCI_WORDENDPOSITION, so it's behavior differs slightly from <W> for instance at the end of lines, as it will stop at linebreaks. * Unfortunately, these changes will break lots of macros, among others the M#rf, M#sp and git.blame macros ("Useful macros" from the wiki).
2025-03-15Curses: use special ellipsis symbol instead of "..." when truncating stringsRobin Haberkorn1-1/+1
This requires Unicode icon support to be enabled via ED. The ellipsis symbol is shorter and more distinctive, allowing more of the original text to be preserved before truncation.
2025-03-13rewrote <W> command on the same basis as <V> and <Y>Robin Haberkorn1-61/+57
* <W> was also using keyboard movement commands. * This fixes an inconsistency between the handling of punctuation characters, e.g. "(word" followed by -W vs. Y.
2025-03-08fixed the `Y` command: no longer delete any characters after dotRobin Haberkorn1-31/+23
* This has __always__ been broken. It's been especially annoying when pressing `Y` at the end of a line with trailing whitespace since the linebreak would also be deleted. This was because `Y` always deleted the entire word or non-word character-span. This was inconsistent with `V`. * We now use SCI_WORDSTART|ENDPOSITION instead of the keyboard commands. It therefore also requires less Scintilla messages (4+2*n vs. 4+4*n). Most importantly, we can now check for errors before changing the buffer, so there is no need to undo anything in case of errors. This should always be the preferred strategy. * Added test case.
2025-02-16implemented mouse support via special ^KMOUSE and <EJ> with negative keysRobin Haberkorn1-37/+109
* You need to set 0,64ED to enable mouse processing in Curses. It is always enabled in Gtk as it should never make the experience worse. sample.teco_ini enables mouse support, since this should be the new default. `sciteco --no-profile` won't have it enabled, though. * On curses, it requires the ncurses mouse protocol version 2, which will also be supported by PDCurses. * Similar to the Curses API, a special key macro ^KMOUSE is inserted if any of the supported mouse events has been detected. * You can then use -EJ to get the type of mouse event, which can be used with a computed goto in the command-line editing macro. Alternatively, this could have been solved with separate ^KMOUSE:PRESSED, ^KMOUSE:RELEASED etc. pseudo-key macros. * The default ^KMOUSE implementation in fnkeys.tes supports the following: * Left click: Edit command line to jump to position. * Ctrl+left click: Jump to beginning of line. * Right click: Insert position or position range (when dragging). * Double right click: insert range for word under cursor * Ctrl+right click: Insert beginning of line * Scroll wheel: scrolls (faster with shift) * Ctrl+scroll wheel: zoom (GTK-only) * Currently, there is no visual feedback when "selecting" ranges via right-click+drag. This would be tricky to do and most terminal emulators do not appear to support continuous mouse updates.
2025-01-19support :EF for saving a file before closing itRobin Haberkorn1-45/+0
Analoguous to :EX, but always saves the file like EW$, not only if it's dirty.
2025-01-13updated copyright to 2025Robin Haberkorn1-1/+1
2024-12-28avoid some compiler warningsRobin Haberkorn1-1/+1
2024-12-13SciTECO lexing: fixed styling of commands after dollar or escape (when used ↵Robin Haberkorn1-1/+2
as a separate command)
2024-12-13document the FK...$^SR idiomRobin Haberkorn1-0/+2
* We don't actually have to negate ^S results after FK. For deleting the matched pattern, you can use ^YD or -^SD.
2024-12-13implemented Scintilla lexer for SciTECO code, i.e. TECO syntax highlightingRobin Haberkorn1-5/+15
* this works by embedding the SciTECO parser and driving it always (exclusively) in parse-only mode. * A new teco_state_t::style determines the Scintilla style for any character accepted in the given state. * Therefore, the SciTECO lexer is always 100% exact and corresponds to the current SciTECO grammer - it does not have to be maintained separately. There are a few exceptions and tweaks, though. * The contents of curly-brace escapes (`@^Uq{...}`) are rendered as ordinary code using a separate parser instance. This can be disabled with the lexer.sciteco.macrodef property. Unfortunately, SciTECO does not currently allow setting lexer properties (FIXME). * Labels and comments are currently styled the same. This could change in the future once we introduce real comments. * Lexers are usually implemented in C++, but I did not want to draw in C++. Especially not since we'd have to include parser.h and other SciTECO headers, that really do not want to keep C++-compatible. Instead, the lexer is implemented "in the container". @ES/SCI_SETILEXER/sciteco/ is internally translated to SCI_SETILEXER(NULL) and we get Scintilla notifications when styling the view becomes necessary. This is then centrally forwarded to the teco_lexer_style() which uses the ordinary teco_view_ssm() API for styling. * Once the command line becomes a Scintilla view even on Curses, we can enabled syntax highlighting of the command line macro.
2024-12-08implemented the ^Q command for converting between line and glyph positionsRobin Haberkorn1-0/+65
* As known from DEC TECO, but extended to convert absolute positions to line numbers as well. :^Q returns the current line. * Especially useful in macros that accept line arguments, as it is much shorter than something like ^E@ES/LINEFROMPOSITION//+Q.l@ES/POSITIONFROMLINE//:^E-. * On the other hand, the fact that ^Q checks the line range means we cannot easily replace lexer.checkheader with something like [:J 0,^Q::S...$ ]: Using SCI_POSITIONFROMLINE still has the advantage that it returns `Z` for out-of-bounds ranges which would be cumbersome to write with the current ^Q. * Perhaps there should be a separate command for converting between absolute lines and positions and :^Q should be repurposed to return a failure boolean for out-of-range values? * fnkeys.tes could be simplified.
2024-12-06support the ::S anchored search (string comparison) command (and ::FD, ::FR, ↵Robin Haberkorn1-23/+31
::FS as well) * The colon modifier can now occur 2 times. Specifying `@` more than once or `:` more than twice is an error now. * Commands do not check for excess colon modifiers - almost every command would have to check it. Instead, a double colon will simply behave like a single colon on most commands. * All search commands inherit the anchored semantics, but it's not very useful in some combinations like -::S, ::N or ::FK. That's why the `::` variants are not documented everywhere. * The lexer.checkheader macro could be simplified and should also be faster now, speeding up startup. Eventually this macro can be made superfluous, e.g. by using 1:FB or 0,1^Q::S.
2024-12-04the <Xq> command now supports the @ modifier for cutting into the registerRobin Haberkorn1-1/+3
* Can be freely combined with the colon-modifier as well. :@Xq cut-appends to register q. * This simply deletes the given buffer range after the copy or append operation as if followed by another <K> command. * This has indeed been a very annoying missing feature, as you often have to retype the range for a K or D command. At the same time, this cannot be reasonably solved with a macro since macros do not accept Q-Register arguments -- so we would have to restrict ourselves to one or a few selected registers. I was also considering to solve this with a special stack operation that duplicates the top values, so that Xq leaves arguments for K, but this couldn't work for cutting lines and would also be longer to type. * It's the first non-string command that accepts @. Others may follow in the future. We're approaching ITS TECO madness levels.
2024-12-04implemented ^Y/^S commands for receiving pattern match/insertion ranges and ↵Robin Haberkorn1-2/+118
lengths (refs #27) * Allows storing pattern matches into Q-Registers (^YXq). * You can also refer to subpatterns marked by ^E[...] by passing a number > 0. This is equivalent to \0-9 references in many programming languages. * It's especially useful for supporting TECO's equivalent of structural regular expressions. This will be done with additional macros. * You can also simply back up to the beginning of an insertion or search. So I...$^SC leaves dot at the beginning of the insertion. S...$^SC leaves dot before the found pattern. This has been previously requested by users. * Perhaps there should be ^Y string building characters as well to backreference in search-replacement commands (TODO). This means that the search commands would have to store the matched text itself in teco_range_t structures since FR deletes the matched text before processing the replacement string. It could also be made into a FR/FS-specific construct, so we don't fetch the substrings unnecessarily. * This differs from DEC TECO in always returning the same range even after dot movements, since we are storing start/end byte positions instead of only the length. Also DEC TECO does not support fetching subpattern ranges.
2024-11-24added special Q-Register ":" for accessing dotRobin Haberkorn1-0/+2
* We cannot call it "." since that introduces a local register and we don't want to add an unnecessary syntactic exception. * Allows the idiom [: ... ]: to temporarily move around. Also, you can now write ^E\: without having to store dot in a register first. * In the future we might add an ^E register as well for byte offsets. However, there are much fewer useful applications. * Of course, you can now also write nU: instead of nJ, Q: instead of "." and n%: instead of "nC.". However it's all not really useful.
2024-11-24minor documentation changes: use typographic quotes instead of "Robin Haberkorn1-1/+1
2024-11-23disallow setting the radix to values lower than 2Robin Haberkorn1-6/+1
* This would actually causes crashes when trying to format numbers. * The ^R local register has a custom set_integer() method now, so that the check is performed also when using nU.^X.
2024-11-23the search mode and current radix are mapped to __local__ Q-Registers ^X and ↵Robin Haberkorn1-12/+43
^R now (refs #17) * This way the search mode and radix are local to the current macro frame, unless the macro was invoked with :Mq. If colon-modified, you can reproduce the same effect by calling [.^X 0^X ... ].^X * The radix register is cached in the Q-Reg table as an optimization. This could be done with the other "special" registers as well, but at the cost of larger stack frames. * In order to allow constructs like [.^X typed with upcarets, the Q-Register specification syntax has been extended: ^c is the corresponding control code instead of the register "^".
2024-11-23implemented search mode flag (^X): allow case-sensitive searches (closes #17)Robin Haberkorn1-1/+2
* Usually you will only want -^X for enabling case sensitive searches and 0^X for case-insensitive searches (which is also the default). * An open question is what happens if the user sets -^X and then calls a macro. The search mode flag should probably be stacked away along with the search-string. This means we'd need a ^X special Q-Reg as well, so you can write [^X[_ 0^X S...$ ]_]^X. Alternatively, the search mode flag should be a property of the macro frame, along with the radix.
2024-10-30fixed invalid memory access when executing the F< command (but only when ↵Robin Haberkorn1-1/+1
jumping to the beginning of the macro) * I am not sure whether this feature is really that useful... * teco_machine_main_t::macro_pc is now pointing to the __next__ character to execute, therefore it's easier to manipulate by flow control commands. Also, it can now be unsigned (gsize) like all other program counters. * Detected thanks to running the testsuite under Valgrind.
2024-10-16fixup: use teco_machine_t::must_undo instead of trying to identify the ↵Robin Haberkorn1-5/+2
current state machine * The previous solution was not wrong, but unnecessarily complex. We already have a flag for exactly this purpose. * Avoid redundancies by introducing teco_machine_stringbuilding_set_codepage().
2024-10-15fixed memory corruptions due to undoing the ↵Robin Haberkorn1-1/+5
teco_machine_stringbuilding_t::codepage * It's contained in teco_machine_main_t which is created per macro call frame. So after macro calls, the machine no longer exists. It is therefore unsafe to undo its members indiscriminately. * On the other hand, we must undo the codepage setting when run interactively, so it is now only undone when belonging to the commandline macro frame. * This was actually causing memory corruptions on every fnkeys cursor movement, but never caused crashes - probably because the invalid pointers are always pointing to unused parts of the C call stack. * Initially broken in b31b8871.
2024-10-15improved support for braces within loops: warn about unclosed braces and ↵Robin Haberkorn1-2/+11
allow breaking from within braces For instance, you can now write <23(1;)> without leaving anything on the stack.
2024-09-23allow OSC-52 clipboards on all terminal emulatorsRobin Haberkorn1-4/+3
* The XTerm version is still checked if we detect running under XTerm. * Actually, the XTerm implementation is broken for Unicode clipboard contents. * Kitty supports OSC-52, but you __must__ enable read-clipboard. With read-clipboard-ask, there will be a timeout. But we cannot read without a timeout since otherwise we would hang indefinitely if the escape sequence turns out to not work. * For urxvt, I have hacked an existing extension: https://gist.github.com/rhaberkorn/d7406420b69841ebbcab97548e38b37d * st currently supports only setting the clipboard, but not querying it.
2024-09-20^W^W and ^V^V can be typed completely with upcarets now and they case fold ↵Robin Haberkorn1-2/+2
all expansions of ^EQq, ^EUq and so on * Previously, there was no way to enter upper-case mode in interactive commands since the Ctrl+W immediate editing command is interpreted everywhere. * Without the case folding of ^EQq/^EUq results, the upper and lower case modes are actually pretty useless considering that modern keyboards have caps lock. So it was clear we need this, regardless of what the classic TECOs did. The TECO-11 manual is not very clear on this. tecoc apparently does not case-fold ^EQq results. * This opens up new idioms, for instance `EUq^W^W^EQq$` in order to upper case register q. It's also the only way you can currently upper-case Unicode codepoints.