]> git.lizzy.rs Git - nothing.git/blob - src/ui/history.c
TODO(#390)
[nothing.git] / src / ui / history.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4
5 #include "history.h"
6 #include "system/lt.h"
7 #include "system/error.h"
8 #include "str.h"
9
10 struct History
11 {
12     Lt *lt;
13
14     char **buffer;
15     size_t begin;
16     size_t capacity;
17     size_t cursor;
18 };
19
20 History *create_history(size_t capacity)
21 {
22     Lt *lt = create_lt();
23     if (lt == NULL) {
24         return NULL;
25     }
26
27     History *history = PUSH_LT(
28         lt,
29         malloc(sizeof(History)),
30         free);
31     if (history == NULL) {
32         throw_error(ERROR_TYPE_LIBC);
33         RETURN_LT(lt, NULL);
34     }
35     history->lt = lt;
36
37     history->capacity = capacity;
38     history->begin = 0;
39     history->cursor = 0;
40
41     history->buffer = PUSH_LT(lt, calloc(capacity, sizeof(char*)), free);
42     if (history->buffer == NULL) {
43         throw_error(ERROR_TYPE_LIBC);
44         RETURN_LT(lt, NULL);
45     }
46
47     return history;
48 }
49
50 void destroy_history(History *history)
51 {
52     assert(history);
53
54     for (size_t i = 0; i < history->capacity; ++i) {
55         if (history->buffer[i] != NULL) {
56             free(history->buffer[i]);
57         }
58     }
59
60     RETURN_LT0(history->lt);
61 }
62
63 int history_push(History *history, const char *command)
64 {
65     assert(history);
66     assert(command);
67
68     const size_t next_begin = (history->begin + 1) % history->capacity;
69
70     if (history->buffer[history->begin] != NULL) {
71         free(history->buffer[history->begin]);
72     }
73
74     history->buffer[history->begin] = string_duplicate(command, NULL);
75
76     if (history->buffer[history->begin] == NULL) {
77         return -1;
78     }
79
80     history->begin = next_begin;
81     history->cursor = next_begin;
82
83     return 0;
84 }
85
86 const char *history_current(History *history)
87 {
88     assert(history);
89     return history->buffer[history->cursor];
90 }
91
92 void history_prev(History *history)
93 {
94     assert(history);
95     if (history->cursor == 0) {
96         history->cursor = history->capacity - 1;
97     } else {
98         history->cursor--;
99     }
100 }
101
102 void history_next(History *history)
103 {
104     assert(history);
105     history->cursor = (history->cursor + 1) % history->capacity;
106 }