Bass
Bass

Reputation: 5338

Escape sequences unprocessed under the "cygwin" terminal

I have a Java application which uses ANSI escape sequences to display colours, position the cursor, etc.

It works fine under regular Unices, and also under xterm and mintty(in Cygwin), but I'm having trouble running it under the cygwin terminal (i. e. bash launched from cmd.exe).

As you can see from the screen shot:

enter image description here

escape sequences are output "as is", without processing. On the other hand, I can easily run smth like echo -e '\033[1;31mTest' -- and colour text will be just there.

At the same time, if I launch exactly the same application from a Midnight Commander subshell, escape sequences produced by the application will be interpreted correctly:

enter image description here

Also, if I log in to my Windows box using SSH (i. e. replace the local connection with the remote one, but retain the same cygwin terminal), again, escape sequences are processed just fine.

It looks like when a subshell of some kind is created (mc or ssh), the terminal is put into some other mode. But playing with stty wasn't helpful, nor was export'ing TERM=ansi.

Could anyone please suggest any solution?

I'm running

CYGWIN_NT-6.3 UNIT-725 2.5.1(0.297/5/3) 2016-04-21 22:14 x86_64 Cygwin

and Windows 8.1.

Upvotes: 3

Views: 1732

Answers (1)

Bass
Bass

Reputation: 5338

In order for an application to be able to use ANSI escape sequences when launched from cmd.exe (TERM=cygwin), either the application itself needs to be linked with cygwin1.dll, or its output needs to be filtered through another one which is (e. g.: mc or ssh subshells).

The same C program:

#include <stdio.h>

int main() {
    const char esc = 0x1b;
    printf("%c[31;91;1mHello, World!%c[0m\n", esc, esc);
    return 0;
}

supports colour output when compiled with Cygwin GCC:

$ ldd test-ansi-escape.exe
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x7ffeeb450000)
    KERNEL32.DLL => /cygdrive/c/Windows/system32/KERNEL32.DLL (0x7ffee92c0000)
    KERNELBASE.dll => /cygdrive/c/Windows/system32/KERNELBASE.dll (0x7ffee8700000)
    cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)

but displays garbage like

←[31;91;1mHello, World!←[0m

when compiled with MSVC or mingw64-x86_64-gcc:

$ ldd test-ansi-escape.exe
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x7ffeeb450000)
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x770a0000)
    wow64.dll => /cygdrive/c/Windows/SYSTEM32/wow64.dll (0x76fd0000)
    wow64win.dll => /cygdrive/c/Windows/system32/wow64win.dll (0x77020000)
    wow64cpu.dll => /cygdrive/c/Windows/system32/wow64cpu.dll (0x77090000)
    ??? => ??? (0x1040000)
    KERNEL32.DLL => /cygdrive/c/Windows/SYSTEM32/KERNEL32.DLL (0x76480000)
    ??? => ??? (0x1040000)
    ??? => ??? (0x1040000)
    KERNEL32.DLL => /cygdrive/c/Windows/SYSTEM32/KERNEL32.DLL (0x76480000)
    KERNELBASE.dll => /cygdrive/c/Windows/SYSTEM32/KERNELBASE.dll (0x74b40000)
    MSVCR120D.dll => /cygdrive/c/Windows/SYSTEM32/MSVCR120D.dll (0x62b90000)

An alternative solution is using ConEmu as the external output filter (bash.exe running as a direct child of ConEmu.exe). This approach doesn't require linking with cygwin1.dll, as output filtering is performed by ConEmu itself. The downside is that ConEmu's support for escape sequences is limited (particularly, it doesn't understand the VT100 alternate character set used for line drawing).

Upvotes: 7

Related Questions