Refresh screen every 1 second with ncurses - c

I want to refresh the screen every one second. I'm implementing a chat with ncurses.
So far, I have the following function:
void print_chat(char *chat) {
mvprintw(1, 1, "RPC Chat");
move(2, 1);
for (int i=0; i<CHAT_WIDTH; i++) {
addch('_');
}
move(CHAT_HEIGHT + 3, 1);
for (int i=0; i<CHAT_WIDTH; i++) {
addch('_');
}
mvprintw(CHAT_HEIGHT + 5, 1, "Enter message: ");
}
Which prints the following screen:
In the main function I'd like to have a loop that refreshes the screen every 1 second, obtaining possible new messages from a server, and refreshes the screen in that interval so if any, new messages could be displayed. I also want to read users input while the refreshing goes on at the same time. Do I need threads?
My attempt so far in the main function:
while (1) {
print_chat(chat);
refresh();
sleep(1);
chat = read_chat_from_server();
/*char l = getch(); --> This would block the loop, waiting for input...
}
Do I need threads to achieve this? If so, would the thread be able to reprint the screen? Any other way to solve this problem?

The problem is that getch() is waiting for the user to press return.
You want to have a look at raw() and call it once before getting any input. By calling this function you can get characters from the user without him pressing return, pausing your program. Basically the console reads user input, prints each character as its being written, and when the user sends '\n', it returns that input to your program (See this answer).
You might want to look at noecho() too. Similar to raw(), lets you scan for user input (using getch()) without printing the characters on the screen. This is usually useful for letting your program handle how the characters are displayed.
Finally, it may be a good idea to call refresh() when something gets updated (e.g. check each second if you got a message, you sent one, etc.) and then call refresh(). If you still want to run it every second, maybe try nodelay(stdscr, 1), where stdscr is your default window:
The nodelay option causes getch to be a non-blocking call. If no input is ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a key is pressed.

You need to call the timeout() function when you first initialize your program.
timeout(0) should cause getch() to not wait for user input.

Related

Get key press info out of console

I am trying to create a C application (keylogger) that works on the background and gets notified when any key is pressed on windows 10. I have used this code sample so far:
while(37) {
for(int i=0; i<256; i++) {
if(GetAsyncKeyState(i) == -32767) DoTheJob();
}
}
The main problem I have here is that it uses too much power with this infinite loop and sometimes even when I press a button the 3rd line doesn't check for that buttons key state at the first moment of the press action and the code doesn't works. I have also tried kbhit(); but it works only when I input to console not on background.

AUTOHOTKEY: Problem with code which suspend script after clicking key and unsuspend it after clicking 2 another keys. Doing 2 things at the same time

In game chat start with t key and I want that after pressing t on keyboard my script will be suspend and I will can normally write on chat but if I press enter or esc my script will be unsuspended (esc - close chat, enter - send message on chat).
I have problem with this code:
t::
Suspend On
Loop
{
GetKeyState, state, Enter, P
GetKeyState, state2, Escape, P
if (state = Enter){
Suspend Off
break
}
else if (state2 = Escape){
Suspend Off
break
}
}
return
Main problem with this code is loop which not work, and I don't know how to repair it or replace it something more useful or better solution.
Another problem is t key which work but I must click it 2 times, why? First click suspends script, second click runs chat. I want after clicking 1 time t key chat will run and script will suspend. I want the same with enter and esc, to make 2 functions at the same time (enter - unsuspends script and send message on chat, esc - close chat and unsuspends script)
The problem is with the usage of the (deprecated legacy) GetKeyState command, but I must say, the whole solution could be implemented a lot better.
The output value of the command doesn't contain key names, it contains D for down, or U for up, as stated in the documentation. And also you'd need to "quote" your strings.
And the problem with your T key not working on the first press, is of course because you have a hotkey that is capturing the press of the T key.
To not consume the T key press when the hotkey runs, you want to use the ~ modifier(docs).
But anyway, I think a better implementation would be just that a press of the keys simply suspends/unsuspends.
Like so:
~t::Suspend, On
~Enter::
~Esc::Suspend, Off
As a bonus:
The usage of #IfWinActive(docs) might be desirable so the hotkeys only work when your game is active.
#IfWinActive, ahk_exe ExeOfMyGame.exe
~t::Suspend, On
~Enter::
~Esc::Suspend, Off
#IfWinActive
I change code to this:
~t::
Suspend On
Loop
if (GetKeyState("Enter", "P") || GetKeyState("Escape", "P"))
break
Suspend Off
return
Why? Because in #0x464e code was that problem when I suspended script manually and click enter / esc it unsuspended it, I needed after click T it suspend and only enter / esc will unsuspend it. When I manually suspend it in code which is above enter / esc do not unsuspend it.

Non-blocking ReadConsoleInput

I'm writing a Win32 console application that interacts with the mouse. I'm using ReadConsoleInput to get the window-relative mouse movements like so. Here's a simplified version of my problem:
int main(void)
{
HANDLE hStdin;
DWORD cNumRead;
INPUT_RECORD irInBuf[128];
hStdin = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
while (1)
{
mouse_position_changed = 0;
ReadConsoleInput(hStdin, irInBuf, 128, &cNumRead);
/* input handler here: changes the cursor position if the mouse position changed;
clears screen if mouse position changed;
sets mouse_position_changed (self-explanatory).
(this part of the code is irrelevant to the quesiton at hand) */
if (!mouse_position_changed)
putchar('0');
}
}
(I've removed most of the code including error checks. This is a simple, watered-down version of what I'm doing; it's much larger-scale than making 0's run away from the cursor.)
I want the screen to be cleared and the cursor set to the mouse coordinates whenever the mouse is moved. This part is working.
I want 0 to be printed the screen whenever the mouse is not moved. This will have the effect of 0's running away from the mouse cursor. This is not working, because ReadConsoleInput will block until it receives input.
The 0 is not printed until more input is received. Unless the user continually hits the keyboard, nothing is printed because whenever the mouse is moved, the screen is cleared.
The problem
I would like the loop to continue even when no input is present. ReadConsoleInput waits for input to be read, which means that the loop will pause until the keyboard is hit, or the mouse is moved.
I'm looking for an alternative to ReadConsoleInput, or a way to make it non-blocking.
This is all documented in ReadConsoleInput. You can determine if there is a console input with GetNumberOfConsoleInputEvents. And you are able to to determine the type of console input events with PeekConsoleInput.
So GetNumberOfConsoleInputEvents is all you need.
You can also use WaitForSingleObject with the console handle to wait for a next available input. This is also documented in ReadConsoleInput

