ncurses window close on trigger keyboard arrow [duplicate] - c

I've been trying to find a solution to this for quite a while; I cannot get my terminal window to recognize the keypad.
Here is my code:
while (1){
if (cmd != ERR) {
printw("Controls: LEFT/RIGHT and SPACEBAR (Q TO QUIT)");
if (cmd == ' '){
// Stuff
}
else if (cmd == KEY_LEFT){
// Stuff
}
else if (cmd == KEY_RIGHT){
// Stuff
}
else if (cmd == 'q'){
// Stuff
}
refresh();
}
cmd = getchar();
}
It recognizes that I am entering space (case 1) or "q" (case 4), but it will not recognize the built in curses macros. I'm using regular C, not C++ for this. Any suggestions?

Those constants are only returned by getch() if you enable the keypad.
The function signature is:
int keypad(WINDOW *win, bool bf)
keypad(win, true) enables the keypad and keypad(win, false) disables it. win is a pointer to the window where getch() is being called.

As mentioned by Alexandre Bell, keypad has to be enabled. Enable it for the default window or the window you are working with.
keypad(stdscr, TRUE); //Enables keypad for default window
If you are still having trouble getting it to work, make sure you are using an int datatype with getch(). The function prototype for getch() is:
int getch(void);
If you are using a char datatype for the return value of getch(), then it will not be large enough to fit the return value of special characters and you will get garbage values back.

Related

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 ?
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.

How do I make characters in C using the ncurses.h library "blink"

Before I make one of these posts, I look around at around 5-10 other forums to see if my question has been answered.
There are a lot of websites that explain that my compiler doesn't have blinking enabled, and that I just need to download the package to enable it, or something to that affect
However, of all the ones that I have seen, none of them go into detail about where and how to acquire the package I need to allow blinking, or if they do then it isn't with my compiler.
So if someone could assist me, how do I enable blinking on Ubuntu with a function such as
attron(A_BLINK);
I'm aware that similarly phrased questions will get down-votes. I do not care, I just want to know how to fix my problem.
Any feedback would be really appreciated
-Edit
#include <string.h>
#include <ncurses.h>
int main(void)
{
char text[] = "Please Blink";
size_t len = strlen(text);
int i, row, col;
initscr();
getmaxyx(stdscr, row,col);
keypad(stdscr, TRUE);
noecho();
curs_set(0);
move((row / 2), (col / 2) - (len / 2));
attron(A_BLINK);
for(i = 0; i < len; ++i)
{
printw("%c", text[i]);
}
refresh();
getch();
attroff(A_BLINK);
endwin();
return 0;
}
-Ryan
ansi escape sequences
as an example of usage:
from the terminal type:
echo -e "\x1b[5;32;43m"
this results in a blinking green foreground over a yellow background
then type:
echo "test"
to display the word test as green letters over a yellow background
then, if the screen has not returned to normal operation, type:
echo -e "\1b[0m"
to reset the screen to normal
Note: the same ansi escape sequences can be output using the printf() function via:
printf( "%s\n", "\x1b[5;32;43m" );
and so on.
Blinking is a property of your terminal emulator. If your terminal does not support it, it won't happen.
FWIW, a plain xterm window does support blinking for me.
However, if you want the text to blink, you can manually make it happen by periodically overwriting the text with blanks. Something along the lines of:
int toggle = 0;
halfdelay(5);
do {
toggle = !toggle;
move((row / 2), (col / 2) - (len / 2));
printw("%*.*s", len, len, toggle ? text : "");
refresh();
} while (getch() == ERR);
nocbreak();
The halfdelay() call will cause getch() to return after 5/10ths of a second. If no key was hit within that time, ERR is returned. The nocbreak() call will disable halfdelay().

Why console cannot catch mouse event after using function system()?

When I use the function system(), I cannot catch any mouse event.
I have already know system() function is a shell command, but why using this command will block catching mouse event?
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE ConsoleWin;
INPUT_RECORD eventMsg;
DWORD Pointer;
//system("mode con cols=140 lines=40"); //after using this function,I cannot catch any mouse event
while (1)
{
ConsoleWin = GetStdHandle(STD_INPUT_HANDLE);//Get the console window
ReadConsoleInput(ConsoleWin, &eventMsg, 1, &Pointer);//Read input msg
if (eventMsg.EventType == MOUSE_EVENT && eventMsg.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) {
printf("Left button clicked.");
}
else if (eventMsg.EventType == MOUSE_EVENT && eventMsg.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED) {
printf("Right button clicked.");
}
}
return 0;
}
system() executes a new cmd.exe which resets many console flags. After each "system" you should restore console options this way:
DWORD mode;
GetConsoleMode(ConsoleWin, &mode);
system("...your command...");
SetConsoleMode(ConsoleWin, mode);
By the way, your program may have the same problem even without executing any system(). It relies on default console settings, which in turn depend on system settings and user preferences. I suggest you to add this code at the beginning of your program:
DWORD mode;
GetConsoleMode(ConsoleWin, &mode);
mode |= ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS;
SetConsoleMode(ConsoleWin, mode);

