Search code examples
c++ncursescodepoint

"Width" of character on screen


I'm using Ncurses to write text editor. I would like to know if there is a way to determine how many different characters can be placed on screen, where each of the character is encoded with UTF-8. For example when I get screen width of 10 and one row, I can put 10 characters of width 1 with values as below:

0123456789

But when I would like to put whole row of smiling faces I can only put 4 of those, on screen of size 10:

😊😊😊😊

So in this example smiling face takes width of 2,5 on screen. I would like to know is there a way to determine width of character on the screen?


Solution

  • ncurses uses wcwidth to determine the number of columns that a "wide character" (usually a Unicode value) in a wchar_t uses. That might not be the same as what the terminal actually does, but if your locale (LC_CTYPE, etc.) is set consistently with the terminal's capabilities and configuration, the results are fairly consistent.

    While wcwidth is a standard function, it is incompletely standardized (I could digress). Most implementations use tables that are updated periodically (one source of problems), terminal emulators may/may not be consistent, and fonts may not correspond to the values in wcwidth.

    With all of that in mind, you can always ask ncurses (or some other implementation of X/Open Curses) how many columns on the screen it would use by writing into a window that you do not display. Lynx does this for example, in LYStrExtent0:

    /*
     * Determine the number of cells the given string would take up on the screen,
     * limited (in the case of wide characters) by the maxCells parameter.
     *
     * If the returnCellNum parameter is TRUE, return the number of cells;
     * otherwise, return the length (limited by the len parameter) of the prefix of
     * the string that fits in maxCells cells.
     */