Displaying buffer in the desired moment

I have a GTK program with a lot of buttons. When I press one of them, my program starts to displaying a buffer, line by line, in this way:
...
gchar * stuff = g_strdup_printf("Some text");
gtk_text_buffer_insert(buffer, &iter, stuff, -1);
g_free(stuff);
while (gtk_events_pending())
gtk_main_iteration();
...
Because I manage a lot of data, this method is very slow.
I want a second plane mode when some variable reach a high value (for example an int scndplane=1). My idea for this mode is a normal execution of the main program, but to display the buffer only at the end of the program (a kind of backbuffer).
Is there any efficient way to do it?
Thank you.
Why do not you simply make a method of this and then call it at the end of your program ?
If you press your button during the exexution, put a boolean at true.
Then at the end of your program, you will have something along the lines of:
if(isClicked)
displayBuffer();

how to get Return key press event?

I'm coding a console editor in C. I'm using CodeLite Editor on Windows. I want to insert a newline ('\n') when the user presses Return (Enter) key. I want to accomplish this goal with getchar() function is that possible?
I need it because I want to increment the y axis variable.
Code I'm trying on :
int X = 0; // X-axis
int Y = 0; // Y-axis
char key = getchar();
if (key=='sth') // Here I want to perform my check
{
//Do Something
++Y;
}
Update :
If it has a code like : '\x45' for example post it in the comments plz!!!
If you are trying to implement an editor, you will quickly find that getchar() is not the way to interpret keyboard events. In this very simplistic example, where all you might do is wait for a single keystroke of input that either is or is not a newline, your program will work if you change 'sth' (an abbreviation for "something"?) to '\n'. However, as your editor becomes more complicated, you will want to have an actual event handler that can detect any sort of keyboard events and can asynchronously deal with them. getchar() is not the way to do that.
This answer from 7 years ago shows that (1) you can go a limited distance with getch() (and getchar()), but (2) a far larger number of people agree that it's no substitute for a real event handler: Detect Keyboard Event in C

Resources