user1018183
user1018183

Reputation: 95

C detect arrow keys with termios doesn't work well

I have the problem that when you press an arrow key You detect 3 input and the while loop is executed 3 times, in fact the print of the string PRINT OF DEBUG occurs three times. Why? I would that when you press a arrow key the loop is executed 1 time. How do I do it? Here the code:

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#define KEYCODE_R 0x43
#define KEYCODE_L 0x44
#define KEYCODE_U 0x41
#define KEYCODE_D 0x42

int main()
{
    int c;
    printf("\nPRESS A ARROW\n");
    while(1)
    {
        c = getch();
        printf("\nPRINT OF DEBUG\n");
        switch(c)
        {
            case KEYCODE_L:      //rilevazione pressione freccia sinistra
                printf("\nLEFT\n");     
            break;
            case KEYCODE_R:
                printf("\nRIGHT\n");         
            break;
            case KEYCODE_U:
                printf("\nFORWARD\n");
            break;
            case KEYCODE_D:
                printf("\nINDIETRO\n"); 
            break;        
        }
    }
    return 0;
}

int getch() 
{
    char c;
    struct termios before,after;
    tcgetattr (STDIN_FILENO, &before);//STDIN_FILENO e' il File Descriptor dello stdin. Salviamo in before la configurazione attuale dello stdin
    memcpy(&after, &before, sizeof(struct termios)); 
    after.c_lflag &=~ (ICANON | ECHO); //modifichiamo la configurazione dello stadin modificando il flag c_lflag con degli or e and bit a bit
    after.c_cc[VMIN] = 1;
    after.c_cc[VTIME] = 0; 
    tcsetattr (STDIN_FILENO, TCSANOW, &after); //qui effettuiamo effettivamente le modifiche

    if (read (STDIN_FILENO, &c, sizeof(char)) == -1) //read e' una system call, leggiamo dallo stdin
    {
        perror("\nErrore in lettura\nIl programma termina");
        tcsetattr (STDIN_FILENO, TCSANOW, &before);
        exit(-1);
    }

    tcsetattr (STDIN_FILENO, TCSANOW, &before); //si ripristina la configurazione dello stdin
    return c;
}

Thank you for the attention

Upvotes: 1

Views: 1300

Answers (1)

No One in Particular
No One in Particular

Reputation: 2874

The getch will end up getting three hex codes: 0x1B 0x5B and [0x41, 0x42, 0x43, or 0x44]. When it gets 0x1B (escape char), the switch statement doesn't do anything. The same for 0x5B.

The last char gotten is the one you are processing. If you want to see something, add a default to your switch statement. Adding the default will let you know that you are getting the entire escape sequence. (You should really process the input differently unless you know with absolute certainty that the user will only press the arrow keys.)

Upvotes: 2

Related Questions