0

(No, not a hardware issue)

I have coded kbhit() in standard C as follows (obtained from here; another function "setTerm()" sets (non)canonical mode):

#include <sys/ioctl.h>

int kbhit()
{
    int bytesWaiting;
    ioctl(STDIN_FILENO,FIONREAD,&bytesWaiting);
    return bytesWaiting;
}

And I have subsequently implemented kbhit() in a program that reads and prints the keyboard input to the screen. When a key (how about 'A'?) is held, it is repeatedly printed. However, when a second key (say, 'B') is pressed while 'A' is held, 'B' is printed and no more 'A's appear. My intentions are that 'A' continues to be printed, but this is not the case. Here is some code showing the issue (meant for use with arrow keys or A-D; press Enter or '\n' to end):

#include <stdio.h>
#include "kbhit.h" //just replace this line with previous code example

int main()
{
    setTerm(0);//turns terminal to noncanonical mode; if necessary I can include the function

    int test=1;
    int c=0;
    while(test)
    {
        if(kbhit())
        {
            c = getchar();
            switch(c)
            {
                case 'A':
                case 'B':
                case 'C':
                case 'D':
                    printf("%c\n",c);
                break;
                
                case '[':
                    printf("%c",c);
                break;

                case 27:
                    printf("ESC");
                break;

                case '\n':
                    test=0;
                break;
            }
        }
    }

    setTerm(1);//restores terminal to canonical mode
}

Again, I can add my setTerm() function if necessary. But the question remains, how can I keep taking the input of the held key?

Luke Dunn
  • 39
  • 5
  • 2
    The `FIONREAD` queries the state of the _kernel_ buffer. But, `getchar` is stream buffered. You can't mix them. Start by using `read(0,...)` instead of `getchar`. But, what you really need is something lower level that can interpret keycodes (e.g. keydown, keyup, etc) so you can track the fact that the `A` remains down (e.g. no corresponding keyup) when you get a keydown for `B` – Craig Estey Sep 22 '21 at 00:31
  • @CraigEstey does ```read()``` actually let you store those bytes somewhere, or is it like ```kbhit()``` in the way it gives only a number? From the manual it seems like I won't be able to access what's in the bytes, just tell that they're there – Luke Dunn Sep 22 '21 at 02:37
  • No, I don't _think_ you can get keycodes from `read`. There are two methods. If you are using a linux "virtual terminal" or console (e.g. `ctrl-alt-F4`), you can use the linux keyboard ioctls: `man ioctl_console`. Otherwise, you'll have to use x11 events. There are widget, GTK, and SDL2 calls that can poll events. (e.g.) under SDL2, this would be `SDL_PollEvent(&e); switch (e.type) { case SDL_QUIT: break; case SDL_KEYDOWN: break; case SDL_KEYUP: break; }` If you're trying to get key events from within (e.g.) an `xterm` window, this probably won't work. There _may_ be a way, specific to `xterm` – Craig Estey Sep 23 '21 at 01:55
  • I see. Also related: https://blog.robertelder.org/detect-keyup-event-linux-terminal/ – Luke Dunn Sep 23 '21 at 20:18

0 Answers0