Fixed keyboard bug where keypresses were not being registered, working on libreadline
[tpg/acess2.git] / Usermode / Libraries / libreadline.so_src / main.c
1 /*
2  * Acess2 Library Suite
3  * - Readline
4  * 
5  * Text mode entry with history
6  */
7 #include <readline.h>
8 #include <acess/sys.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #define STDIN_FD        0
14 #define STDOUT_FD       1
15
16 // === PROTOTYPES ===
17  int    SoMain();
18 tReadline       *Readline_CreateInstance(int bUseHistory);
19 char    *Readline(tReadline *Info);
20
21 // === GLOBALS ===
22
23 // === CODE ===
24 int SoMain()
25 {
26         return 0;
27 }
28
29 char *Readline(tReadline *Info)
30 {
31         char    *ret;
32         char    *orig;
33          int    len, pos, space = 1023-8-8;     // optimised for the heap manager
34         char    ch;
35          int    scrollbackPos = Info->NumHistory;
36          
37         // Preset Variables
38         ret = malloc( space+1 );
39         if(!ret)        return NULL;
40         len = 0;        pos = 0;
41         
42         orig = ret;
43         
44         // Read In Command Line
45         do {
46                 read(STDIN_FD, 1, &ch); // Read Character from stdin (read is a blocking call)
47                 
48                 if(ch == '\n')  break;
49                 
50                 switch(ch)
51                 {
52                 // Control characters
53                 case '\x1B':
54                         read(STDIN_FD, 1, &ch); // Read control character
55                         switch(ch)
56                         {
57                         //case 'D':     if(pos) pos--;  break;
58                         //case 'C':     if(pos<len)     pos++;  break;
59                         case '[':
60                                 read(STDIN_FD, 1, &ch); // Read control character
61                                 switch(ch)
62                                 {
63                                 case 'A':       // Up
64                                         {
65                                                  int    oldLen = len;
66                                                 if( scrollbackPos <= 0 )        break;
67                                                 
68                                                 if(ret != orig) free(ret);
69                                                 ret = strdup( Info->History[--scrollbackPos] );
70                                                 
71                                                 space = len = strlen(ret);
72                                                 while(pos-->1)  write(STDOUT_FD, 3, "\x1B[D");
73                                                 write(STDOUT_FD, len, ret);     pos = len;
74                                                 while(pos++ < oldLen)   write(STDOUT_FD, 1, " ");
75                                         }
76                                         break;
77                                 case 'B':       // Down
78                                         {
79                                                  int    oldLen = len;
80                                                 if( scrollbackPos >= Info->NumHistory ) break;
81                                                 
82                                                 if(ret != orig) free(ret);
83                                                 ret = strdup( Info->History[scrollbackPos++] );
84                                                 
85                                                 space = len = strlen(ret);
86                                                 while(pos-->1)  write(STDOUT_FD, 3, "\x1B[D");
87                                                 write(STDOUT_FD, len, ret);     pos = len;
88                                                 while(pos++ < oldLen)   write(STDOUT_FD, 1, " ");
89                                         }
90                                         break;
91                                 case 'D':       // Left
92                                         if(pos == 0)    break;
93                                         pos --;
94                                         write(STDOUT_FD, 3, "\x1B[D");
95                                         break;
96                                 case 'C':       // Right
97                                         if(pos == len)  break;
98                                         pos++;
99                                         write(STDOUT_FD, 3, "\x1B[C");
100                                         break;
101                                 }
102                         }
103                         break;
104                 
105                 // Backspace
106                 case '\b':
107                         if(len <= 0)            break;  // Protect against underflows
108                         write(STDOUT_FD, 1, &ch);
109                         if(pos == len) {        // Simple case of end of string
110                                 len --;
111                                 pos--;
112                         }
113                         else {
114                                 char    buf[7] = "\x1B[000D";
115                                 buf[2] += ((len-pos+1)/100) % 10;
116                                 buf[3] += ((len-pos+1)/10) % 10;
117                                 buf[4] += (len-pos+1) % 10;
118                                 write(STDOUT_FD, len-pos, &ret[pos]);   // Move Text
119                                 ch = ' ';       write(STDOUT_FD, 1, &ch);       ch = '\b';      // Clear deleted character
120                                 write(STDOUT_FD, 7, buf);       // Update Cursor
121                                 // Alter Buffer
122                                 memmove(&ret[pos-1], &ret[pos], len-pos);
123                                 pos --;
124                                 len --;
125                         }
126                         break;
127                 
128                 // Tab
129                 case '\t':
130                         //TODO: Implement Tab-Completion
131                         //Currently just ignore tabs
132                         break;
133                 
134                 default:                
135                         // Expand Buffer
136                         if(len+1 > space) {
137                                 space += 256;
138                                 if(ret == orig) {
139                                         orig = ret = realloc(ret, space+1);
140                                 }
141                                 else {
142                                         ret = realloc(ret, space+1);
143                                 }
144                                 if(!ret)        return NULL;
145                         }
146                         
147                         // Editing inside the buffer
148                         if(pos != len) {
149                                 char    buf[7] = "\x1B[000D";
150                                 buf[2] += ((len-pos)/100) % 10;
151                                 buf[3] += ((len-pos)/10) % 10;
152                                 buf[4] += (len-pos) % 10;
153                                 write(STDOUT_FD, 1, &ch);       // Print new character
154                                 write(STDOUT_FD, len-pos, &ret[pos]);   // Move Text
155                                 write(STDOUT_FD, 7, buf);       // Update Cursor
156                                 memmove( &ret[pos+1], &ret[pos], len-pos );
157                         }
158                         else {
159                                 write(STDOUT_FD, 1, &ch);
160                         }
161                         ret[pos++] = ch;
162                         len ++;
163                         break;
164                 }
165         } while(ch != '\n');
166         
167         // Cap String
168         ret[len] = '\0';
169         printf("\n");
170         
171         // Return length
172         //if(Length)    *Length = len;
173         
174         // Add to history
175         if( Info->UseHistory )
176         {
177                 if( !Info->History || strcmp( Info->History[ Info->NumHistory-1 ], ret) != 0 )
178                 {
179                         void    *tmp;
180                         Info->NumHistory ++;
181                         tmp = realloc( Info->History, Info->NumHistory * sizeof(char*) );
182                         if(tmp != NULL)
183                         {
184                                 Info->History = tmp;
185                                 Info->History[ Info->NumHistory-1 ] = strdup(ret);
186                         }
187                 }
188         }
189         
190         if(ret != orig) free(orig);
191         
192         return ret;
193 }

UCC git Repository :: git.ucc.asn.au