Ncurses reading numpad keys and escaping

I am trying to use ESC to escape from a program using getch(). I created a small program to demonstrate my problem.
#include <ncurses.h>
int main(void) {
int key = 0;
initscr();
noecho();
keypad(stdscr, TRUE);
do {
key = getch();
clear();
mvprintw(0, 0, "Key = %d\n", key);
refresh();
} while (key != 27);
clear();
refresh();
endwin();
return 0;
}
I am trying to allow a user to use either the arrow keys or keypad (whichever is more convenient)
the issue lies within the keypad (whether numlock is on or not). When I compile and run the program and try and use the numpad keys in this simple test it exits as soon as I touch a numpad key. If I remove the while (key != 27) (esc being 27) condition it reads the keys and displays their numbers. Why does it exit the loop when the numpad keys register as
ENTER 343
UP 120
DOWN 114
LEFT 116
RIGHT 118
Any help is much appreciated!
I found a fix in the source for Dungeon Crawl Stone Soup. It basically sets the keycodes for those.
{DCSS-dir}/source/libunix.cc (333)
define_key("\033Op", 1000);
define_key("\033Oq", 1001);
define_key("\033Or", 1002);
define_key("\033Os", 1003);
define_key("\033Ot", 1004);
define_key("\033Ou", 1005);
define_key("\033Ov", 1006);
define_key("\033Ow", 1007);
define_key("\033Ox", 1008);
define_key("\033Oy", 1009);
// non-arrow keypad keys (for macros)
define_key("\033OM", 1010); // Enter
define_key("\033OP", 1011); // NumLock
define_key("\033OQ", 1012); // /
define_key("\033OR", 1013); // *
define_key("\033OS", 1014); // -
define_key("\033Oj", 1015); // *
define_key("\033Ok", 1016); // +
define_key("\033Ol", 1017); // +
define_key("\033Om", 1018); // .
define_key("\033On", 1019); // .
define_key("\033Oo", 1020); // -
// variants. Ugly curses won't allow us to return the same code...
define_key("\033[1~", 1031); // Home
define_key("\033[4~", 1034); // End
define_key("\033[E", 1040); // center arrow
The XTERM terminal emulator sends an escape for certain numpad keys if Num Lock is off.
You can turn on Num Lock, use something other than the numpad, use something other than ESC to break your loop, or try to find a terminal emulator that doesn't do this. There is no way for your program to distinguish between ESC and certain numpad characters when Num Lock is off within the confines of your terminal emulator.

How do i stop the blocking?

Hey all I've asked this question a few times in the past few days but I just don't get it...I basically want to have the while loop for the Beep command executed in the background while the user can interact with the available case statements (only one shown..there are others)....i keep getting blocked and everytime i want the beep to make a sound constantly i block the rest of my program...I have to use Beep so please don't suggest any other functionality..
here's a sample code...
while( keypress != 'q' || keypress != 'Q')
{
x = Beep(x);
while (x == 1)
Beep(350,300);
alarm_t current;
keypress = _getch();
switch(keypress){
case 'h':
sprintf_s(current.message,"high alarm");
current.timeOfEvent = time(NULL);
recordEvent(current);
break;
Now...my issue is with the while loop and the Beep command....here is what i call to Beep(x)
int Beep(int y)
{
return y;
}
So basically i am trying to call a function outside of my current cpp file to just compare x and y, and return y as being equivalent to x...i thought this might avoid blocking but it doesn't...
Your while loop around beep just won't work and _getch is blocking. So it will just block until there's a character.
Depending what platform you are on, you need something like kbhit (and if you google that you will find alternatives for other platforms). ie it's not standard C functionality and platform specific.
kbhit will return true or false depending if there is a character or not.
So you can do:
while(!key_is_quit(ch))
{
Beep();
if(kbhit())
{
ch = getch();
// switch....
}
}

Resources