How to print spades, hearts, diamonds, etc. in C and Linux? - c

So i started off by placing an array of char
char symbols[52] = { '\x03' , '\x04', etc. . etc.)
and the first time I did it, it actually did print the hearts,spades, etc. but after changing my system locale to a korean one (idk if this is what caused it), it started giving me weird symbols that had nothing to do with it.
I also tried to do it in another computer and it actually compiled the symbols correctly.
However, then I tried moving it on to linux and it printed weird squares with a 0 0 0 3 in it.
Does anyone know why these appear or is there a better way to print these symbols?
P.S.: I'm using Visual Studio in Windows and then used the .c code in Linux

Linux systems typically use UTF-8 encoding, in which:
♠ = U+2660 = "\xE2\x99\xA0"
♣ = U+2663 = "\xE2\x99\xA3"
♥ = U+2665 = "\xE2\x99\xA5"
♦ = U+2666 = "\xE2\x99\xA6"
Edit: Unfortunately, the Windows command prompt doesn't support UTF-8, but uses the old DOS code pages. If you want your program to work cross-platform, you'll have to do something like:
#if defined(_WIN32) || defined(__MSDOS__)
#define SPADE "\x06"
#define CLUB "\x05"
#define HEART "\x03"
#define DIAMOND "\x04"
#else
#define SPADE "\xE2\x99\xA0"
#define CLUB "\xE2\x99\xA3"
#define HEART "\xE2\x99\xA5"
#define DIAMOND "\xE2\x99\xA6"
#endif

Characters like '\x03 are control characters. \x03 in particular is the character you get when you type Control-C (though typing that character often has other effects).
Some fonts happen to assign images to control character. As far as I know, there's no standard for doing so. Apparently in your previous configuration, some of the control character happened to be displayed as playing card suit symbols.
There are standard Unicode characters for those symbols:
2660 BLACK SPADE SUIT
2661 WHITE HEART SUIT
2662 WHITE DIAMOND SUIT
2663 BLACK CLUB SUIT
2664 WHITE SPADE SUIT
2665 BLACK HEART SUIT
2666 BLACK DIAMOND SUIT
2667 WHITE CLUB SUIT
(The numbers are in hexadecimal.)
Different systems encode Unicode in different ways. Windows usually uses some form of UTF-16. Linux usually uses UTF-8, but you can vary that by setting the locale.

If your Linux terminal character set is set to UTF-8, as it usually is, then you should be able to display all of the Unicode glyphs you have fonts for. Suit symbols are in the neighborhood of \u2660.
printf("A\u2660");
Should print "A" and the spade symbol, for example.

On Linux:
Verify that your locale is set to <somelanguage>_<SOMEPLACE>.UTF-8 (type locale in the termunal).
Find a Unicode chart on the web. Verify that you can copy interesting characters with a mouse and paste them to the terninal.
Learn what UTF-8 is.
Write a program.
When it doesn't work, search this site using sonething like "how to print utf-8 in Linux". There are tons and tons of relevant answers. You want to call setlocale(LC_ALL, "") at the beginning of your program, as the language standard requires, and use char, not wchar_t.
On Windows:
Give up and cry. No, really.
Type chcp 65001 in the console. No, really!
Set console fonts to Lucida. No, really!!!
Copy your Linux program over and compile and run it. (You do want to use the same program source on both OSes, right?) When it doesn't work, search for solutions online.
Go to 1.

Related

Can I change the text color through sprintf in C?

