printing a message on window after i pressed enter, c using ncurses - c

I work on a project to implement the WORDLE game in C using ncurses. I have a problem. I need to implement the functionality when I pressed enter before I typed five letters to print on the window a message.
here is my code//
WINDOW *window = newwin(10, 40, 0, 0);
// Print a message on the window
waddstr(window, "Press Enter to continue...");
// Refresh the window to display the message
wrefresh(window);
wrefresh(geam);
// Wait for the user to press Enter
getch();
// Clear the window
wclear(window);

Related

XNextEvent does not work when program isn't ran from terminal

I'm trying to create a program which reacts to user key presses to display information over the screen.
I was able to create a window to display the information onto, but I have trouble grabbing the key presses - or more specifically, grabbing the key presses when running the program not directly from my terminal.
If I just run it as ./program, key presses are registered as expected, but if I run it from an sxhkd mapping, it does not work.
I put together a stripped down version of the program without the information displaying to illustrate the issue:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
Display *display;
Window window, rootwindow;
XEvent event;
KeySym escape;
display = XOpenDisplay(NULL);
rootwindow = DefaultRootWindow(display);
window = XCreateWindow(display, rootwindow,
-99, -99, 1, 1,
0, 0, InputOnly,
CopyFromParent,
0, NULL);
XSetWindowAttributes winattr;
winattr.override_redirect = 1;
XChangeWindowAttributes(display, window, CWOverrideRedirect, &winattr);
XGrabKeyboard(display, rootwindow, False, GrabModeAsync, GrabModeAsync, CurrentTime);
XMapWindow(display, window);
XSelectInput(display, rootwindow, KeyPressMask | KeyReleaseMask );
while (1)
{
XNextEvent(display, &event);
/* keyboard events */
if (event.type == KeyPress)
{
printf( "KeyPress: %x\n", event.xkey.keycode );
system("echo test >> ~/output");
/* exit on ESC key press */
if ( event.xkey.keycode == 0x09 )
break;
}
else if (event.type == KeyRelease)
{
printf( "KeyRelease: %x\n", event.xkey.keycode );
}
}
XUngrabKeyboard(display, CurrentTime);
XUnmapWindow(display, window);
XCloseDisplay(display);
return 0;
}
You can build it with gcc main.c -o program -lX11 -lXfixes -lXtst.
If you run ./program in your terminal, you should see KeyPress and KeyRelease info being printed out and be able to stop the program with ESC.
But if you map it to a keyboard shortcut somewhere, so it is not run this way, the program won't react to the key presses and won't exit on ESC (you'll need to kill it manually).
I think the culprit is setting override_redirect to the created window, but I need to do that since I don't want the program to open a new managed window but rather an overlay.
I'm not quite sure what the issue is, so the title of this question might need correcting.
Is what I'm trying to achieve possible? And if so, what am I doing wrong?
lsof output:
0r CHR 1,3 0t0 2051 /dev/null
1w CHR 1,3 0t0 2051 /dev/null
2w REG 8,3 3590712 524358 /home/eyfl/.xsession-errors
3u unix 0x00000000648e641e 0t0 4028921 type=STREAM
4u unix 0x00000000f842df04 0t0 24192 /tmp/bspwm_0_0-socket type=STREAM

ncurses only reporting mouse movement when bstate is non-zero

I'm following along with the code from
https://gist.github.com/sylt/93d3f7b77e7f3a881603
Here it is, in case of 404
#include <curses.h>
#include <stdio.h>
int main()
{
initscr();
cbreak();
noecho();
// Enables keypad mode. This makes (at least for me) mouse events getting
// reported as KEY_MOUSE, instead as of random letters.
keypad(stdscr, TRUE);
// Don't mask any mouse events
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
printf("\033[?1003h\n"); // Makes the terminal report mouse movement events
fflush(stdout);
for (;;) {
int c = wgetch(stdscr);
// Exit the program on new line fed
if (c == '\n')
break;
char buffer[512];
size_t max_size = sizeof(buffer);
if (c == ERR) {
snprintf(buffer, max_size, "Nothing happened.");
}
else if (c == KEY_MOUSE) {
MEVENT event;
if (getmouse(&event) == OK) {
snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0x%08lx",
event.y, event.x, event.bstate);
}
else {
snprintf(buffer, max_size, "Got bad mouse event.");
}
}
else {
snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
}
move(0, 0);
insertln();
addstr(buffer);
clrtoeol();
move(0, 0);
}
printf("\033[?1003l\n"); // Disable mouse movement events, as l = low
endwin();
return 0;
}
When I put that into a file and compile it (gcc -o test test.c -lncurses), in xterm, mouse movements are reported without a button press. In gnome-terminal and Konsole, the movement events are only reported if a button on my mouse is pressed!
I would usually say it's just a compatibility/ standards thing BUT when I execute:
printf '\033[?1003h' on gnome-terminal or konsole, I can see all the mouse movements reported without any buttons pressed!
So what's going on here? How do I persuade gnome-terminal and konsole to behave like xterm? Or even to behave like themselves when they are in bash mode?
EDIT: Additional clues:
It appears this code works on all terminals if I scroll my mouse wheel. It's more than likely that this is what happened when I originally tested in xterm, as even xterm requires either a button pressed or the mouse to be scrolled for this to work.
Therefore: my question becomes why does the terminal only report mouse movement after the bstate has been modified in some way, even when the terminal reports escape sequences in bash mode?

