Merge pull request #3 from dopefishh/standard-maybe
[CleanReadLine.git] / Clean System Files / readLine.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <readline/readline.h>
5 #include <readline/history.h>
6
7 #include "Clean.h"
8
9 static char *cs_answer = (char *)NULL;
10 static char **cs_tokens = (char **)NULL;
11 static int num_tokens = 0;
12 HISTORY_STATE *history_state = NULL;
13
14 //Helper functions
15 char *cleanStringToCString(CleanString s)
16 {
17 unsigned long len = CleanStringLength(s);
18 char *cs = (char *)malloc(len+1);
19 if(cs == NULL){
20 printf("malloc failed...\n");
21 exit(1);
22 }
23 memcpy(cs, CleanStringCharacters(s), len);
24 cs[len] = '\0';
25 return cs;
26 }
27
28 void cleanSetReadLineName(CleanString name)
29 {
30 rl_readline_name = cleanStringToCString(name);
31 }
32
33 //Readline functions
34 void cleanReadLine(
35 CleanString prompt, int history, CleanString *result, int *eof)
36 {
37 char *cs_prompt = cleanStringToCString(prompt);
38
39 //Get the answer and add to history if not empty
40 if(cs_answer){
41 free(cs_answer);
42 cs_answer = (char *)NULL;
43 }
44 cs_answer = readline(cs_prompt);
45 free(cs_prompt);
46 if(cs_answer && *cs_answer && history){
47 add_history(cs_answer);
48 }
49
50 *eof = 0;
51 if(!cs_answer){ //In case of an EOF
52 cs_answer = (char *)malloc(1);
53 cs_answer[0] = '\0';
54 *eof = 1;
55 }
56 CleanStringVariable(answer, strlen(cs_answer));
57 *result = (CleanString) answer;
58 memcpy(CleanStringCharacters(answer), cs_answer, strlen(cs_answer));
59 CleanStringLength(answer) = strlen(cs_answer);
60 }
61
62 //History Functions
63 //Initializing History and State Management
64 void cleanUsingHistory()
65 {
66 using_history();
67 }
68
69 void cleanGetState(int *offset, int *num, int *flags)
70 {
71 *offset = history_get_history_state()->offset;
72 *num = history_get_history_state()->length;
73 *flags = history_get_history_state()->flags;
74 }
75
76 void cleanGetHistoryItem(int num, CleanString *line, CleanString *timestamp)
77 {
78 char *cs_line = history_get_history_state()->entries[num]->line;
79 char *cs_stamp = history_get_history_state()->entries[num]->timestamp;
80
81 CleanStringVariable(cleanLine, strlen(cs_line));
82 *line = (CleanString) cleanLine;
83 memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line));
84 CleanStringLength(cleanLine) = strlen(cs_line);
85
86 CleanStringVariable(cleanTimestamp, strlen(cs_stamp));
87 *timestamp = (CleanString) cleanTimestamp;
88 memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp));
89 CleanStringLength(cleanTimestamp) = strlen(cs_stamp);
90 }
91
92 void cleanInitNewHistoryState(int offset, int flags, int num)
93 {
94 if(history_state != NULL){
95 //we should test if we can recursively free the object
96 free(history_state);
97 }
98 history_state = (HISTORY_STATE *)malloc(sizeof(HISTORY_STATE));
99 if(history_state == NULL){
100 printf("Not enough memory...\n");
101 exit(1);
102 }
103 HIST_ENTRY **entries = (HIST_ENTRY **)malloc(sizeof(HIST_ENTRY*)*num);
104 if(entries == NULL){
105 printf("Not enough memory...\n");
106 exit(1);
107 }
108 for(int i = 0; i<num; i++){
109 entries[i] = (HIST_ENTRY *)malloc(sizeof(HIST_ENTRY));
110 }
111 history_state->offset = offset;
112 history_state->entries = entries;
113 history_state->length = num;
114 history_state->size = num;
115 history_state->flags = 0;
116 }
117
118 void cleanSetNewHistoryEntry(int i, CleanString line, CleanString timestamp)
119 {
120 char *cs_line = cleanStringToCString(line);
121 char *cs_timestamp = cleanStringToCString(timestamp);
122 history_state->entries[i]->line = cs_line;
123 history_state->entries[i]->timestamp = cs_timestamp;
124 }
125
126 void cleanCommitSetHistory(void)
127 {
128 history_set_history_state(history_state);
129 }
130
131 //History List Management
132 void cleanAddHistoryTime(CleanString timestamp)
133 {
134 char *cs_timestamp = cleanStringToCString(timestamp);
135 add_history_time(cs_timestamp);
136 free(cs_timestamp);
137 }
138
139 void cleanAddHistory(CleanString entry)
140 {
141 char *cs_entry = cleanStringToCString(entry);
142 add_history(cs_entry);
143 free(cs_entry);
144 }
145
146 void cleanRemoveHistory(int which, CleanString *line, CleanString *timestamp)
147 {
148 HIST_ENTRY *entry = remove_history(which);
149 char *cs_line = entry->line;
150 char *cs_stamp = entry->timestamp;
151
152 CleanStringVariable(cleanLine, strlen(cs_line));
153 *line = (CleanString) cleanLine;
154 memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line));
155 CleanStringLength(cleanLine) = strlen(cs_line);
156
157 CleanStringVariable(cleanTimestamp, strlen(cs_stamp));
158 *timestamp = (CleanString) cleanTimestamp;
159 memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp));
160 CleanStringLength(cleanTimestamp) = strlen(cs_stamp);
161
162 histdata_t tofree = free_history_entry(entry);
163 free(tofree);
164 }
165
166 void cleanReplaceHistoryEntry(
167 int which, CleanString l, CleanString *line, CleanString *timestamp)
168 {
169 char *cs_l = cleanStringToCString(l);
170 HIST_ENTRY *entry = replace_history_entry(which, cs_l, NULL);
171 free(cs_l);
172 if(entry == NULL){
173 printf("invalid which\n");
174 }
175
176 char *cs_line = entry->line;
177 char *cs_stamp = entry->timestamp;
178
179 CleanStringVariable(cleanLine, strlen(cs_line));
180 *line = (CleanString) cleanLine;
181 memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line));
182 CleanStringLength(cleanLine) = strlen(cs_line);
183
184 CleanStringVariable(cleanTimestamp, strlen(cs_stamp));
185 *timestamp = (CleanString) cleanTimestamp;
186 memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp));
187 CleanStringLength(cleanTimestamp) = strlen(cs_stamp);
188
189 histdata_t tofree = free_history_entry(entry);
190 free(tofree);
191 }
192
193
194 void cleanClearHistory()
195 {
196 clear_history();
197 }
198
199 void cleanStifleHistory(int max)
200 {
201 stifle_history(max);
202 }
203
204 int cleanUnstifleHistory()
205 {
206 return unstifle_history();
207 }
208
209 int cleanHistoryIsStifled()
210 {
211 return history_is_stifled();
212 }
213
214 //Information About the History List
215 int cleanHistoryTotalBytes()
216 {
217 return history_total_bytes();
218 }
219
220 //Moving Around the History List
221 int cleanHistorySetPos(int pos)
222 {
223 return history_set_pos(pos);
224 }
225
226 void cleanPreviousHistory(
227 CleanString *line, CleanString *timestamp, int *null)
228 {
229 *null = 0;
230 HIST_ENTRY *entry = previous_history();
231 char *cs_line = "";
232 char *cs_stamp = "";
233 if(entry == NULL){
234 *null = 1;
235 } else {
236 *null = 0;
237 cs_line = entry->line;
238 cs_stamp = entry->timestamp;
239 }
240
241 CleanStringVariable(cleanLine, strlen(cs_line));
242 *line = (CleanString) cleanLine;
243 memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line));
244 CleanStringLength(cleanLine) = strlen(cs_line);
245
246 CleanStringVariable(cleanTimestamp, strlen(cs_stamp));
247 *timestamp = (CleanString) cleanTimestamp;
248 memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp));
249 CleanStringLength(cleanTimestamp) = strlen(cs_stamp);
250 }
251
252 void cleanNextHistory(CleanString *line, CleanString *timestamp, int *null)
253 {
254 *null = 0;
255 HIST_ENTRY *entry = next_history();
256 char *cs_line = "";
257 char *cs_stamp = "";
258 if(entry == NULL){
259 *null = 1;
260 } else {
261 *null = 0;
262 cs_line = entry->line;
263 cs_stamp = entry->timestamp;
264 }
265
266 CleanStringVariable(cleanLine, strlen(cs_line));
267 *line = (CleanString) cleanLine;
268 memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line));
269 CleanStringLength(cleanLine) = strlen(cs_line);
270
271 CleanStringVariable(cleanTimestamp, strlen(cs_stamp));
272 *timestamp = (CleanString) cleanTimestamp;
273 memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp));
274 CleanStringLength(cleanTimestamp) = strlen(cs_stamp);
275 }
276
277 //Searching the History List
278 int cleanHistorySearch(CleanString s, int dir)
279 {
280 char *cs_s = cleanStringToCString(s);
281 int ret = history_search(cs_s, dir);
282 free(cs_s);
283 return ret;
284 }
285
286 int cleanHistorySearchPrefix(CleanString s, int dir)
287 {
288 char *cs_s = cleanStringToCString(s);
289 int ret = history_search_prefix(cs_s, dir);
290 free(cs_s);
291 return ret;
292 }
293
294 int cleanHistorySearchPos(CleanString s, int dir, int pos)
295 {
296 char *cs_s = cleanStringToCString(s);
297 int ret = history_search_pos(cs_s, dir, pos);
298 free(cs_s);
299 return ret;
300 }
301
302 //Managing the History File
303 int cleanReadHistory(CleanString path)
304 {
305 char *cs_path = cleanStringToCString(path);
306 int errno = read_history(cs_path);
307 free(cs_path);
308 return errno == 0;
309 }
310
311 int cleanReadHistoryRange(CleanString path, int from, int to)
312 {
313 char *cs_path = cleanStringToCString(path);
314 int errno = read_history_range(cs_path, from, to);
315 free(cs_path);
316 return errno == 0;
317 }
318
319 int cleanWriteHistory(CleanString path)
320 {
321 char *cs_path = cleanStringToCString(path);
322 int errno = write_history(cs_path);
323 free(cs_path);
324 return errno == 0;
325 }
326
327 int cleanAppendHistory(int n, CleanString path)
328 {
329 char *cs_path = cleanStringToCString(path);
330 int errno = append_history(n, cs_path);
331 free(cs_path);
332 return errno == 0;
333 }
334
335 int cleanHistoryTruncateFile(CleanString path, int nlines)
336 {
337 char *cs_path = cleanStringToCString(path);
338 int errno = history_truncate_file(cs_path, nlines);
339 free(cs_path);
340 return errno == 0;
341 }
342
343 //History Expansion
344 void cleanHistoryExpand(CleanString string, CleanString *output, int *ret)
345 {
346 char *cs_output;
347 char *cs_string = cleanStringToCString(string);
348 *ret = history_expand(cs_string, &cs_output);
349
350 CleanStringVariable(cleanOutput, strlen(cs_output));
351 *output = (CleanString) cleanOutput;
352 memcpy(CleanStringCharacters(cleanOutput), cs_output, strlen(cs_output));
353 CleanStringLength(cleanOutput) = strlen(cs_output);
354 free(cs_output);
355 free(cs_string);
356 }
357
358 void cleanGetHistoryEvent(
359 CleanString string, int qchar, int cindex, CleanString *output,
360 int *retcindex, int *null)
361 {
362 char *cs_string = cleanStringToCString(string);
363 char *cs_output = get_history_event(cs_string, &cindex, qchar);
364
365 if(cs_output == NULL){
366 *null = 1;
367 cs_output = "";
368 } else {
369 *null = 0;
370 }
371
372 CleanStringVariable(cleanOutput, strlen(cs_output));
373 *output = (CleanString) cleanOutput;
374 memcpy(CleanStringCharacters(cleanOutput), cs_output, strlen(cs_output));
375 CleanStringLength(cleanOutput) = strlen(cs_output);
376
377 if(*null == 0){
378 free(cs_output);
379 }
380 *retcindex = cindex;
381 }
382
383 int cleanHistoryTokenizeInit(CleanString string)
384 {
385 if(cs_tokens){
386 for(int i = 0; i<num_tokens; i++){
387 free(cs_tokens[i]);
388 }
389 free(cs_tokens);
390 }
391 char *cs_string = cleanStringToCString(string);
392 cs_tokens = history_tokenize(cs_string);
393 free(cs_string);
394
395 num_tokens = 0;
396 for(; cs_tokens[num_tokens]; num_tokens++);
397 return num_tokens;
398 }
399
400 void cleanHistoryTokenizeItem(int num, CleanString *output)
401 {
402 char *cs_output = cs_tokens[num];
403 CleanStringVariable(cleanOutput, strlen(cs_output));
404 *output = (CleanString) cleanOutput;
405 memcpy(CleanStringCharacters(cleanOutput), cs_output, strlen(cs_output));
406 CleanStringLength(cleanOutput) = strlen(cs_output);
407 }
408
409 void cleanHistoryArgExtract(
410 int first, int last, CleanString string, CleanString *output, int *null)
411 {
412 char *cs_string = cleanStringToCString(string);
413 char *cs_output = history_arg_extract(first, last, cs_string);
414 if(cs_output == NULL){
415 *null = 1;
416 cs_output = "";
417 } else {
418 *null = 0;
419 }
420
421 CleanStringVariable(cleanOutput, strlen(cs_output));
422 *output = (CleanString) cleanOutput;
423 memcpy(CleanStringCharacters(cleanOutput), cs_output, strlen(cs_output));
424 CleanStringLength(cleanOutput) = strlen(cs_output);
425
426 if(*null == 0){
427 free(cs_output);
428 }
429 }