I'm new to C and I came across this code and it was confusing me:
sprintf(banner1, "\e[37╔═╗\e[37┌─┐\e[37┌┐┌\e[37┌─┐\e[37┌─┐\e[37┌─┐\e[37┌─┐\e[37m\r\n");
sprintf(banner2, "\e[37╠═╝\e[37├─┤\e[37│││\e[37│ ┬\e[37├─┤\e[37├┤\e[37 ├─┤\e[37m\r\n");
sprintf(banner3, "\e[37╩ \e[37┴ ┴┘\e[37└┘\e[37└─┘\e[37┴ ┴\e[37└─┘\e[37┴ ┴\e[37m\r\n");
I was just confused as I don't know what do \e[37 and \r\n mean. And can I change the colors?
This looks like an attempt to use ANSI terminal color escapes and Unicode box drawing characters to write the word "PANGAEA" in a large, stylized, colorful manner. I'm guessing it's part of a retro-style BBS or MUD system, intended to be interacted with over telnet or ssh. It doesn't work, because whoever wrote it made a bunch of mistakes. Here's a corrected, self-contained program:
#include <stdio.h>
int main(void)
{
printf("\e[31m╔═╗\e[32m┌─┐ \e[33m┌┐┌\e[34m┌─┐\e[35m┌─┐\e[36m┌─┐\e[37m┌─┐\e[0m\n");
printf("\e[31m╠═╝\e[32m├─┤ \e[33m│││\e[34m│ ┬\e[35m├─┤\e[36m├┤ \e[37m├─┤\e[0m\n");
printf("\e[31m╩ \e[32m┴ ┴┘\e[33m┘└┘\e[34m└─┘\e[35m┴ ┴\e[36m└─┘\e[37m┴ ┴\e[0m\n");
return 0;
}
The mistakes were: using \r\n instead of plain \n, leaving out the m at the end of each and every escape sequence, and a number of typos in the actual letters (missing spaces and the like).
I deliberately changed sprintf(bannerN, ... to printf to make it a self-contained program instead of a fragment of a larger system, and changed the actual color codes used for each letter to make it a more interesting demo. When I run this program on my computer I get this output:
The program will only work on your computer if your terminal emulator supports both ANSI color escapes and printing UTF-8 with no special ceremony. Most Unix-style operating systems nowadays support both by default; I don't know about Windows.

So how can you really print colored text in c, on windows, using gcc?

I searched and tried some solutions, none worked.
ansi escape sequences - only works for unix-based
textcolor() (conio.h and curses.h) - only in turbo c++
graphic.h - doesn't really fix it, you'd have to change your .c files to .cpp every time
Is there a simple, or simple-ish, way to print color in c?
Newer Windows can use the Unix way by enabling Virtual Terminal Sequences in the console.
Older Windows need to use SetConsoleTextAttribute. See https://learn.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes.
For example, if you want to turn text red, you'd do
#include "Windows.h"
void MakeRed() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
}

strange extended characters in ncurses

