why do I get the same value of "up down right left" key-press from getch() - curses

I write a small program about B-Trix. And I want to use getch() to get gamer's input.
I try to get the value of up,down,right,left key-press by using getch(), here is my test code:
#include <stdio.h>
#include <curses.h>
int main(void)
{
int ch;
initscr();
printw("Input a character:");
ch = getch();
printw("\nYou input a '%c'\n%d", ch, ch);
refresh();
sleep(3);
endwin();
return 0;
}
the outputs of up down left right are 27, why are these value same?
Could anybody help me?

The arrow keys were encoded by three characters in Ubuntu.
So I changed my code like this to check arrow keys.
if(kbhit()){
switch(getch()){
case 0x1b: //For case arrow pressed
if(getch() == 0x5b){
switch(getch()){
case 0x41:
turn();
break;
case 0x44:
mv_left();
break;
case 0x43:
mv_right();
break;
case 0x42:
mv_down();
break;
}
}
break;
}
}

Related

Capturing mouse click count from the Background [duplicate]

I am using "XGrabPointer" to get the mouse click events when ever they occured in the active window.But my requirement is to detect the clicks globally i.e in any application on the X11 desktop.
XGrabPointer blocks the active window so i can not move to other applications and detect the mouse click events.
Here are the codes:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
int main(int argc, char **argv)
{
Display *display;
XEvent xevent;
Window window;
int grb;
int scr;
if( (display = XOpenDisplay(NULL)) == NULL )
return -1;
unsigned int t_new=0,t_prev=0,t_diff=0;
scr = DefaultScreen(display);
window = RootWindow(display, scr);
while(1) {
XGrabPointer(display,
window,
True,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
XAllowEvents(display,AsyncPointer, CurrentTime);
XNextEvent(display, &xevent);
switch (xevent.type) {
case MotionNotify:{
printf("motion event\n");
break;
}
case ButtonPress:{
switch (xevent.xbutton.button) {
case 1:
printf("Left Click\n");
t_prev=t_new;
printf("Click Occured : [%d, %d]\n",
xevent.xbutton.x_root,
xevent.xbutton.y_root);
break;
case 2:
printf("Grabed\n");
printf("Middle Click\n");
break;
case 3:
printf("Right Click\n");
break;
case 4:
printf("Grabed\n");
printf("Scroll UP\n");
break;
case 5:
printf("Scroll Down\n");
break;
}
break;
}
}
}
XUngrabPointer(display,CurrentTime);
return 0;
}
Couldn't find an answer on how to listen to mouse events in the background as well. It's impossible to do it with mouse grabbing and you won't be able to click anywhere outside of your program.
So the solution is to read linux's /dev/input/mice device for the raw mouse input (we want button clicks) and when a low-level event occur we query X server for mouse position (can't query mouse key presses from X this way).
Display *display;
Window root_window;
XEvent event;
display = XOpenDisplay(0);
root_window = DefaultRootWindow(display);
int fd, bytes;
unsigned char data[3];
const char *pDevice = "/dev/input/mice";
// Open Mouse
fd = open(pDevice, O_RDWR);
if (fd == -1) {
printf("ERROR Opening %s\n", pDevice);
return -1;
}
int left, middle, right;
while (1) {
// Read Mouse
bytes = read(fd, data, sizeof(data));
if (bytes > 0) {
left = data[0] & 0x1;
right = data[0] & 0x2;
middle = data[0] & 0x4;
XQueryPointer(
display,
root_window,
&event.xbutton.root,
&event.xbutton.subwindow,
&event.xbutton.x_root,
&event.xbutton.y_root,
&event.xbutton.x,
&event.xbutton.y,
&event.xbutton.state
);
printf("x=%d, y=%d, left=%d, middle=%d, right=%d\n", event.xmotion.x, event.xmotion.y, left, middle, right);
}
}
Sample output
x=470, y=969, left=1, middle=0, right=0
x=470, y=969, left=0, middle=0, right=0
x=467, y=969, left=0, middle=4, right=0
x=463, y=969, left=0, middle=0, right=0
x=444, y=971, left=0, middle=0, right=2
x=441, y=971, left=0, middle=0, right=0

How can I remove the segmentation error in the following code?

