I'm trying to use Unicode box drawing characters in a C program that is intended to be portable across a range of operating systems, C compilers and environments. Example:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
printf ("┌─────┐\n");
printf ("│┼┼┼┼┼│\n");
printf ("└─────┘\n");
return EXIT_SUCCESS;
}
The above works just fine in Linux with either gcc or icc, in Windows WSL with gcc, in Windows with Cygwin gcc in both Command Prompt and Cygwin Terminal windows, and with Windows MinGW in a Command Prompt window.
That is, in all those cases, the output looks like this:
┌─────┐
│┼┼┼┼┼│
└─────┘
But with MinGW in a Cygwin Terminal, the output looks like this:
ÔöîÔöÇÔöÇÔöÇÔöÇÔöÇÔöÉ
ÔöéÔö╝Ôö╝Ôö╝Ôö╝Ôö╝Ôöé
ÔööÔöÇÔöÇÔöÇÔöÇÔöÇÔöÿ
The problem doesn't seem to be the Cygwin Terminal font, because the same program compiled with Cygwin gcc displays correctly in the same Cygwin Terminal. Also, the same MinGW program displays correctly in a Windows Command Prompt window, just not in a Cygwin Terminal.
Windows compiler versions used:
gcc (MinGW.org GCC-6.3.0-1) 6.3.0
gcc (GCC) 11.3.0 - with Cygwin
What do I need to do to fix this please?
Thanks, Peter McGavin.
Related
Under Cygwin: How can I stop output from msvc compiled programs from being transcoded in the tty.
Under Cygwin: gcc vs msvc compiled programs appear to run differently to each other under a tty. Specifically, I am seeing some strange character set translations from only msvc generated binaries output under a tty when the character's 8th bit is set. I'd really like to know how to turn off this annoying behaviour please. Consider:
screen-cap of terminal output (duplicated in a code quote below)
! pwd
/tmp/demo_dir
! echo $LC_ALL "," $LANG "," $LC_CTYPE
, ,
! ./compiled_with_gcc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_msvc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_gcc.exe
▒▒▒▒!
! ./compiled_with_msvc.exe
╬╬╬╬!
The problem is the last line. The output from the msvc compiled version is not as expected. The two programs are demonstrated above to be outputting the same data: so the last two outputs should be the same. But the tty version (without the pipe) gets changed in only the msvc case. gcc compiled program outputs are passed through the tty unharmed. The output presented here is from the cygwin terminal, but I see exactly the same output difference in xterm.
I am confident it is happenning in the tty not the terminal: because I written a standalone cygwin program in C that runs either the gcc and msvc compiled programs, either under a pipe or under a tty that is not connected to a terminal. The program logs the actual bytes received from the tty.
When running the gcc compiled one, the tty gives the '0xce's bytes as expected.
But a sequence of '0x8ec3' patterns is instead received from the msvc compiled program when listening to it via an identical tty.
When using a pipe instead of a tty, they both output '0xce's.
This notes that the msvc compiled program's output via a tty has an increased width. Given cygwin's preference for UTF-8: it is easy to suspect something is going wrong here and cygwin is causing an extra transcoding that does not happen with gcc compiled programs. I wish to turn that off... How do I successfully disable UTF-8 translations in todays cygwin.
I note that LC_ALL does not appear to be respected to stop this happenning for msvc compiled binaries accessed via a tty. Even when the C program begins with setlocale(0,"");
The output-generating program (to be alternately compiled with the two compilers for the test) is exactly as you'd expect it to be. The same C source in both cases. It simply calls printf or write with some bytes. The msvc version is compiled with Visual Studio 2019 cl.exe (all running on Windows10).
reproduce with:
#ifndef __CYGWIN__
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <io.h>
#include <fcntl.h>
#include <locale.h>
int main()
{
if(!setlocale(LC_ALL, "")) {
return 77; //historically: non-filesystem permission-denied exit-code
}
#ifndef __CYGWIN__
//Irrelevent: But avoids stackexchange users asking for it.
_setmode(1,_O_BINARY);
_set_fmode(_O_BINARY);
#endif
char *dat="\316\316\316\316";
write(1,dat,4); // printf/fflush here gives same results.
return 0;
}
#echo off
:: ugly msvc build script. ms_cl.bat
:: full of M$ hardcoded paths. Likely includes some unused libraries.
:: Load compilation environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
:: Invoke compiler with any options passed to this batch file
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x64\cl.exe" /std:c17 %* kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Build msvc version with:
! ms_cl.bat code.c
Run in terminal with:
! ./code.exe | hexdump
! ./code.exe
Build gcc version with:
! gcc code.c
Run in terminal with:
! ./a.exe | hexdump
! ./a.exe
Note identical programs, with identical output in a hex, have output transcoded differently. The msvc one being 'wrong' in my usage case.
I obviously, suspected M$ was doing some translation: so I have tried every combination of _fmode setmode() and more to set binary mode. I suspected some failed cygwin UTF-8 detection situation, so tried setting LC_ALL etc. to plain "C" mode with export in the shell. I similarly tried setting the locale within the msvc source.
Cygwin does a lot of work to make a unix-like environment under windows. Given the hexdumps above I can only guess Cygwin (or some hidden msvc console layer) are doing something quite specialised here and getting in my way. It maybe related to cygwin's migration to ConPty. Either way. I'd like help turning it off.
OP: It's been a little while. And the problem presented in the question presently remains unsolved. However, I have discovered a hacky hack hack from the planet hack that allows for avoiding the problem without solving it. I am posting this non-answer problem-avoidance-hack as an answer and will (eventually) mark it as the solution.. But only if no actual solutions to the problem can be found..
To avoid the output of msvc-compiled program from being transcoded in the tty: first pipe the output of the msvc-compiled program to a gcc compiled program that simply repeats it (such as 'cat' or 'tail -f') and connect that gcc-compiled program to the tty instead.
This hides whatever is going on in the msvc case by seperating it from the tty. The environment is then respected. The tty only knows it is connected to a gcc-compiled program -and works right.
! ./compiled_with_gcc.exe # gcc_compiled->tty = good
▒▒▒▒!
! ./compiled_with_msvc.exe # msvc_compiled->tty = bad
╬╬╬╬!
! ./compiled_with_msvc.exe|cat # msvc_compiled->gcc_compiled->tty = hacky but good
▒▒▒▒!
I've used this guide to set-up cross-compiler in Linux for Windows binaries:
http://wiki.codeblocks.org/index.php/Code::Blocks_and_Cross_Compilers
Simple programs works and generates .exe files as expected. However when I try to use specific Windows.h functions - no reasonable results.
For example Code:
int main()
{
Beep(1000, 1000);
MessageBeep(MB_OK);
return 0;
}
Don't produce system beep sound neither MessageBeep() works. Any suggestions ?
EDIT:
Output from nm
Output from objdump
I don't know is it related, but also when I execute this binary on my Linux system I get some warning on console:
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
Platform: Linux 3.2.0 x86 (Debian Wheezy)
Compiler: GCC 4.7.2 (Debian 4.7.2-5)
I am writing a program that requires advanced terminal control that is provided by ncurses but I cannot get my program to print anything to stdscr. For example if I compiled the following code I would not see "Testing.. Testing" on the screen. I have used ncurses before and I have never encountered such a problem. I do not know if this is relevant or not but I am running a fresh install of Debian (I literally installed it a couple of hours ago).
#include <ncurses.h>
int main()
{
initscr();
printw("Testing... Testing");
refresh();
return;
}
Also the above progam was compiled with,
gcc --all-warnings --extra-warnings -std=c11 filename.c -lncurses
If you want to see the text, maybe you should keep the program running when you're printing it.
#include <ncurses.h>
int main()
{
initscr();
printw("Testing... Testing");
refresh();
getch(); // Wait the user input in order to keep the program active and showing text.
endwin(); // Terminate the window to clean all memory allocations.
return;
}
You can get more informations on the ncurses "hello world": http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/helloworld.html
Cygwin64 bit
Command to compile:
gcc hello.c -o hello -ansi -pedantic-errors
Command to run
./hello
hello.c
#include<stdio.h>
int main() {
/*setbuf(stdout, 0); I KNOW THIS WILL WORK IF ADDED, it is a solution, but I want to know why line break itself is not working*/
printf("hello world!\n");
printf("hello world again!\r\n");
/*fflush(stdout); without fflush, the above strings are not showing*/
while(1)
{
}
}
Questions:
I don't want a fflush after every printf to let the terminal show the string in time, then how?
ANSWER: setbuf(stdout, 0);
Why is "\n" or "\r\n" not working in my case considering lots of posts pointed out a line break will fix the problem?
Is it true that cygwin's terminal behaves differently than normal Linux's terminal? Since I don't have linux installed, anyone give a test for me?
Or let me ask a more general question: On which kinds of terminals, the sentence "a new line will force flush" is true?
Thanks
It seems that in Cygwin, stdout isn't identified as a terminal (but as a pipe), so it isn't line-buffered by default.
Based on this answer, perhaps linking with the Cygwin DLL would help.
That program works for me under 32-bit Cygwin. Specifically, when I compile and execute this program:
#include<stdio.h>
int main() {
/*setbuf(stdout, 0); I KNOW THIS WILL WORK IF ADDED, it is a solution, but I want to know why line break itself is not working*/
printf("hello world!\n");
printf("hello world again!\r\n");
/*fflush(stdout); without fflush, the above strings are not showing*/
while(1)
{
}
}
it produces this output:
hello world!
hello world again!
and then hangs until I kill it with Ctrl-C.
I get the same behavior invoking the program from bash under the Windows console, mintty, and xterm (I doubt that the terminal would make any difference).
I'm using 32-bit Cygwin under 64-bit Windows 7. You say you're using 64-bit Cygwin, which was just announced a few days ago; I haven't tried it yet.
I suspect an issue with 64-bit vs. 32-bit Cygwin. I suggest you post to the Cygwin mailing list.
Here's a cleaned-up version of your program that should exhibit the same issue (please verify that the comments are correct):
#include <stdio.h>
int main(void) {
/* Adding setbuf(stdout, 0) here makes the output appear */
printf("hello world!\n");
/* Adding fflush(stdout) here makes the output appear */
while(1) {
/* nothing */
}
}
I know nothing about cgywin. but here I do a test in Linux.
I try the code below, and compile by : gcc -std=c90 filename.c
Without fflush It print all words before loop,so I think the newline flush the buffer! It just work!
I use SUSE gcc .
#include<stdio.h>
int main() {
/*setbuf(stdout, 0); I KNOW THIS WILL WORK IF ADDED, it is a solution, but I want to know why line break itself is not working*/
printf("hello world!\n"); /*without fflush, not shown*/
printf("hello world again!\r\n"); /*without fflush, not shown*/
/* fflush(stdout);*/
while(1)
{
}
}
I've just had this problem. I've got some code I've been working on a while and had to reinstall Cygwin on my PC. I installed the 64-bit version this time, it was x86 previously.
Built my code, ran it in the bash shell and no output.
What I didn't realize is that I have a Cygwin1.dll from the previous 32-bit version of cygwin still in my bin folder. I renamed this and ran my program and the output worked.
You may have a different issue, but if you've got different dll versions in use your bin other folders, it may cause this problem.
I found this code for a replacement gotoxy() function using C standard library only. apparently it compiles using GCC and works like the gotoxy() found in conio.h.
However I only have Borland C++ v5.5 compiler, this compiles fine but does not reposition the curser like gotoxy() in conio.h does. Can anybody verify the fact that this works when using GCC or tell me why it doesn't work using Borland?
#include<stdio.h>
#include<stdlib.h>
void gotoxy(int x, int y)
{
printf("%c[%d;%df", 0x1B, y, x);
}
int main()
{
gotoxy(10, 10);
printf("hello world");
}
The escape codes being used in your function depend on support being present in your terminal emulator. It may or may not work, depending on the environment you're using. For example, your program works as expected in Mac OS X's Terminal application, running bash in xterm compatibility mode.
You can read about ANSI escape codes for more information about this specific case, which is the "HVP – Horizontal and Vertical Position" command.
That code prints an ANSI escape sequence: <esc>[y;xf, so will only work on an ANSI terminal, or a terminal emulator that supports ANSI codes.
The issue isn't GCC vs BC++, but running in a unix-style terminal emulator that supports ANSI codes vs the Windows CMD window.
EDIT: try changing the body of gotoxy() to the following. The escape code in your sample moves the cursor to a previous line. The code ending in H should position the cursor to the requested (Y,X) coordinate.
printf("%c[%d;%dH", 0x1B, y, x);
EDIT2: since the asker is using the Windows CMD console, the correct solution is to use SetConsoleCursorPosition(). ANSI escapes aren't supported, or are incompletely supported in Win2k and later.