A program run directly by `ansicon` should always be hooked, regardless
if it's GUI or excluded. This was broken in v1.84 due to the DLL being
imported.
If the console buffer was wider than the window then the wrap buffer
would not be created, resulting in erroneous movement. Preserve the
height of the wrap buffer so the new width can be set.
I create a secondary buffer to assist with wrap detection. On Win10
1803 writing to this buffer outputs to the active buffer. Disable
virtual terminal processing to prevent it.
Windows 10's MSVCRT will only work if the Win32 version in the header is
0 or 10. Some PE's use it for something else, so when the DLL is
injected the process fails. Provide custom routines for the C functions
used, so the DLL only depends on KERNEL32.
With the DLL independent of the CRT that would mean the exe would either
also need to be independent, or the source files would need to be built
twice (or just remove a linker warning). Another option is to export
the functions from the DLL and have the exe import them, which turned
out to simplify things quite nicely.
A process that has a really long command line would not log properly, so
double the heap to accommodate it.
If ANSICON_DEF could not be parsed the default attribute would be zero
(black on black). Use 7 or -7 instead.
Windows 8 and later require the IDT to be within a section when there's
no IAT. This prevents relocated imports from working, so we cannot add
ourself to the import table. Use `LdrLoadDll` via `CreateRemoteThread`
for such a situation.
Processes on Windows 10 that return rather than call `ExitProcess` may
have a 30 second delay before terminating. This seems due to the
console creating a thread. Detect a detached primary thread and
explicitly call `ExitProcess`.
Prevent loading more libraries than necessary, so load WINMM the first
time the bell is used and use the CRT printf functions to avoid loading
USER32 at all.
I was also going to remove MSVCRT, but that turned out to be more
trouble than it's worth. However, a side-effect that I kept is
replacing bsearch with a dedicated search routine.
Some processes just return from the entry point; this only exits the
thread, not the process. It seems that when ANSICON created its flush
thread in DllMain, that became the primary thread, so when the entry
point returned the process was still waiting for the flush thread to
exit. Creating the flush thread the first time it is used avoids this
problem, letting the process exit.
Git's error messages were being truncated. Turns out git used two
threads, one writing to the console and one to file. This caused a
conflict in `IsConsoleHandle` when the cache was updated. Making it a
critical section solves the issue.
Some programs (notably less) rely on the right margin performing the
wrap. Add such programs to the ANSICON_WRAP environment variable to
stop ANSICON suppressing the newline.
Support the entire 256-color palette. When specifying an index or RGB
color, find the nearest match in the console palette. Preserve bold and
underline when setting color by index. Getting all palette entries will
stop at 15 if the initial index is below that (i.e. `0;*` will get 0 to
15 and `16;*` will get 16 to 255).
Turns out testing for an empty buffer outside the critical section
wasn't a good idea (testing in a virtual 10 started the thread between
the test and enter, causing buffer overflow in the small loop).
CR and BS would still be processed during CRM. Fix all the partial CRM
sequences followed by a complete CRM sequence.
It's possible for some text files to have `\r\r\n` endings (Microsoft
converts LF to CRLF even when the CR is already there). Collapse
multiple CRs to a single CR to catch this. It is also necessary to
always delay flushing if the last character is CR, to see if the next
character is CR or LF.
Setting the cursor position on a non-active buffer still displays it on
the active buffer. Hide the cursor, set the position, show the cursor
is a sufficient workaround.
CR will match BS/CUB/HPB, moving back to previous line(s) after a wrap.
I hadn't updated the comment when I switched ANSICON_API from WriteFile
to WriteConsoleA. Mention that is should be deleted when upgrading.
I had intended for margins to be set per process, but during testing I
was wondering why they weren't working, so per console it is.
In changing the above, I realised that `pState` may stay `NULL` when a
process is created without a window. Initialise it to a default state,
updating it when the window becomes available.
Rather than flushing immediately after every write, only flush before
accessing the console. This improves the speed, particularly for
programs that write character-by-character (which is basically every
program using Microsoft's printf). Should it go wrong, there's a new
mode to restore the immediate flush: `\e[1+h`.
Margins always use the window, never the buffer; the exception is
`\e[+r` which will remove the margins ('\e[r' will set the margins to
the window). With the margins set, the window will not scroll when the
cursor is at the bottom, outside of the margins. In this case, the
display is not quite right, since I copy the line from another buffer,
rather than actually overwrite the existing line.
Setting IRM will cause characters to be inserted, discarding anything
that goes beyond the edge.
Turn off the wrap flag when the cursor moves.
SM/RM allow more than one parameter.
SGR parameters 90-97 are bright foreground (leaving bold unchanged) and
100-107 are bright background (leaving underline/blink unchanged);
`38;5;#` & `48;5;#` will work for the first 16 colors, setting both
foreground & bold or background & underline (0-7 bold/underline off,
8-15 bold/underline on).
Save/restore the attributes and G0 character set (the ANSI version still
only does the cursor).
Add the comment I missed when adding SCS; remove `DEC` from the sequence
descriptions.
Support setting (HTS & DECST8C) and clearing (TBC) tabs, overriding the
console's own tab processing. I've extended TBC with `\e[8g` to restore
console processing and added an extra parameter to DECST8C to set a
particular tab size.
DECSC (Save Cursor) & DECRC (Restore Cursor) are the same as their
ANSI.sys equivalents (`\e[s` & `\e[u`).
DA (Device Attributes) will respond with `\e[?62;1c` - VT220 with 132
columns.
Setting DECCOLM will size the buffer & window to 132 columns; resetting
will restore the original values (NOT set 80 columns). Setting DECNSCM
will prevent the display from being erased; however, the first time
DECCOLM is used will scroll in a new window, if appropriate.
Recognise the xterm ESC]4 & ESC]104 OSC commands to set/reset colors.
Three color specs are recognised: `#RGB`, `#RRGGBB` and `R,G,B`; in
addition, multiple specs can be given (separated by commas) to
automatically increase the index. I also allow `*` to query this index
and all subsequent ones. Reset will restore the colors from when the
DLL was first loaded, not from the Console Properties.
Since ESC is now preserved for unrecognised sequences, I feel able to
use it to escape control characters in order to display them (e.g.
"\e\e" will display a single escape).
Control mode would not display the recognised controls (i.e. BEL, SO and
SI) and would not work if it was turned off in the same string.
Normally the display uses the window height; adding an intermediate
character of `+` will use the buffer height. Report cursor position
will also output `+R` when used with `+n`.
There are some differences from the VT520: volume is ignored (although
silence is honored); duration is in 1/32 of a second up to and including
48 (1.5 seconds), after which it is in milliseconds (but still a maximum
of 8 seconds); notes are 1..25, anything else is frequency.