-\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
+
+
+/* pd_readline.c */
+/* Some code to allow the editing of a command-line. */
+/* You can also move around with the left and right */
+/* arrow keys, and recall previous commands with the */
+/* up-arrow key. */
+/* This code is released to the public domain. */
+/* "Share and enjoy...." ;) */
+
+
+
+#include <string.h>
+#include <stdio.h>
+#include <termios.h>
+
+/* 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 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. */
+}
+
+
+/* Helper function to chop newlines off the lines read in. */
+/* Without this being done, an extra newline is inserted */
+/* (which is usually not what is wanted). */
+char *chop(char *s)
+{
+ s[strcspn(s,"\n")] = '\0';
+ return s;
+}
+
+
+/* An array to store the command-history file in. */
+/* Only 20 lines are read. */
+char hist[20][80];
+
+
+/* Read the file into the array of strings. */
+void readfile(char *fname)
+{
+ int retval = fexists(fname);
+
+ int i;
+ if (retval == 0) {
+ /* File exists, so open it. */
+ /* We open it in read-write mode so we can */
+ /* append new commands to it. */
+ FILE *fptr;
+ fptr = fopen(fname, "rw");
+
+ for(i=0; i<20; i++)
+ {
+ chop(fgets(hist[i], 80, fptr) );
+ }
+
+ } /* retval == 0 */
+
+ else puts("Error! File does not exist. \n");
+
+}
+
+
+/* Helper function to print the command-history file. */
+void printfile(void)
+{
+ int j;
+
+ for(j=0; j<20; j++)
+ {
+ puts(hist[j]);
+ }
+}
+
+
+
+
+/* Helper function. Print a previous command-line WITHOUT */
+/* a newline. */
+void putline(char *str)
+{
+ char *line = chop(str);
+ printf("%s", line);
+}
+
+
+
+
+int main(void)
+{
+
+/* Our "command-history" file. */
+readfile("test.txt");
+
+/* Main buffer for the command-line. */
+char buffer[80];
+
+/* Main buffer "pointer" */
+int bufpnt = 0;
+
+/* "Pointer" for the history file. */
+int histpnt = 20;
+
+
+ while(1)
+ {
+
+ int key = getch();
+ buffer[bufpnt] = key;
+ bufpnt += 1;
+
+ /* Printable chars. */
+ if ( (key >= 32) && (key <= 126) )
+ {
+ /* We have a printable key so print it. */
+ putchar(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. */
+
+ /* Backspace */
+ else if(key == 127)
+ {
+ /* Move left 1 char and delete that char */
+ bufpnt -= 1;
+ printf("\033[1D");
+ printf("\040");
+ printf("\033[1D");
+ /* Move 1 char to left again */
+ bufpnt -= 1;
+ }
+
+ /* We have an escape key-sequence */
+ else if(key == 27)
+ {
+ key = getch();
+ if(key == 91)
+ key = getch();
+
+ if (key == 65) /* Up Arrow */
+ {
+ /* Move one command "back" in history. */
+ histpnt -= 1;
+ /* Clear to end of line. */
+ printf("\033[80D");
+ printf("\033[K");
+ /* Move buffer pointer to start of line */
+ bufpnt = 0;
+ /* Clear the array. */
+ memset(buffer, 0, sizeof(char)*80);
+ /* Print the pointed-at command-sequence. */
+ putline(hist[histpnt]);
+ }
+
+ if(key == 66) /* Down Arrow */
+ {
+ /* Move one command "forward" in history. */
+ histpnt += 1;
+ /* Clear to end of line. */
+ printf("\033[80D");
+ printf("\033[K");
+ /* Move buffer pointer to start of line */
+ bufpnt = 0;
+ /* Clear the array. */
+ memset(buffer, 0, sizeof(char)*80);
+ /* Print the pointed-at command-sequence. */
+ putline(hist[histpnt]);
+ }
+
+ if(key == 67) /* Left arrow */
+ {
+ /* Move one character to the left. */
+ printf("\033[1C");
+ }
+
+ if(key == 68) /* Right arrow */
+ {
+ /* Move one character to the right. */
+ printf("\033[1D");
+ }
+
+ } /* End of key=27 key sequence. */
+
+
+ /* The Enter key exits. Enter is 10 decimal */
+ else if(key == 10)
+ {
+ puts("\n");
+ puts("Exiting... \n");
+ break;
+ } /* Key = Enter */
+ }
+
+ return 0;
+
+}
+
+
+
+
+
+