In the following code, I am getting the segmentation fault. Whenever the query type is 1, we have to push element into the stack, if it is 2 then we have to pop from stack, and if it is 3 then print the maximum value in the stack.
My guess is that the error is present somewhere in the switch case. However, I am unable to spot it. Please help.
#include<bits/stdc++.h>
using namespace std;
int maxinStack(stack<int> st){
int max=st.top();
for (int i=0;i<st.size();i++){
if(st.top()>max){
max=st.top();
}
st.pop();
}
return max;
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
stack<int> s;
int querySize;
cin >> querySize;
vector<int> queryType(querySize);
queue<int> queryData;
for(int i=0;i<querySize;i++){
cin>>queryType[i];
if(queryType[i]==1){
int x;
cin >> x;
queryData.push(x);
}
}
/*for (int j=0;j<querySize;j++){
cout << queryType.at(j)<<" ";
}
cout << endl;
while(!queryData.empty()){
cout << queryData.front()<<" ";
queryData.pop();
}
cout << endl;
*/
for (int j=0;j<querySize;j++){
switch (queryType[j]){
case 1:{
int y=queryData.front();
s.push(y);
queryData.pop();
}
case 2: s.pop();
case 3: cout << maxinStack(s)<<endl;
}
}
return 0;
}
Assuming inputs are correct, I think you forgot to put break at the end of each case handlers.
So it should be something like:
switch (queryType[j]){
case 1:{
int y=queryData.front();
s.push(y);
queryData.pop();
break;
}
case 2: s.pop(); break;
case 3: cout << maxinStack(s)<<endl; break;
}
Otherwise when it handles case 1 it will still fall-through to the next case handlers so it also does case 2 and case 3. This means that the stack is always empty and it causes segmentation fault when it handles query type of 2 - tried to pop for an empty stack.
As pointed above by #Hanjoung, your switch cases are missing break statements. Just to give you a little context on these break statements, if not specified all the cases after the matched case will also run. For eg:
switch(choice){
case 1:
case 2: // Suppose this case matched
case 3: // This will also run as no break in case 2
break;
case 4: // Will not run as break in case 3
default:
}
The reason you are getting segmentation error is because your "case 2" is popping from empty stack, and reason for running of this "case 2" is absence of break statement in "case 1".

Non-blocking input in Gforth

If we take a very simple counter using ncurses:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
int main(void) {
struct timespec start;
clock_gettime(CLOCK_REALTIME, &start);
initscr();
cbreak();
nodelay(stdscr, TRUE);
{
int key = -1;
struct timespec delay, now;
do {
clock_gettime(CLOCK_REALTIME, &delay);
delay.tv_sec = 0;
delay.tv_nsec = 1000L * 1000L * 1000L - delay.tv_nsec;
nanosleep(&delay, NULL);
clock_gettime(CLOCK_REALTIME, &now);
mvprintw(1, 1, "%ld\n", (long)(now.tv_sec - start.tv_sec));
refresh();
key = getch();
if (key >= 0)
break;
} while (now.tv_sec - start.tv_sec < 60);
}
endwin();
return 0;
}
it aborts after pressing any key (OK, because of cbreak() using ctrl-C would always work without any extra effort...).
But we can make this more complicated, like adding a function to pause the counter or resetting it on the fly (+/- 1 second).
We definitely need a non-blocking keyboard input for this.
I wonder if it possible to do this in Gforth? OK, I know how to catch interrupts like SIGINT there, but something like above, working for any key or a any predetermined key?
Use key?, it returns a flag which is true if new input is available.
You can augment the following code as you see fit, but I think it explains the basic idea of running in a loop until a key is pressed.
: run-until-key ( -- )
0
begin
\ place your terminal code here
." Num:" dup . cr
1+
key? until drop ;
If you want to wait for a specific key, just add an if before the until:
...
key? if key 13 = else false then until
...
You can also add your timer there.

scanf,fgets, fgetc get skipped inside loop

