Search code examples
clinuxncursesarchlinux

ncurses "get_wch" function behavior


I try to understand how the get_wch function from ncurses works.

Here is a piece of code that I use to test it under TTY, terminator, and konsole:

 #include <stdlib.h>
 #include <curses.h>
 #include <locale.h>
 
 int main(void)
 {
     // initialize curses
     initscr();
     setlocale(LC_ALL, "");   // Just a check to see if something change with it
     wint_t char_code;
     int key_code = get_wch(&char_code);
     char truc [20];
     sprintf(truc, "%d / %d", key_code, char_code);
     refresh();
     getch();
     endwin();
     
     printf("%d\n", KEY_CODE_YES);
     printf(truc);
     printf("\n");
     return 0;
 }

When I hit a "classic" key like 'a' or '?', I get a char_code (UTF-8 code, I supposed). But when I hit a function key like F1 or F12, I get a char_code 27, and a key_code 0, except for F11 (key_code: KEY_CODE_YES, char_code: 410).

The documentation say that:

When get_wch, wget_wch, mvget_wch, and mvwget_wch functions successfully report the pressing of a function key, they return KEY_CODE_YES. When they successfully report a wide character, they return OK.

F1 to F12 are the so called "function keys" ? If I'm right, could you explain me why the function return 0 as a key_code when I hit a Fx key ?


Solution

  • You'll get KEY_CODE_YES only with keypad set to true, see keypad man page about that :

    The keypad option enables the keypad of the user's terminal. If enabled (bf is TRUE), 
    the user can press a function key (such as an arrow key) and wgetch returns a single value 
    representing the function key, as in KEY_LEFT. If disabled (bf is FALSE), curses does not 
    treat function keys specially and the program has to interpret the escape sequences 
    itself. If the keypad in the terminal can be turned on (made to transmit) and off (made to 
    work locally), turning on this option causes the terminal keypad to be turned on when 
    wgetch is called. The default value for keypad is false.
    

    And you're not getting keycode 0 but the success status OK from get_wch, see related manpage.

    Without it, you'll have to get multiple char_code to get the key code like :

         wint_t char_code;
         wint_t char_code2 = 0, char_code3 = 0;
         int key_code = get_wch(&char_code);
         if (key_code == OK) key_code = get_wch(&char_code2);
         if (key_code == OK) key_code = get_wch(&char_code3);
    

    For function keys, you'll the escape code in char_code (0x27), the function code in char_code2 (0x4b) and the specific function key_code in char_code3.

    EDIT As noticed by @dratenik, with xterm/VT220+ terminals, the F5-F12 function keys output four char_code, so you'll need to query another char_code when you get [ (0x5b) in char_code2 and 1 (0x31) in char_code3 to get the specific function keys key_code for theses function keys. You'll find the possible key codes in this useful link provided by @dratenik.