--- /dev/null
+
+ **** 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.
+
+
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
--- /dev/null
+
+
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <ctype.h>
+
+
+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;
+
+}
+
+
+
--- /dev/null
+\r
+\r
+/* pd_readline.c */ \r
+/* Status (as at 26th Aug 2012) : useful progress. */ \r
+/* Keystroke sequences (along with the special flags */ \r
+/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
+/* ( an array of structs ). */ \r
+/* It will still be some time before this is a REAL */ \r
+/* readline, but we are "on the way"...... */ \r
+/* This code is released to the public domain. */ \r
+/* "Share and enjoy...." ;) */ \r
+\r
+\r
+#include <string.h> \r
+#include <stdio.h> \r
+#include <termios.h> /* For getch() */ \r
+\r
+/* This implementation of getch() is from here - */ \r
+/* http://wesley.vidiqatch.org/ */ \r
+/* Thanks, Wesley! */ \r
+static struct termios old, new;\r
+\r
+/* Initialize new terminal i/o settings */\r
+void initTermios(int echo) {\r
+ tcgetattr(0, &old); /* grab old terminal i/o settings */\r
+ new = old; /* make new settings same as old settings */\r
+ new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
+ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
+ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
+}\r
+\r
+\r
+/* Restore old terminal i/o settings */\r
+void resetTermios(void) {\r
+ tcsetattr(0, TCSANOW, &old);\r
+}\r
+\r
+\r
+/* Read 1 character - echo defines echo mode */\r
+char getch_(int echo) {\r
+ char ch;\r
+ initTermios(echo);\r
+ ch = getchar();\r
+ resetTermios();\r
+ return ch;\r
+}\r
+\r
+\r
+/* Read 1 character without echo */\r
+char getch(void) {\r
+ return getch_(0);\r
+}\r
+\r
+\r
+/* Read 1 character with echo */\r
+char getche(void) {\r
+ return getch_(1);\r
+} \r
+\r
+\r
+\r
+/* Helper function, to let us see if a .history file */ \r
+/* exists in the current directory. */ \r
+int fexists(char *fname)\r
+{ \r
+\r
+ FILE *fptr ; \r
+ \r
+ fptr = fopen(fname, "r") ; \r
+ \r
+ if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
+ \r
+ fclose(fptr); \r
+ return 0; /* File DOES exist in dir. */ \r
+\r
+} \r
+\r
+\r
+ /* Struct to store key sequences */ \r
+typedef struct { \r
+ int fnkey; \r
+ int ctrl; \r
+ int alt ; \r
+ int shf ; \r
+ int esc ; \r
+ int lbr ; /* For left-bracket ([) of escape sequences */ \r
+ int key; \r
+ } keyseq ; \r
+\r
+\r
+\r
+\r
+\r
+int main(void)\r
+{\r
+ \r
+ printf("Public Domain Readline \n"); \r
+ printf("NOTE! - at the moment, we are using \n"); \r
+ printf("NON-echoing reads, storing the keystrokes \n"); \r
+ printf("in a buffer \n"); \r
+ \r
+ \r
+ /* Buffer - an array of keyseq structs. */ \r
+ /* Note - now that we store the keystrokes in here, */ \r
+ /* we can look at the various flags and decide whether to */ \r
+ /* "echo" the key (as normal) or suppress it (as with an */ \r
+ /* arrow key). */ \r
+ keyseq buffer[80] ; \r
+ \r
+ /* Buffer "pointer" */ \r
+ int bufpnt = 0; \r
+ \r
+ \r
+ /* Test for existence of history file. */ \r
+ int exists; \r
+ exists = fexists(".history"); \r
+ printf("Result: %d \n", exists); \r
+ \r
+ while(1) \r
+ { \r
+ \r
+ int key = getch(); \r
+ \r
+ /* Printable chars. */ \r
+ if ( (key >= 32) && (key <= 126) ) \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
+ /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
+ /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
+ /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
+ /* Function keys. */ \r
+ /* F2 is 27, 79, 81. */ \r
+ /* F3 is 27, 79, 82. */ \r
+ /* F4 is 27, 79, 83. */ \r
+ \r
+ \r
+ else if(key == 27) \r
+ { \r
+ \r
+ buffer[bufpnt].esc = 1; \r
+ key = getch(); \r
+ if(key == 91) \r
+ buffer[bufpnt].lbr = 1; \r
+ key = getch(); \r
+ if( (key >= 65) && (key <= 68) ) \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ } \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ \r
+ \r
+ /* The Enter key exits. Enter is 10 decimal */ \r
+ else if(key == 10) \r
+ { \r
+ int j ; \r
+ /* Print the array of structs. */ \r
+ for (j=0; j<10; j++) \r
+ { \r
+ printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
+ printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
+ printf("Alt: %d ", buffer[j].alt ) ; \r
+ printf("Shf: %d ", buffer[j].shf ) ; \r
+ printf("Esc: %d ", buffer[j].esc ) ; \r
+ printf("Lbr: %d ", buffer[j].lbr ) ; \r
+ printf("Key: %d \n", buffer[j].key ) ; \r
+ } \r
+ \r
+ break; \r
+ } /* Key = Enter */ \r
+ } \r
+ \r
+ return 0;\r
+} \r
+\r
+\r
+\r
+\r
--- /dev/null
+\r
+\r
+/* pdmenu.c */ \r
+/* This code is aimed at helping those who would like to */ \r
+/* create menus without using the curses library. */ \r
+/* It creates a count variable (which could be used to */ \r
+/* keep track of which item is highlighted). Using the */ \r
+/* up and down arrow keys increments and decrements the */ \r
+/* count variable. Finally, when you press Enter, the */ \r
+/* value of the count variable is printed and the program */ \r
+/* exits. */ \r
+/* This code is released to the public domain. */ \r
+/* "Share and enjoy...." ;) */ \r
+\r
+\r
+#include <string.h> \r
+#include <stdio.h> \r
+#include <termios.h> /* For getch() */ \r
+\r
+/* This implementation of getch() is from here - */ \r
+/* http://wesley.vidiqatch.org/ */ \r
+/* Thanks, Wesley! */ \r
+static struct termios old, new;\r
+\r
+/* Initialize new terminal i/o settings */\r
+void initTermios(int echo) {\r
+ tcgetattr(0, &old); /* grab old terminal i/o settings */\r
+ new = old; /* make new settings same as old settings */\r
+ new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
+ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
+ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
+}\r
+\r
+\r
+/* Restore old terminal i/o settings */\r
+void resetTermios(void) {\r
+ tcsetattr(0, TCSANOW, &old);\r
+}\r
+\r
+\r
+/* Read 1 character - echo defines echo mode */\r
+char getch_(int echo) {\r
+ char ch;\r
+ initTermios(echo);\r
+ ch = getchar();\r
+ resetTermios();\r
+ return ch;\r
+}\r
+\r
+\r
+/* Read 1 character without echo */\r
+char getch(void) {\r
+ return getch_(0);\r
+}\r
+\r
+\r
+/* Read 1 character with echo */\r
+char getche(void) {\r
+ return getch_(1);\r
+} \r
+\r
+\r
+\r
+/* Helper function, to let us see if a .history file */ \r
+/* exists in the current directory. */ \r
+int fexists(char *fname)\r
+{ \r
+\r
+ FILE *fptr ; \r
+ \r
+ fptr = fopen(fname, "r") ; \r
+ \r
+ if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
+ \r
+ fclose(fptr); \r
+ return 0; /* File DOES exist in dir. */ \r
+\r
+} \r
+\r
+\r
+\r
+int main(void)\r
+{\r
+ \r
+ printf("Public Domain Menu Program \n"); \r
+ printf("\nUse the up and down arrow keys then press Enter\n"); \r
+ \r
+ int menunum = 0; \r
+ \r
+ /* Buffer */ \r
+ char buffer[80] ; \r
+ \r
+ /* Buffer "pointer" */ \r
+ int bufpnt = 0; \r
+ \r
+ \r
+ /* Test for existence of history file. */ \r
+ int exists; \r
+ exists = fexists(".history"); \r
+ printf("Result: %d \n", exists); \r
+ \r
+ while(1) \r
+ { \r
+ \r
+ int key = getch(); \r
+ \r
+ /* Printable chars. */ \r
+ if ( (key >= 32) && (key <= 126) ) \r
+ { \r
+ buffer[bufpnt] = key; \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
+ /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
+ /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
+ /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
+ else if(key == 27) \r
+ { key = getch(); \r
+ if(key == 91) \r
+ key = getch(); \r
+ if(key == 65) \r
+ { puts("You pressed up arrow! \n"); \r
+ menunum-=1; \r
+ printf("Menunum is now %d \n", menunum); \r
+ } \r
+ else if(key == 66) \r
+ { puts("You pressed down arrow! \n"); \r
+ menunum+=1; \r
+ printf("Menunum is now %d \n", menunum); \r
+ } \r
+ else if(key == 67) \r
+ { puts("You pressed right arrow! \n"); \r
+ } \r
+ else if(key == 68) \r
+ { puts("You pressed left arrow! \n"); \r
+ } \r
+ }\r
+ \r
+ /* A few other keys (for testing purposes ) */ \r
+ \r
+ /* \r
+ else if(key == 97) \r
+ { puts("You pressed the \"a\" key! \n"); \r
+ } \r
+ else if(key == 98) \r
+ { puts("You pressed the \"b\" key! \n"); \r
+ } \r
+ else if(key == 99) \r
+ { puts("You pressed the \"c\" key! \n"); \r
+ }\r
+ else if(key == 100) \r
+ { puts("You pressed the \"d\" key! \n"); \r
+ } \r
+ */ \r
+ \r
+ \r
+ /* The Enter key exits. Enter is 10 decimal */ \r
+ else if(key == 10) \r
+ { printf("You pressed ENTER! You chose item %d \n", menunum); \r
+ printf("Buffer is %s \n", buffer) ; \r
+ break; } \r
+ } \r
+ \r
+ return 0;\r
+} \r
+\r
+\r
+\r
+\r
--- /dev/null
+\r
+\r
+/* pdmenu.c */ \r
+/* This code is aimed at helping those who would like to */ \r
+/* create menus without using the curses library. */ \r
+/* It creates a count variable (which could be used to */ \r
+/* keep track of which item is highlighted). Using the */ \r
+/* up and down arrow keys increments and decrements the */ \r
+/* count variable. Finally, when you press Enter, the */ \r
+/* value of the count variable is printed and the program */ \r
+/* exits. */ \r
+/* This code is released to the public domain. */ \r
+/* "Share and enjoy...." ;) */ \r
+\r
+\r
+#include <string.h> \r
+#include <stdio.h> \r
+#include <termios.h> /* For getch() */ \r
+\r
+/* This implementation of getch() is from here - */ \r
+/* http://wesley.vidiqatch.org/ */ \r
+/* Thanks, Wesley! */ \r
+static struct termios old, new;\r
+\r
+/* Initialize new terminal i/o settings */\r
+void initTermios(int echo) {\r
+ tcgetattr(0, &old); /* grab old terminal i/o settings */\r
+ new = old; /* make new settings same as old settings */\r
+ new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
+ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
+ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
+}\r
+\r
+\r
+/* Restore old terminal i/o settings */\r
+void resetTermios(void) {\r
+ tcsetattr(0, TCSANOW, &old);\r
+}\r
+\r
+\r
+/* Read 1 character - echo defines echo mode */\r
+char getch_(int echo) {\r
+ char ch;\r
+ initTermios(echo);\r
+ ch = getchar();\r
+ resetTermios();\r
+ return ch;\r
+}\r
+\r
+\r
+/* Read 1 character without echo */\r
+char getch(void) {\r
+ return getch_(0);\r
+}\r
+\r
+\r
+/* Read 1 character with echo */\r
+char getche(void) {\r
+ return getch_(1);\r
+} \r
+\r
+\r
+\r
+/* Helper function, to let us see if a .history file */ \r
+/* exists in the current directory. */ \r
+int fexists(char *fname)\r
+{ \r
+\r
+ FILE *fptr ; \r
+ \r
+ fptr = fopen(fname, "r") ; \r
+ \r
+ if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
+ \r
+ fclose(fptr); \r
+ return 0; /* File DOES exist in dir. */ \r
+\r
+} \r
+\r
+\r
+ /* Struct to store key sequences */ \r
+typedef struct { \r
+ int fnkey; \r
+ int ctrl; \r
+ int alt ; \r
+ int shf ; \r
+ int esc ; \r
+ int lbr ; /* For left-bracket ([) of escape sequences */ \r
+ int key; \r
+ } keyseq ; \r
+\r
+\r
+\r
+\r
+\r
+int main(void)\r
+{\r
+ \r
+ printf("Public Domain Menu Program \n"); \r
+ \r
+ \r
+ keyseq myseq; \r
+ \r
+ \r
+ /* Buffer */ \r
+ keyseq buffer[80] ; \r
+ \r
+ /* Buffer "pointer" */ \r
+ int bufpnt = 0; \r
+ \r
+ \r
+ /* Test for existence of history file. */ \r
+ int exists; \r
+ exists = fexists(".history"); \r
+ printf("Result: %d \n", exists); \r
+ \r
+ while(1) \r
+ { \r
+ \r
+ int key = getch(); \r
+ \r
+ /* Printable chars. */ \r
+ if ( (key >= 32) && (key <= 126) ) \r
+ { \r
+ myseq.key = key; \r
+ buffer[bufpnt] = myseq; \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
+ /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
+ /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
+ /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
+ /* Function keys. */ \r
+ /* F2 is 27, 79, 81. */ \r
+ /* F3 is 27, 79, 82. */ \r
+ /* F4 is 27, 79, 83. */ \r
+ \r
+ \r
+ else if(key == 27) \r
+ { \r
+ myseq.key = key; \r
+ buffer[bufpnt] = myseq; \r
+ bufpnt += 1; \r
+ key = getch(); \r
+ if(key == 91) \r
+ myseq.key = key; \r
+ buffer[bufpnt] = myseq; \r
+ bufpnt += 1; \r
+ key = getch(); \r
+ if( (key >= 65) && (key <= 68) ) \r
+ { \r
+ myseq.key = key; \r
+ buffer[bufpnt] = myseq; \r
+ bufpnt += 1; \r
+ } \r
+ }\r
+ \r
+ \r
+ \r
+ /* The Enter key exits. Enter is 10 decimal */ \r
+ else if(key == 10) \r
+ { \r
+ int j ; \r
+ /* Print the array of structs. */ \r
+ for (j=0; j<10; j++) \r
+ { \r
+ printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
+ printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
+ printf("Alt: %d ", buffer[j].alt ) ; \r
+ printf("Shf: %d ", buffer[j].shf ) ; \r
+ printf("Esc: %d ", buffer[j].esc ) ; \r
+ printf("Lbr: %d ", buffer[j].lbr ) ; \r
+ printf("Key: %d \n", buffer[j].key ) ; \r
+ } \r
+ \r
+ break; \r
+ } /* Key = Enter */ \r
+ } \r
+ \r
+ return 0;\r
+} \r
+\r
+\r
+\r
+\r
--- /dev/null
+\r
+\r
+/* pd_readline.c */ \r
+/* Status (as at 26th Aug 2012) : useful progress. */ \r
+/* Keystroke sequences (along with the special flags */ \r
+/* like Esc, Ctrl, Alt etc are now stored in a buffer */ \r
+/* ( an array of structs ). */ \r
+/* It will still be some time before this is a REAL */ \r
+/* readline, but we are "on the way"...... */ \r
+/* This code is released to the public domain. */ \r
+/* "Share and enjoy...." ;) */ \r
+\r
+\r
+#include <string.h> \r
+#include <stdio.h> \r
+#include <termios.h> /* For getch() */ \r
+\r
+/* This implementation of getch() is from here - */ \r
+/* http://wesley.vidiqatch.org/ */ \r
+/* Thanks, Wesley! */ \r
+static struct termios old, new;\r
+\r
+/* Initialize new terminal i/o settings */\r
+void initTermios(int echo) {\r
+ tcgetattr(0, &old); /* grab old terminal i/o settings */\r
+ new = old; /* make new settings same as old settings */\r
+ new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
+ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
+ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
+}\r
+\r
+\r
+/* Restore old terminal i/o settings */\r
+void resetTermios(void) {\r
+ tcsetattr(0, TCSANOW, &old);\r
+}\r
+\r
+\r
+/* Read 1 character - echo defines echo mode */\r
+char getch_(int echo) {\r
+ char ch;\r
+ initTermios(echo);\r
+ ch = getchar();\r
+ resetTermios();\r
+ return ch;\r
+}\r
+\r
+\r
+/* Read 1 character without echo */\r
+char getch(void) {\r
+ return getch_(0);\r
+}\r
+\r
+\r
+/* Read 1 character with echo */\r
+char getche(void) {\r
+ return getch_(1);\r
+} \r
+\r
+\r
+\r
+/* Helper function, to let us see if a .history file */ \r
+/* exists in the current directory. */ \r
+int fexists(char *fname)\r
+{ \r
+\r
+ FILE *fptr ; \r
+ \r
+ fptr = fopen(fname, "r") ; \r
+ \r
+ if ( !fptr ) return -1 ; /* File does not exist in dir. */ \r
+ \r
+ fclose(fptr); \r
+ return 0; /* File DOES exist in dir. */ \r
+\r
+} \r
+\r
+\r
+ /* Struct to store key sequences */ \r
+typedef struct { \r
+ int fnkey; \r
+ int ctrl; \r
+ int alt ; \r
+ int shf ; \r
+ int esc ; \r
+ int lbr ; /* For left-bracket ([) of escape sequences */ \r
+ int key; \r
+ } keyseq ; \r
+\r
+\r
+\r
+\r
+\r
+int main(void)\r
+{\r
+ \r
+ printf("Public Domain Readline \n"); \r
+ printf("NOTE! - at the moment, we are using \n"); \r
+ printf("NON-echoing reads, storing the keystrokes \n"); \r
+ printf("in a buffer \n"); \r
+ \r
+ \r
+ /* Buffer - an array of keyseq structs. */ \r
+ /* Note - now that we store the keystrokes in here, */ \r
+ /* we can look at the various flags and decide whether to */ \r
+ /* "echo" the key (as normal) or suppress it (as with an */ \r
+ /* arrow key). */ \r
+ keyseq buffer[80] ; \r
+ \r
+ /* Buffer "pointer" */ \r
+ int bufpnt = 0; \r
+ \r
+ \r
+ /* Test for existence of history file. */ \r
+ int exists; \r
+ exists = fexists(".history"); \r
+ printf("Result: %d \n", exists); \r
+ \r
+ while(1) \r
+ { \r
+ \r
+ int key = getch(); \r
+ \r
+ /* Printable chars. */ \r
+ if ( (key >= 32) && (key <= 126) ) \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ /* Up arrow is 27, 91, 65. ( ESC [ A ) */ \r
+ /* Down arrow is 27, 91, 66. ( ESC [ B ) */ \r
+ /* Right arrow is 27, 91, 67. ( ESC [ C ) */ \r
+ /* Left arrow is 27, 91, 68. ( ESC [ D ) */ \r
+ /* Function keys. */ \r
+ /* F2 is 27, 79, 81. */ \r
+ /* F3 is 27, 79, 82. */ \r
+ /* F4 is 27, 79, 83. */ \r
+ \r
+ \r
+ else if(key == 27) \r
+ { \r
+ \r
+ buffer[bufpnt].esc = 1; \r
+ bufpnt += 1; \r
+ key = getch(); \r
+ if(key == 91) \r
+ buffer[bufpnt].lbr = 1; \r
+ bufpnt += 1; \r
+ key = getch(); \r
+ if( (key >= 65) && (key <= 68) ) \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ bufpnt += 1; \r
+ } \r
+ }\r
+ \r
+ \r
+ \r
+ /* The Enter key exits. Enter is 10 decimal */ \r
+ else if(key == 10) \r
+ { \r
+ int j ; \r
+ /* Print the array of structs. */ \r
+ for (j=0; j<20; j++) \r
+ { \r
+ printf("Fnkey: %d ", buffer[j].fnkey ) ; \r
+ printf("Ctrl: %d ", buffer[j].ctrl ) ; \r
+ printf("Alt: %d ", buffer[j].alt ) ; \r
+ printf("Shf: %d ", buffer[j].shf ) ; \r
+ printf("Esc: %d ", buffer[j].esc ) ; \r
+ printf("Lbr: %d ", buffer[j].lbr ) ; \r
+ printf("Key: %d \n", buffer[j].key ) ; \r
+ } \r
+ \r
+ break; \r
+ } /* Key = Enter */ \r
+ } \r
+ \r
+ return 0;\r
+} \r
+\r
+\r
+\r
+\r