+\r
+\r
+/* pd_readline2.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
+\r
+/* The code can now distinguish between a printable key */ \r
+/* and a key that should not be printed. */ \r
+\r
+/* Backspace key, and left and right arrow keys now work. */ \r
+\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
+/* Helper function to print escape sequences to terminal */ \r
+void prtseq(char *what) \r
+{ \r
+ if (strcmp(what, "left") ) printf("\033[1D"); \r
+ else if (strcmp(what, "right") ) printf("\033[1C"); \r
+ else if (strcmp(what, "bs") ) \r
+ printf("\033[1D");\r
+ printf("\040"); \r
+ printf("\033[1D"); \r
+} \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
+ \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
+ /* We have a printable key so print it. */ \r
+ putchar(key); \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
+ /* Backspace */ \r
+ else if(key == 127) \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ /* Move 1 char to left */ \r
+ prtseq("bs"); \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ else if(key == 27) \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) /* Up arrow */ \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ } \r
+ if(key == 66) /* Down arrow */ \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ } \r
+ if(key == 67) /* Left arrow */ \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ prtseq("left"); \r
+ }\r
+ if(key == 68) /* Right arrow */ \r
+ { \r
+ buffer[bufpnt].key = key; \r
+ prtseq("right"); \r
+ }\r
+ \r
+ bufpnt += 1; \r
+ } \r
+ \r
+ \r
+ \r
+ /* The Enter key exits. Enter is 10 decimal */ \r
+ else if(key == 10) \r
+ { \r
+ puts("\n"); \r
+ int j ; \r
+ /* Print the array of structs. */ \r
+ for (j=0; j<bufpnt; 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