]> pd.if.org Git - pd_readline/blob - pd_readline2.c
More progress.
[pd_readline] / pd_readline2.c
1 \r
2 \r
3 /*  pd_readline2.c                                          */  \r
4 /*  Status (as at 26th Aug 2012) : useful progress.         */ \r
5 /*  Keystroke sequences (along with the special flags       */ \r
6 /*  like Esc, Ctrl, Alt etc are now stored in a buffer      */ \r
7 /*  ( an array of structs ).                                */    \r
8 \r
9 /*  The code can now distinguish between a printable key    */ \r
10 /*  and a key that should not be printed.                   */ \r
11 \r
12 /*  Backspace key, and left and right arrow keys now work.  */   \r
13 \r
14 /*  It will still be some time before this is a REAL        */ \r
15 /*  readline, but we are "on the way"......                 */     \r
16 /*  This code is released to the public domain.             */ \r
17 /*  "Share and enjoy...."  ;)                               */  \r
18 \r
19 \r
20 #include <string.h>   \r
21 #include <stdio.h> \r
22 #include <termios.h>  /* For getch()  */  \r
23 \r
24 /* This implementation of getch() is from here - */ \r
25 /* http://wesley.vidiqatch.org/                  */ \r
26 /* Thanks, Wesley!                               */  \r
27 static struct termios old, new;\r
28 \r
29 /* Initialize new terminal i/o settings */\r
30 void initTermios(int echo) {\r
31     tcgetattr(0, &old); /* grab old terminal i/o settings */\r
32     new = old; /* make new settings same as old settings */\r
33     new.c_lflag &= ~ICANON; /* disable buffered i/o */\r
34     new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */\r
35     tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */\r
36 }\r
37 \r
38 \r
39 /* Restore old terminal i/o settings */\r
40 void resetTermios(void) {\r
41     tcsetattr(0, TCSANOW, &old);\r
42 }\r
43 \r
44 \r
45 /* Read 1 character - echo defines echo mode */\r
46 char getch_(int echo) {\r
47     char ch;\r
48     initTermios(echo);\r
49     ch = getchar();\r
50     resetTermios();\r
51     return ch;\r
52 }\r
53 \r
54 \r
55 /* Read 1 character without echo */\r
56 char getch(void) {\r
57     return getch_(0);\r
58 }\r
59 \r
60 \r
61 /* Read 1 character with echo */\r
62 char getche(void) {\r
63     return getch_(1);\r
64\r
65 \r
66 \r
67 \r
68 /*  Helper function, to let us see if a .history file */ \r
69 /*  exists in the current directory.  */ \r
70 int fexists(char *fname)\r
71 {  \r
72 \r
73    FILE *fptr ;         \r
74         \r
75    fptr = fopen(fname, "r") ;  \r
76    \r
77    if ( !fptr )  return -1 ;  /* File does not exist in dir. */         \r
78          \r
79    fclose(fptr);  \r
80    return 0;    /* File DOES exist in dir.  */          \r
81 \r
82\r
83 \r
84 \r
85  /* Struct to store key sequences */ \r
86 typedef struct { \r
87            int fnkey; \r
88            int ctrl; \r
89            int alt ; \r
90        int shf ; \r
91        int esc ; \r
92        int lbr ;  /* For left-bracket ([) of escape sequences */ \r
93        int key; \r
94    } keyseq ;         \r
95 \r
96 \r
97 \r
98 \r
99 \r
100 int main(void)\r
101 {\r
102         \r
103   printf("Public Domain Readline \n");              \r
104       \r
105   /* Buffer - an array of keyseq structs.                     */  \r
106   /* Note - now that we store the keystrokes in here,         */ \r
107   /* we can look at the various flags and decide whether to   */ \r
108   /* "echo" the key (as normal) or suppress it (as with an    */ \r
109   /* arrow key).                                              */    \r
110   keyseq buffer[80] ;   \r
111   \r
112   /* Buffer "pointer"  */ \r
113   int bufpnt = 0; \r
114   \r
115   \r
116   /* Test for existence of history file. */  \r
117   int exists;  \r
118   exists = fexists(".history"); \r
119   printf("Result: %d \n", exists);  \r
120   \r
121   while(1) \r
122     {  \r
123                    \r
124       int key = getch(); \r
125        \r
126       /* Printable chars. */  \r
127       if ( (key >= 32)  && (key <= 126) ) \r
128       { \r
129                 /* We have a printable key so print it. */   \r
130                 putchar(key);                   \r
131         buffer[bufpnt].key = key;  \r
132         bufpnt += 1; \r
133       }  \r
134                                                                        \r
135       /* Up arrow is 27, 91, 65.    ( ESC [ A )   */   \r
136       /* Down arrow is 27, 91, 66.  ( ESC [ B )   */ \r
137       /* Right arrow is 27, 91, 67. ( ESC [ C )   */ \r
138       /* Left arrow is 27, 91, 68.  ( ESC [ D )   */    \r
139       /* Function keys.     */ \r
140       /* F2 is 27, 79, 81.  */  \r
141       /* F3 is 27, 79, 82.  */  \r
142       /* F4 is 27, 79, 83.  */  \r
143       \r
144       /* Backspace */ \r
145       else if(key == 127) \r
146       { \r
147                  buffer[bufpnt].key = key;  \r
148                  /* Move 1 char to left */  \r
149                  printf("\033[1D");\r
150                  printf("\040"); \r
151                  printf("\033[1D");  \r
152                  bufpnt += 1;                   \r
153           }           \r
154                            \r
155       else if(key == 27)        \r
156           {                       \r
157                           buffer[bufpnt].esc = 1;                        \r
158                           key = getch(); \r
159               if(key == 91)               \r
160               buffer[bufpnt].lbr = 1;                \r
161               key = getch(); \r
162               if(key == 65) /* Up arrow */ \r
163                {                                 \r
164                                  buffer[bufpnt].key = key;                                            \r
165                }        \r
166                if(key == 66) /* Down arrow */ \r
167                {                                 \r
168                                  buffer[bufpnt].key = key;                                            \r
169                }         \r
170                if(key == 67) /* Left arrow */ \r
171                {                                 \r
172                                  buffer[bufpnt].key = key; \r
173                                  printf("\033[1C");   \r
174                }\r
175                 if(key == 68) /* Right arrow */ \r
176                {                                 \r
177                                  buffer[bufpnt].key = key; \r
178                                  printf("\033[1D");                                                                                                                                               \r
179                }\r
180                                                   \r
181             bufpnt += 1;            \r
182           } \r
183               \r
184                                           \r
185                                                  \r
186     /* The Enter key exits. Enter is 10 decimal */        \r
187         else if(key == 10)  \r
188                 { \r
189                          puts("\n");  \r
190                          int j ; \r
191                    /* Print the array of structs. */ \r
192                      for (j=0; j<bufpnt; j++)   \r
193                      { \r
194                             printf("Fnkey: %d ", buffer[j].fnkey  ) ; \r
195                             printf("Ctrl:  %d ", buffer[j].ctrl   ) ;   \r
196                             printf("Alt:   %d ", buffer[j].alt    ) ; \r
197                             printf("Shf:   %d ", buffer[j].shf    ) ; \r
198                             printf("Esc:   %d ", buffer[j].esc    ) ; \r
199                             printf("Lbr:   %d ", buffer[j].lbr    ) ;  \r
200                     printf("Key:   %d \n", buffer[j].key  ) ; \r
201                  }                      \r
202                                           \r
203              break;           \r
204          }  /* Key = Enter */   \r
205     }                \r
206                                       \r
207         return 0;\r
208 }  \r
209 \r
210 \r
211 \r
212 \r