How to keep STDIN at bottom the terminal in C

I am writing a simple instant messaging client in c. It's currently working well, however if a user is typing and receives a message while typing, the message displays AFTER the text, then the user continues on the line below. It would look like this:
USER: I am trying to ty...FRIEND: Hello
pe a message. <--- (the end of the users message)
My idea is:
Somehow force the current data from stdin and load it into a buffer, then use a \r before printing FRIEND: to erase what is on the line, then print from the buffer. Does anyone have any concrete examples of how to accomplish this task?
The final result should be
FRIEND: Hello
USER: I am trying to type a message
The user started typing the message, received a message, the stdin line was shifted downwards, then the user completed their message.
Note: I am running GNOME Terminal 3.6.2 on the newest version of Linux Mint
The usual way to do this is using ncurses (any flavor of curses would work), accepting the input in one window and writing the result to another. Here is a short example:
#include <curses.h>
int
main(void)
{
bool done = FALSE;
WINDOW *input, *output;
char buffer[1024];
initscr();
cbreak();
echo();
input = newwin(1, COLS, LINES - 1, 0);
output = newwin(LINES - 1, COLS, 0, 0);
wmove(output, LINES - 2, 0); /* start at the bottom */
scrollok(output, TRUE);
while (!done) {
mvwprintw(input, 0, 0, "> ");
if (wgetnstr(input, buffer, COLS - 4) != OK) {
break;
}
werase(input);
waddch(output, '\n'); /* result from wgetnstr has no newline */
waddstr(output, buffer);
wrefresh(output);
done = (*buffer == 4); /* quit on control-D */
}
endwin();
return 0;
}
If you want to learn about VT100 control codes (as distinct from ECMA-48), vt100.net has manuals for some terminals.
Regarding the link VT100 control codes: that is a source of misinformation, as noted in the ncurses FAQ How do I get color with VT100?

Clear the input buffer

I am trying to implement the press any key to continue function by using kbhit, however, after the user presses a key for example a, it will appear in the input buffer the next time I ask the user to input a value. How do you clear the input buffer?
my code for press any button to continue is below.
void
press_any_key(void)
{
int b=0;
while (b==0)
{
b=kbhit();
}
}
I'm trying to implement the press any key to continue function by using kbhit taking this statement as a need to wait for user keyboard input to continue the program execution the below code does the job,
void press_any_key(void)
{
while(1)
{
if(kbhit())
ch = getch();
printf("You passed %c\n", ch);
}
}
Note: the above snippet doesn't try to clear the input buffer. However kbhit() is non standard instead the right way is to read a character from stdin is using fgetc.

Capturing a user's "enter" keystroke in C

I'm starting to learn C now and i'm trying to figure out how I would go about capturing when the user hits "enter." I'm looking particularly at the scanf and getc functions but I'm not quite sure how to go about it. When the user hits enter I want to perform some operations while waiting/watching for him to hit enter again... Is "enter" a new line character coming in from the console? Any advice would be much appreciated!
You can check the ascii value using fgetc().
while(condition) {
int c = fgetc(stdin);
if (c==10) {//Enter key is pressed
//your action
}
}
If you just need the input when user presses enter as input you can use scanf or getchar. Here is an example from cplusplus.com
/* getchar example : typewriter */
#include <stdio.h>
int main ()
{
char c;
puts ("Enter text. Include a dot ('.') in a sentence to exit:");
do {
c=getchar();
putchar (c);
} while (c != '.');
return 0;
}
This code prints what you entered to stdin (terminal window).
But if you do not want the input ( i know it's really unnecessary and complicated for a new learner) you should use an event handler.
printf("Hit RETURN to exit"\n");
fflush(stdout);
(void)getchar();
Ref: comp.lang.c FAQ list ยท Question 19.4b
The C language is platform-independent and does not come with any keyboard interaction on its own. As you are writing a console program, it is the console that processes the keyboard input, then passes it to your program as a standard input. The console input/output is usually buffered, so you are not able to react to a single keypress, as the console only sends the input to the program after each line.
However! If you do not demand your console application to be platform-independent, there is a non-standard library <conio.h> in some Windows compilers that has a function called getche();, which does exactly what you want - wait for a single keypress from the console, returning the char that was pressed.

Resources