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

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