Search code examples
c++unicodencurses

"Red Heart ❤️" unicode character in ncurses


Currently using WSL2, C++20, with the preprocessor directives #define _XOPEN_SOURCE_EXTENDED 1, #include <panel.h>, and flags -lpanelw -lncursesw.

Using the code provided below when I try to add the "Red Heart ❤️" character in ncurses, it causes weird bugs on the terminal window, especially when I encase it with a box. I've gotten the same problem on my MacBook as well. When I put the unicode character in a string "❤️", it gives me a const char[7], as opposed to many other unicode characters that give a const char[5]. Could this have something to do with the cause of the bugs? I would really appreciate it if someone could give me some insight into this problem.

(Ignore the cursor at the bottom right of some of the pictures, that's just a cursor problem with the terminal in VS Code).

1 Red Heart:

enter image description here enter image description here

2 Red Hearts:

enter image description here

2 Purple Hearts:

enter image description here

Code:

#define _XOPEN_SOURCE_EXTENDED 1

#include <panel.h>
#include <iostream>

int main() {
    setlocale(LC_ALL, "");
    initscr();
    raw();
    noecho();
    curs_set(0);
    refresh();
    
    WINDOW *win {newwin(8, 16, 10, 10)};
    box(win, 0, 0);
    mvwaddwstr(win, 1, 1, L"❤️");
    mvwaddwstr(win, 1, 5, L"❤️");
    wrefresh(win);

    getch();
    endwin();
}

Solution

  • The "character" "❤️" you are using is not actually a single character. It is composed of two Unicode characters, "❤"(U+2764) and a modifying U+FE0F, "VARIATION SELECTOR-16" which gives the red style of the emoji.

    You can verify the encoded form of a string by typing echo -n ❤️ | hexdump -C in WSL console, which should output

    00000000  e2 9d a4 ef b8 8f                                 |......|
    00000006 
    

    Or with Python,

    In [1]: heart="❤️"
    
    In [2]: len(heart)
    Out[2]: 2
    
    In [3]: hex(ord(heart[0]))
    Out[3]: '0x2764'
    
    In [4]: hex(ord(heart[1]))
    Out[4]: '0xfe0f'
    

    More about Variation Selectors.