From 15155262dff7689ef3601df89e70d42ec3c127ca Mon Sep 17 00:00:00 2001 From: andy Date: Sun, 26 Aug 2012 21:34:33 +1200 Subject: [PATCH] Very good progress. --- Notes_and_ideas.txt | 13 ++++ README | 22 +++--- keyhandler.c | 165 +++++++++++++++++++++++++++++++++++++++ pd_readline.c | 183 +++++++++++++++++++++++++++++++++++++++++++ pdmenu2.c | 170 ++++++++++++++++++++++++++++++++++++++++ pdmenu3.c | 186 ++++++++++++++++++++++++++++++++++++++++++++ pdmenu4.c | 185 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 913 insertions(+), 11 deletions(-) create mode 100644 Notes_and_ideas.txt create mode 100644 keyhandler.c create mode 100644 pd_readline.c create mode 100644 pdmenu2.c create mode 100644 pdmenu3.c create mode 100644 pdmenu4.c diff --git a/Notes_and_ideas.txt b/Notes_and_ideas.txt new file mode 100644 index 0000000..1a367a4 --- /dev/null +++ b/Notes_and_ideas.txt @@ -0,0 +1,13 @@ + + **** A Public Domain readline and command-history utility **** + + Random thoughts, comments ideas on doing a PD readline and +command-history utility. + +Keyboard operation - Keyboard determines characters sent to +computer. Chars are stored in keyboard buffer and then sent. +***NOTE*** - set up editable copy of kbd buffer? + +Keyboard scancodes - make and break codes. + + diff --git a/README b/README index b3a0eca..fa5a322 100644 --- a/README +++ b/README @@ -4,20 +4,20 @@ This repo is for the (eventual) storage of a public-domain readline-and-command-history implementation. -Update - 24th Aug 2012 - -Added the mg editor files from OpenBSD. -I obtained the code from here - -ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/usr.bin/mg/ +Update - 26th Aug 2012 - -( It's not so much the editor itself that is the main interest here, -but the line-management code. ) +Very useful progress. +Keystroke sequences are now stored in an array of structs. +This makes it VERY easy to see the various special flags +in a keystroke sequence +(e.g. Esc, Ctrl, Alt and so on..... ). -NOTE - in the mg directory, the file "theo.c" is NOT -"public domain" ( but it HAD to be included because of the -humour...... ;) ) +Still some way to go to get to a REAL readline, but we are +"on the way......" + +This code is released to the public domain. +"Share and enjoy........ ;) " -Many thanks to the OpenBSD team and the mg devs -(hi Theo - arrrrrrgh, please don't hit me........... ;) ) - mooseman diff --git a/keyhandler.c b/keyhandler.c new file mode 100644 index 0000000..af0eb76 --- /dev/null +++ b/keyhandler.c @@ -0,0 +1,165 @@ + + +/* keyhandler.c */ + +/* + A simple program to handle keys (in particular, function keys, + Ctrl keys, Alt keys and arrow keys). + This code is released to the public domain. + "Share and enjoy...." ;) +*/ + + +#include +#include +#include +#include +#include + + +void func1(void) +{ + printf("Hey, you entered foo! \n"); +} + +void func2(void) +{ + printf("Hey, you entered bar! \n"); +} + +void alt_a(void) +{ + printf("Hey, you pressed ALT a! \n"); +} + +void alt_b(void) +{ + printf("Hey, you pressed ALT b! \n"); +} + +void ctrl_a(void) +{ + printf("Hey, you pressed CTRL a! \n"); +} + +void ctrl_g(void) +{ + printf("Hey, you pressed CTRL g! \n"); +} + +void up_arrow(void) +{ + printf("Hey, you pressed the up arrow! \n"); +} + +void down_arrow(void) +{ + printf("Hey, you pressed the down arrow! \n"); +} + +void left_arrow(void) +{ + printf("Hey, you pressed the left arrow! \n"); +} + +void right_arrow(void) +{ + printf("Hey, you pressed the right arrow! \n"); +} + +void f2(void) +{ + printf("Hey, you pressed F2! \n"); +} + +void f3(void) +{ + printf("Hey, you pressed F3! \n"); +} + +void f4(void) +{ + printf("Hey, you pressed F4! \n"); +} + + + + +int main(void) +{ + + char word[80]; + char ch; + + do { + puts("Enter some text :"); + scanf("%s", word); + + if ( !strcmp(word, "foo") ) { + func1(); + } + + else if (!strcmp(word, "bar") ) { + func2(); + } + + else if (!strcmp(word, "\x1b\x61") ) { + alt_a(); + } + + else if (!strcmp(word, "\x1b\x62") ) { + alt_b(); + } + + else if (!strcmp(word, "\x07") ) { + ctrl_g(); + } + + else if (!strcmp(word, "\x01") ) { + ctrl_a(); + } + + else if (!strcmp(word, "\x1b\x5b\x41") ) { + up_arrow(); + } + + else if (!strcmp(word, "\x1b\x5b\x42") ) { + down_arrow(); + } + + else if (!strcmp(word, "\x1b\x5b\x43") ) { + right_arrow(); + } + + else if (!strcmp(word, "\x1b\x5b\x44") ) { + left_arrow(); + } + + else if (!strcmp(word, "\x1b\x4f\x51") ) { + f2(); + } + + else if (!strcmp(word, "\x1b\x4f\x52") ) { + f3(); + } + + else if (!strcmp(word, "\x1b\x4f\x53") ) { + f4(); + } + + else { + printf("Nope - I do not recognise that phrase.... \n"); + } + + printf("Try again? (y/n) : "); + scanf(" %c%*c", &ch); + } + + while( toupper(ch) != 'N' ); + + return 0; + +} + + + diff --git a/pd_readline.c b/pd_readline.c new file mode 100644 index 0000000..168a860 --- /dev/null +++ b/pd_readline.c @@ -0,0 +1,183 @@ + + +/* pd_readline.c */ +/* Status (as at 26th Aug 2012) : useful progress. */ +/* Keystroke sequences (along with the special flags */ +/* like Esc, Ctrl, Alt etc are now stored in a buffer */ +/* ( an array of structs ). */ +/* It will still be some time before this is a REAL */ +/* readline, but we are "on the way"...... */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ + + +#include +#include +#include /* For getch() */ + +/* This implementation of getch() is 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); +} + + + +/* Helper function, to let us see if a .history file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + + FILE *fptr ; + + fptr = fopen(fname, "r") ; + + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + + fclose(fptr); + return 0; /* File DOES exist in dir. */ + +} + + + /* Struct to store key sequences */ +typedef struct { + int fnkey; + int ctrl; + int alt ; + int shf ; + int esc ; + int lbr ; /* For left-bracket ([) of escape sequences */ + int key; + } keyseq ; + + + + + +int main(void) +{ + + printf("Public Domain Readline \n"); + printf("NOTE! - at the moment, we are using \n"); + printf("NON-echoing reads, storing the keystrokes \n"); + printf("in a buffer \n"); + + + /* Buffer - an array of keyseq structs. */ + /* Note - now that we store the keystrokes in here, */ + /* we can look at the various flags and decide whether to */ + /* "echo" the key (as normal) or suppress it (as with an */ + /* arrow key). */ + keyseq buffer[80] ; + + /* Buffer "pointer" */ + int bufpnt = 0; + + + /* Test for existence of history file. */ + int exists; + exists = fexists(".history"); + printf("Result: %d \n", exists); + + while(1) + { + + int key = getch(); + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + buffer[bufpnt].key = key; + bufpnt += 1; + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + /* Function keys. */ + /* F2 is 27, 79, 81. */ + /* F3 is 27, 79, 82. */ + /* F4 is 27, 79, 83. */ + + + else if(key == 27) + { + + buffer[bufpnt].esc = 1; + key = getch(); + if(key == 91) + buffer[bufpnt].lbr = 1; + key = getch(); + if( (key >= 65) && (key <= 68) ) + { + buffer[bufpnt].key = key; + } + bufpnt += 1; + } + + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { + int j ; + /* Print the array of structs. */ + for (j=0; j<10; j++) + { + printf("Fnkey: %d ", buffer[j].fnkey ) ; + printf("Ctrl: %d ", buffer[j].ctrl ) ; + printf("Alt: %d ", buffer[j].alt ) ; + printf("Shf: %d ", buffer[j].shf ) ; + printf("Esc: %d ", buffer[j].esc ) ; + printf("Lbr: %d ", buffer[j].lbr ) ; + printf("Key: %d \n", buffer[j].key ) ; + } + + break; + } /* Key = Enter */ + } + + return 0; +} + + + + diff --git a/pdmenu2.c b/pdmenu2.c new file mode 100644 index 0000000..746eb31 --- /dev/null +++ b/pdmenu2.c @@ -0,0 +1,170 @@ + + +/* pdmenu.c */ +/* This code is aimed at helping those who would like to */ +/* create menus without using the curses library. */ +/* It creates a count variable (which could be used to */ +/* keep track of which item is highlighted). Using the */ +/* up and down arrow keys increments and decrements the */ +/* count variable. Finally, when you press Enter, the */ +/* value of the count variable is printed and the program */ +/* exits. */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ + + +#include +#include +#include /* For getch() */ + +/* This implementation of getch() is 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); +} + + + +/* Helper function, to let us see if a .history file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + + FILE *fptr ; + + fptr = fopen(fname, "r") ; + + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + + fclose(fptr); + return 0; /* File DOES exist in dir. */ + +} + + + +int main(void) +{ + + printf("Public Domain Menu Program \n"); + printf("\nUse the up and down arrow keys then press Enter\n"); + + int menunum = 0; + + /* Buffer */ + char buffer[80] ; + + /* Buffer "pointer" */ + int bufpnt = 0; + + + /* Test for existence of history file. */ + int exists; + exists = fexists(".history"); + printf("Result: %d \n", exists); + + while(1) + { + + int key = getch(); + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + buffer[bufpnt] = key; + bufpnt += 1; + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + else if(key == 27) + { key = getch(); + if(key == 91) + key = getch(); + if(key == 65) + { puts("You pressed up arrow! \n"); + menunum-=1; + printf("Menunum is now %d \n", menunum); + } + else if(key == 66) + { puts("You pressed down arrow! \n"); + menunum+=1; + printf("Menunum is now %d \n", menunum); + } + else if(key == 67) + { puts("You pressed right arrow! \n"); + } + else if(key == 68) + { puts("You pressed left arrow! \n"); + } + } + + /* A few other keys (for testing purposes ) */ + + /* + else if(key == 97) + { puts("You pressed the \"a\" key! \n"); + } + else if(key == 98) + { puts("You pressed the \"b\" key! \n"); + } + else if(key == 99) + { puts("You pressed the \"c\" key! \n"); + } + else if(key == 100) + { puts("You pressed the \"d\" key! \n"); + } + */ + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { printf("You pressed ENTER! You chose item %d \n", menunum); + printf("Buffer is %s \n", buffer) ; + break; } + } + + return 0; +} + + + + diff --git a/pdmenu3.c b/pdmenu3.c new file mode 100644 index 0000000..6da1936 --- /dev/null +++ b/pdmenu3.c @@ -0,0 +1,186 @@ + + +/* pdmenu.c */ +/* This code is aimed at helping those who would like to */ +/* create menus without using the curses library. */ +/* It creates a count variable (which could be used to */ +/* keep track of which item is highlighted). Using the */ +/* up and down arrow keys increments and decrements the */ +/* count variable. Finally, when you press Enter, the */ +/* value of the count variable is printed and the program */ +/* exits. */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ + + +#include +#include +#include /* For getch() */ + +/* This implementation of getch() is 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); +} + + + +/* Helper function, to let us see if a .history file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + + FILE *fptr ; + + fptr = fopen(fname, "r") ; + + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + + fclose(fptr); + return 0; /* File DOES exist in dir. */ + +} + + + /* Struct to store key sequences */ +typedef struct { + int fnkey; + int ctrl; + int alt ; + int shf ; + int esc ; + int lbr ; /* For left-bracket ([) of escape sequences */ + int key; + } keyseq ; + + + + + +int main(void) +{ + + printf("Public Domain Menu Program \n"); + + + keyseq myseq; + + + /* Buffer */ + keyseq buffer[80] ; + + /* Buffer "pointer" */ + int bufpnt = 0; + + + /* Test for existence of history file. */ + int exists; + exists = fexists(".history"); + printf("Result: %d \n", exists); + + while(1) + { + + int key = getch(); + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + myseq.key = key; + buffer[bufpnt] = myseq; + bufpnt += 1; + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + /* Function keys. */ + /* F2 is 27, 79, 81. */ + /* F3 is 27, 79, 82. */ + /* F4 is 27, 79, 83. */ + + + else if(key == 27) + { + myseq.key = key; + buffer[bufpnt] = myseq; + bufpnt += 1; + key = getch(); + if(key == 91) + myseq.key = key; + buffer[bufpnt] = myseq; + bufpnt += 1; + key = getch(); + if( (key >= 65) && (key <= 68) ) + { + myseq.key = key; + buffer[bufpnt] = myseq; + bufpnt += 1; + } + } + + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { + int j ; + /* Print the array of structs. */ + for (j=0; j<10; j++) + { + printf("Fnkey: %d ", buffer[j].fnkey ) ; + printf("Ctrl: %d ", buffer[j].ctrl ) ; + printf("Alt: %d ", buffer[j].alt ) ; + printf("Shf: %d ", buffer[j].shf ) ; + printf("Esc: %d ", buffer[j].esc ) ; + printf("Lbr: %d ", buffer[j].lbr ) ; + printf("Key: %d \n", buffer[j].key ) ; + } + + break; + } /* Key = Enter */ + } + + return 0; +} + + + + diff --git a/pdmenu4.c b/pdmenu4.c new file mode 100644 index 0000000..c8bff2e --- /dev/null +++ b/pdmenu4.c @@ -0,0 +1,185 @@ + + +/* pd_readline.c */ +/* Status (as at 26th Aug 2012) : useful progress. */ +/* Keystroke sequences (along with the special flags */ +/* like Esc, Ctrl, Alt etc are now stored in a buffer */ +/* ( an array of structs ). */ +/* It will still be some time before this is a REAL */ +/* readline, but we are "on the way"...... */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ + + +#include +#include +#include /* For getch() */ + +/* This implementation of getch() is 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); +} + + + +/* Helper function, to let us see if a .history file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + + FILE *fptr ; + + fptr = fopen(fname, "r") ; + + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + + fclose(fptr); + return 0; /* File DOES exist in dir. */ + +} + + + /* Struct to store key sequences */ +typedef struct { + int fnkey; + int ctrl; + int alt ; + int shf ; + int esc ; + int lbr ; /* For left-bracket ([) of escape sequences */ + int key; + } keyseq ; + + + + + +int main(void) +{ + + printf("Public Domain Readline \n"); + printf("NOTE! - at the moment, we are using \n"); + printf("NON-echoing reads, storing the keystrokes \n"); + printf("in a buffer \n"); + + + /* Buffer - an array of keyseq structs. */ + /* Note - now that we store the keystrokes in here, */ + /* we can look at the various flags and decide whether to */ + /* "echo" the key (as normal) or suppress it (as with an */ + /* arrow key). */ + keyseq buffer[80] ; + + /* Buffer "pointer" */ + int bufpnt = 0; + + + /* Test for existence of history file. */ + int exists; + exists = fexists(".history"); + printf("Result: %d \n", exists); + + while(1) + { + + int key = getch(); + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + buffer[bufpnt].key = key; + bufpnt += 1; + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + /* Function keys. */ + /* F2 is 27, 79, 81. */ + /* F3 is 27, 79, 82. */ + /* F4 is 27, 79, 83. */ + + + else if(key == 27) + { + + buffer[bufpnt].esc = 1; + bufpnt += 1; + key = getch(); + if(key == 91) + buffer[bufpnt].lbr = 1; + bufpnt += 1; + key = getch(); + if( (key >= 65) && (key <= 68) ) + { + buffer[bufpnt].key = key; + bufpnt += 1; + } + } + + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { + int j ; + /* Print the array of structs. */ + for (j=0; j<20; j++) + { + printf("Fnkey: %d ", buffer[j].fnkey ) ; + printf("Ctrl: %d ", buffer[j].ctrl ) ; + printf("Alt: %d ", buffer[j].alt ) ; + printf("Shf: %d ", buffer[j].shf ) ; + printf("Esc: %d ", buffer[j].esc ) ; + printf("Lbr: %d ", buffer[j].lbr ) ; + printf("Key: %d \n", buffer[j].key ) ; + } + + break; + } /* Key = Enter */ + } + + return 0; +} + + + + -- 2.40.0