I'm writing an ncurses application, and there's a strange issue with how special characters are printed to the screen. Here's an example:
#include <ncurses.h>
int main(int argc, char *argv[])
{
initscr();
noecho();
keypad(stdscr, TRUE);
cbreak();
curs_set(0);
addch(ACS_LARROW);
addch(' ');
addch(ACS_UARROW);
addch(' ');
addch(ACS_DARROW);
addch(' ');
addch(ACS_RARROW);
addch(' ');
refresh();
getch();
endwin();
return 0;
}
So, when I run this on a tty, the characters are correctly printed as arrows (←, ↑, ↓, →), but when I try and run this on a terminal (I've tried on gnome-terminal and LXTerminal) this is the output:
< ^ v >
Is there any reason for this difference? I thought it might be font related, but I'm really out of my territory here, and my googling didn't help.
Any suggestion on how to force lxterminal (or any other terminal) to output the same characters of the tty?
ncurses decides which character to output for ACS_LARROW and friends based on your termtype. It's likely that in a tty your termtype is set to 'linux', whereas in gnome-terminal, etc it'll most likely be set to 'xterm'. Although I'm not certain, it's quite possible that the xterm termtype doesn't support these characters.
You could try running you application as so:
env TERM=linux ./a.out
Other termtypes to try are gnome, rxvt and vt102. These will output extended ASCII characters and your terminal emulator should support them. You could also try rxvt-unicode if you have it installed, that should output the correct unicode codepoints for these special symbols.
terminal emulations are sometimes coded in 7bit ASCII, and there is no corresponding Value for the arrows (with line and wedge) in this code page, so the terminal displays what comes near (that is: only the wedge).
on tty you have all the capacities of you computer (UTF-8, color encoding, ...), so the terminal can draw the arrow.
The setting of TERM is largely irrelevant. What matters is
the locale
the choice of library
the particular terminal emulator
The usual reason for this is that the program is built-with and linked-to the ncurses library rather than ncursesw:
if you use the former (ncurses) in a locale using UTF-8, ncurses will use ASCII graphics simply because it cannot draw UTF-8. ncursesw can draw using UTF-8 characters.
using ncursesw, the program will use UTF-8 as needed (since 2002, it can use either the terminfo information, or a built-in table of Unicode values). The Linux console and screen are known special cases where the terminfo cannot describe the behavior of the terminal. For others (terminals which do not support VT100 line-drawing in UTF-8 mode), you would set NCURSES_NO_UTF8_ACS.
the terminal database does in fact have an extended capability addressing the lack of VT100 compatibility vs UTF-8 (see U8 note in the terminal database). However, most people set TERM to xterm or linux and often equate those (see note in xterm FAQ).

Adding Colour To Text In C With Bloodshed

Is this possible?
I know it's possible in the command prompt using COLOR ##
but is it possible in C using bloodshed?
Thanks,
What operating system? What terminal do you have available? Note that this has nothing to do with C, let alone bloodshed. You output a string which the terminal may or may not choose to interpret as a color. You have to see how to do that with your terminal. The solution of course is not portable. One such example for a terminal supporting escape sequences is
printf("\\x1b[1;33mThis is yellow\\x1b[m(Back to default)\n");
You may be interested in ANSI terminal's color escape sequences
You may also want to look for libraries that do that for limited number of terminals. For example, ncurses could help you in Linux.
If you're on *nix, osx, or using cygwin msys on windows, your terminal should support the ANSI sequences Fred Larson mentions (not sure about osx). The normal windows terminal does not. But bloodshed can use cygwin, so you're in luck.
Here's an example:
#include <stdio.h>
#define BOLDMAGENTA "\033[1;35m"
#define BOLDGREEN "\033[1;32m"
int main(void) {
printf("%shello %sworld\n", BOLDMAGENTA, BOLDGREEN);
return 0;
}
Note that this leaves the terminal in bright green, but if your prompt sets colours, that will get reset.
Here's some explanation of ANSI escape codes:
http://en.wikipedia.org/wiki/ANSI_escape_code

Which numerical values do the F-Keys ( F[1-12]) and the Arrow-keys have?

I'd like to write an application in C which uses arrow-keys to navigate and F-keys for other functions, such as saving to a file, language selection, etc.
Propably the values depend on the platform, so how could I find out which values the keys have?
If they don't, or if you know them, I don't have to know how to find out;)
Edit:
My platforms are Linux and M$ Windows.
Therefore, I'm looking for a solution as portable as possible.
(Propably something like
#ifdef __unix__
#define F1 'some number'
/* ... */
#define ARROW_UP 'some other number'
#elif __WIN32__ || MSDOS /*whatever*/
#define F1 'something'
/* ... */
#define ARROW_UP 'something different'
#endif
)
I think that depends on $TERM, but either way it's going to be a sequence of characters. I get this:
% read x; echo $x | od -c --
^[[15~
0000000 033 [ 1 5 ~ \n
0000006
That's my F5 key, and apologies for this being a *nix-centric answer, if that's not your platform.
This problem is a lot messier than anyone would like. In brief, each of these keys sends a sequence of characters, and the details depend on which terminal emulator is being used. On Unix, you have a couple of choices:
Write your app to use the curses library and use its interface to the terminfo database.
Parse the the terminfo database yourself to find the sequences. Or to use an API, look at the sources for tput to see how this is done.
Use the command-line program tput to help discover the sequences. For example, to learn the sequence for F10, run tput kf10 | od -a. Keep in mind this changes from terminal to terminal, so you should run tput each time you run your app.
Write your application using one of the X libraries and get access to 'key symbols' rather than a sequence of characters. the XLookupKeysym function is a good place to get started; you'll find names of the symbols in /usr/include/X11/keysymdef.h. If you are going to connect over the network from non-X systems (e.g., Windows) this option is not so good.
I have no idea how to do any of this on Windows.
If you're on a Unix or Linux machine, simply enter cntl-V and then the key while in vim*. You'll see the code.
HTH
cheers,
Rob
This handy site has lots of useful nuggets of info on the raw scancodes:
http://www.win.tue.nl/~aeb/linux/kbd/scancodes.html#toc1
Some of the keys generate 2 character key codes.
One technique I have successfully used on the pc, is to get the 2 characters, and set the 7th bit on the second character, and return that character as the answer. It lets the rest of the program treat each keystroke as a single character.
The solution to your problem with depend on what keys you need to support. Hiding the translation behind a function of some sort, is generally a good idea.

Resources