Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrupted output on Windows 10 and Windows 11 #160

Closed
ffaf1 opened this issue Nov 9, 2023 · 15 comments
Closed

Corrupted output on Windows 10 and Windows 11 #160

ffaf1 opened this issue Nov 9, 2023 · 15 comments

Comments

@ffaf1
Copy link

ffaf1 commented Nov 9, 2023

From my trusted Win tester:

To reproduce

module Main where

import System.Console.ANSI

main :: IO ()
main = do
  setSGR [SetColor Foreground Vivid Red]
  putStrLn "This text is in Red."
  setSGR [Reset]
  putStrLn "This text is in default colour."

Output

image

System

  • ansi-terminal >= 1.0 && < 1.1
  • Windows 10 22H2 (OS build 19045.3570)
  • running Command Prompt

Additional informations

  • There is no screen corruption when running venzone, which depends on ansi-terminal >=0.11 && <0.12, so this is a regression.
@mpilgrem
Copy link
Collaborator

mpilgrem commented Nov 9, 2023

I no longer have access to a Windows 10 machine. (This is not a problem with Command Prompt on Windows 11.) Is this also a problem in Windows Terminal (Microsoft's replacement for Command Prompt, including for Windows 10 22H2 - https://apps.microsoft.com/detail/9N0DX20HK701?rtc=1&hl=en-gb&gl=GB)? I suspect the problem may be that, on Windows 10 22H2, Microsoft does not enable Console Virtual Terminal Sequences in Command Prompt 'by default'; I need to do some research. ChatGPT suggests there is a registry setting that can be changed so that it is 'turned on'; again, I need to reseach if that suggestion is reliable.

@ffaf1
Copy link
Author

ffaf1 commented Nov 9, 2023

Thanks @mpilgrem!

Asking a tester to test an ansi-terminal-game game with a ansi-terminal-0.11.5 dependency worked, the culpirit has to be 1.0, as you probably have already guessed.

@mpilgrem
Copy link
Collaborator

mpilgrem commented Nov 9, 2023

There is a long discussion here about the Command Prompt problem and the 'registry setting' fix is in the comment that I have linked: microsoft/WSL#1173 (comment).

In short, the history is:

  • Command Prompt on Windows 10 was not ANSI-capable
  • Then, for a short period, it was ANSI-capable AND ANSI-enabled by default
  • Then, it was ANSI-capable and not ANSI-enabled by default.

As I understand it, changing the registry setting makes it ANSI-capable AND ANSI-enabled by default.

You probably have a good reason for using Command Prompt but, in case you are not wedded to it, I strongly recommend switching to Windows Terminal.

@mpilgrem
Copy link
Collaborator

mpilgrem commented Nov 9, 2023

The changed behaviour with ansi-terminal-1.0 is not a regression, as such, but a conscious dropping of 'legacy' Windows.

@ffaf1
Copy link
Author

ffaf1 commented Nov 9, 2023

Was Win 10 with the default terminal intentionally dropped as legacy in 1.0? I feel it is a tricky situation.

It is Microsoft's fault as the behaviour is not backwards compatible and is changed on Windows 11, but there is also a registry key that you can set to get the old behaviour back. So even on Windows 11, you may need to support the older terminal type.

I am not a Windows users, but fiddling with the registry seems a global system modification. I don't think I can ask in good conscience the player — this is a game — to make global modifications just to try my game.

This is an even more pressing matter for the less frivolous applications that rely on ansi-terminal. Compatibility options and the terminal type aren't available to configure per application; this looks like a massive breakage on Windows.

@mpilgrem
Copy link
Collaborator

mpilgrem commented Nov 9, 2023

An alternative to enabling the functionality through the registry is to do it in code:

module Main where

import System.Console.ANSI

import Data.Bits ( (.|.) )
import System.IO ( stdout )

-- From Win32 package:
import System.Win32.Console
         ( eNABLE_VIRTUAL_TERMINAL_PROCESSING, getConsoleMode, setConsoleMode )
import System.Win32.Types ( withHandleToHANDLE )

main :: IO ()
main = do
  -- Using Command Prompt on Windows where VT processing may not be enabled by default
  enableVTProcessing
  setSGR [SetColor Foreground Vivid Red]
  putStrLn "This text is in Red."
  setSGR [Reset]
  putStrLn "This text is in default colour."

enableVTProcessing :: IO ()
enableVTProcessing = do
  withHandleToHANDLE stdout $ \h -> do
    currentMode <- getConsoleMode h
    let newMode = currentMode .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING
    setConsoleMode h newMode

@mpilgrem
Copy link
Collaborator

mpilgrem commented Nov 9, 2023

Command Prompt on Windows 11 is, I think, ANSI-enabled by default.

You are correct that Command Prompt is, formally, the 'default' terminal on Windows 10 but, de facto, Microsoft has, essentially, dropped Command Prompt for Windows Terminal and moved on from its non-ANSI history. The shift to ansi-terminal-1.0 was discussed here and elsewhere over a long period of time: #116.

If there is demand, I will continue to try to 'patch' the ansi-terminal-0.11 series for back-portable developments made to ansi-terminal-1.0. The practical problem is testing.

@ffaf1
Copy link
Author

ffaf1 commented Nov 10, 2023

Matt, you — and @UnkindPartition, and Max — have done a tremendous job on ansi-terminal, a package which has become ubiquitous in the Haskell world whenever there is a CL/TU interface.

What I see here with ansi-terminal-1.0 are two testers of mine reporting critical breakage, breakage which was not present before. Both use Windows 10, an OS which is still supported and that (in its LTSC incarnation) will get support at least until 2029.
I recall reading #115 and participating in the Discussion on Haskell Discourse: the focus was on Win7 (a now unsupported system), Win10 was meant to work as usual.

So yes, my feeling is: yes, this is a regression. Microsoft pulled a fast one on the maintainers.

Do you happen to know whether ansi-terminal < 1.0 works on Win 11? If that is so, you could update the readme to state ansi-terminal is currently broken on the default configuration of Win10, and suggest users, depending on their needs, not to relax boundaries on ansi-terminal.
I am sure the most important users (cabal, stack, hledger, vty, etc.) would be grateful.

@torgeirsh
Copy link

(This is not a problem with Command Prompt on Windows 11.)

Command Prompt on Windows 11 is, I think, ANSI-enabled by default.

Unfortunately that's is not the case, at least in build 22621.2428:

>stack upgrade
←[0mCurrent Stack version: 2.13.1; available download version: 2.13.1.←[0m
←[0mSkipping binary upgrade, you are already running the most recent version.←[0m

@ffaf1 ffaf1 changed the title Corrupted output on Windows 10 Corrupted output on Windows 10 and Windows 11 Dec 26, 2023
@mpilgrem
Copy link
Collaborator

@torgeirsh, may I clarify: are you using Command Prompt on Windows 11 outside of a Windows Terminal tab?

@torgeirsh
Copy link

It's the older one (Conhost?), not Windows Terminal.

mpilgrem added a commit that referenced this issue Dec 30, 2023
mpilgrem added a commit that referenced this issue Dec 31, 2023
Also, in Windows Terminal and ConHost terminals, `hSupportsANSI` will yield `False` if the the processing of \'ANSI\' control characters in output is not enabled.

Also makes deprecated `hSupportsANSIWithoutEmulation` consistent with `hNowSupportsANSI`.
mpilgrem added a commit that referenced this issue Dec 31, 2023
Also, in Windows Terminal and ConHost terminals, `hSupportsANSI` will yield `False` if the the processing of \'ANSI\' control characters in output is not enabled.

Also makes deprecated `hSupportsANSIWithoutEmulation` consistent with `hNowSupportsANSI`.
@mpilgrem
Copy link
Collaborator

@ffaf1, @torgeirsh, #164 makes some additions to allow support of Windows users who use ConHost directly, rather than use Windows Terminal. Specifically, it adds hNowSupportsANSI :: IO Bool, which action will (on ConHost terminals) enable the processing of 'ANSI' control characters in output. If a user of the library wanted to support such users, they could do something like:

module Main where

import System.IO (stdout)
import System.Console.ANSI

main :: IO ()
main = do
  stdoutSupportsANSI <- hNowSupportsANSI stdout
  if stdoutSupportsANSI
    then -- do certain ANSI-related things
    else -- do something else

I think this can be released as a minor version bump, given the nature of the changes.

@ffaf1
Copy link
Author

ffaf1 commented Jan 13, 2024

Hello @mpilgrem, sorry to have taken this long to review this.

I would like to test this with my Windows tester, can I assure him the exe I send does not make any permanent changes (registry, etc.)?

@mpilgrem
Copy link
Collaborator

@ffaf1, in fact, a Stack issue caused me to issue this as ansi-terminal-1.0.2 yesterday (I discovered a problem when I went from a 'toy' test to something that also depended on Win32) and it is incorporated into the master branch of the Stack tool's code. This does not make any permanent changes; it just toggles the part of the Windows Console API that is needed to enable ANSI if it is not enabled.

@torgeirsh
Copy link

That's great! Stack was how I ran into it myself, I'm not a user of the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants