Hi all -
I'm doing a little public-domain key-sequence reader - by that, I mean code that reads keys (along with any shf/alt/ctrl/esc flags) from the keyboard.
This is as part of a P.D. readline that I'm working on - I want to be able to read the arrow keys along with "ordinary" keys.
The code works, but there is a small improvement that I don't know how to do, hence this post. Here is the code -
Code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
/* Getch() from here - */
/* http://wesley.vidiqatch.org/ */
/* Thanks, Wesley! */
static struct termios old, new;
/* Initialize new terminal i/o settings */
void initTermios(int echo) {
tcgetattr(0, &old); /* grab old terminal i/o settings */
new = old; /* make new settings same as old settings */
new.c_lflag &= ~ICANON; /* disable buffered i/o */
new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
/* Restore old terminal i/o settings */
void resetTermios(void) {
tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
char getch_(int echo) {
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* Read 1 character without echo */
char getch(void) {
return getch_(0);
}
/* Read 1 character with echo */
char getche(void) {
return getch_(1);
}
/* A struct to hold key sequence data. */
struct keyseq {
int ctrl;
int shf;
int esc;
int lbrack;
int del;
int key;
} ;
/* Create a new struct and set it to NULL. */
struct keyseq *k = NULL;
/* Print the struct data. */
void print_seq(struct keyseq *k)
{
printf( "k->ctrl = %d\n", (k->ctrl) );
printf( "k->shf = %d\n", (k->shf) );
printf( "k->esc = %d\n", (k->esc) );
printf( "k->lbrack = %d\n", (k->lbrack) );
printf( "k->del = %d\n", (k->del) );
printf( "k->key = %d\n", (k->key) );
puts("--------------------\n");
}
/* Function to add data to struct. */
struct keyseq *add_data(struct keyseq *k, int data)
{
/* Clear existing flags */
k->ctrl = k->del = k->esc = k->key = k->lbrack = k->shf = 0;
/* Set flags. */
switch (data)
{
case 1 ... 26: k->ctrl = 1; break;
case 27: k->esc = 1; break;
case 65 ... 90: k->shf = 1; break;
case 91: k->lbrack = 1; break;
case 127: k->del = 1; break;
default: break;
}
/* We do not include esc and lbrack keys here. */
switch (data)
{
case 1 ... 26: k->key = data; break;
case 32 ... 90: k->key = data; break;
case 92 ... 127: k->key = data; break;
default: break;
}
print_seq(k);
return k;
}
int main()
{
/* Create a new struct and set it to NULL. */
struct keyseq *k = NULL;
k = malloc(sizeof(struct keyseq));
while(1)
{
int key = getch();
k = add_data(k, key);
}
free(k);
return 0;
}
Ok - now, I am testing this on the arrow keys and this is what I get as the output for the Up Arrow -
andy@obsidian ~/pd_c_stuff $ ./keyseq
k->ctrl = 0
k->shf = 0
k->esc = 1
k->lbrack = 0
k->del = 0
k->key = 0
--------------------
k->ctrl = 0
k->shf = 0
k->esc = 0
k->lbrack = 1
k->del = 0
k->key = 0
--------------------
k->ctrl = 0
k->shf = 1
k->esc = 0
k->lbrack = 0
k->del = 0
k->key = 65
--------------------
Esc-Lbrack-Shf-65 ( = ESC [ A ) .Fine.
What I *want* to do is to do that all in one hit, so that instead of having three "output blocks" as above, I would have one, showing the flags as follows -
k->ctrl = 0
k->shf = 1
k->esc = 1
k->lbrack = 1
k->del = 0
k->key = 65
--------------------
So - how can the code be changed to do that?
( I thought of maybe using a bitmask, but I have never used those and wouldn't know where to start. )
So - very many thanks in advance for your help! Bye for now -
- latte123