Im trying to make a recursive menu.
This program will later work with a tree(hojanodo), thats why I keep track of the root.
Problem: For some reason the fgets/fgetc is being skipped inside the recursivity on the second run, why does this happen?
I want the user to input either 1,2 or 3.(int)
What would be the fix for this? and is this the best way to implement a menu?
Here's what I have right now:(It compiles and runs so you can test it out but doesn't really work like I would like to..)
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
char ch;
int i;
struct node *left;
struct node *right;
}hojaNodo;
int handle_menu(int eventHandler, hojaNodo **root);
int opcion_menu();
char get_symbol();
int get_userMenuInput();
int intro();
int main(){
hojaNodo *treeRoot = NULL;
intro();
// system("clear");
handle_menu(opcion_menu(), &treeRoot);
return 0;
}
int opcion_menu(){
int userOption;
printf("1.Agrega un Simbolo.\n");
printf("2.Listar Codigo\n");
printf("3.Exit");
userOption = get_userMenuInput();
printf("User: %d",userOption);
if(userOption < 4 && userOption > 0){
return userOption;
}
else
return -1;
}//eof opcion_menu
int handle_menu(int userOption,hojaNodo **root){
hojaNodo *tempRoot = NULL;
tempRoot = *root;
int valor;
char simbol;
switch(userOption){
case 1:
simbol = get_symbol();
printf("Simbol: %c", simbol);
break;
case 2:
printf("List Nodes\n");
break;
case 3:
printf("Exit");
userOption = -1;
// destroy_tree(root);
break;
default:
printf("userOption Error, Bye!");
break;
}//eof switch
if(userOption != -1)
handle_menu(opcion_menu(),&tempRoot);
// return userOption;
return -1;
}//eof menu()
char get_symbol(){
/*char userKey[3]
fgets(userKey,len,stdin);*/
char simbolo;
printf("Give me a symbol.");
simbolo = fgetc(stdin);
return simbolo;
}
int get_userMenuInput(){
char userKey[3];
int userOption;
size_t len;
len = sizeof(userKey);
fgets(userKey,len,stdin);
userOption = atoi(userKey);
//printf("User Option: %d\n", userOption);
return userOption;
}
Well apart from all the comments related to recursion and other changes suggested, please check this out. fgets() function needs flushing the input stream. It can be done using fflush() or fgetc().
A simple solution would be:
In function:
int opcion_menu(){
...
fgets(userKey,2,stdin);
fgetc(stdin); // Add this statement
Also in function:
int handle_menu(int userOption,hojaNodo **root)
case 1:
printf("Give me a choice : ");
fgets(userKey,2,stdin);
fgetc(stdin); // add this statement
fgets reads in at most one less than size characters from stream and stores them into the buffer pointed to by string. This will lead the newline character still available in Input Stream which need to be flushed. If this newline character is not read from Input stream, than this would become the input for next fgets function and ultimately it will skip the fgets(since it has already got its input a newline character)
fgetc(stdin) will flush out these extra newline character.
I don't know if this might help anyone.
In my case, I had to 'free' the buffer from the char with this function:
void clean(){
char cTemp;
while((cTemp = getchar()) != '\n')
;
}
Im not really sure why this works but it does(if anyone does, please add it to my answer).
I call it right before I call get_userOption();

X11 key press translator

I would like to make a key press translator that would "convert" one key press to another, eg. Ctrl+T would be translated to Ctrl+X. I would like it to make "gobal"; to make it work in any application.
As a proof of concept I'm experimenting with the code below but it doesn't work. The problem is that when I capture a key press I send out another key press that is again captured by my code... I'm getting an infinite loop (the counter is there only to break out of the infinite loop).
How should I send out key press event from a key press event handler?
#include <stdio.h>
#include <X11/Xlib.h>
#include <xdo.h>
#include <X11/extensions/XTest.h>
int main(void)
{
Display *dpy = XOpenDisplay(0x0);
XEvent ev;
int counter;
xdo_t *xdo = xdo_new(NULL);
XGrabKeyboard(dpy, DefaultRootWindow(dpy), False,
GrabModeAsync, GrabModeAsync,CurrentTime);
for(counter = 0; counter < 10; counter++)
{
XNextEvent(dpy, &ev);
if(ev.type == KeyPress) {
XUngrabKeyboard(dpy, CurrentTime);
printf("%d %d\n", ev.xkey.keycode, ev.xany.send_event);
xdo_keysequence(xdo, CURRENTWINDOW, "A", 0);
}
}
return 0;
}

Resources