1

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?

Mateusz Wojtczak
  • 1,621
  • 1
  • 12
  • 28
  • isn't that determined by the font you are using? only if each char is the same width, you are able to know beforehand how wide a certain number of chars will be. – nada Apr 08 '19 at 08:24
  • related: [std::setw and unicode character](https://stackoverflow.com/q/49858446/995714) – phuclv Apr 09 '19 at 16:20

1 Answers1

3

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.
 */
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105