]> git.lizzy.rs Git - nothing.git/blob - src/ui/history.c
Formatting
[nothing.git] / src / ui / history.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "system/stacktrace.h"
4
5 #include "history.h"
6 #include "system/str.h"
7 #include "system/lt.h"
8 #include "system/nth_alloc.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
24     History *history = PUSH_LT(
25         lt,
26         nth_calloc(1, sizeof(History)),
27         free);
28     if (history == NULL) {
29         RETURN_LT(lt, NULL);
30     }
31     history->lt = lt;
32
33     history->capacity = capacity;
34     history->begin = 0;
35     history->cursor = 0;
36
37     history->buffer = PUSH_LT(lt, nth_calloc(capacity, sizeof(char*)), free);
38     if (history->buffer == NULL) {
39         RETURN_LT(lt, NULL);
40     }
41
42     return history;
43 }
44
45 void destroy_history(History *history)
46 {
47     trace_assert(history);
48
49     for (size_t i = 0; i < history->capacity; ++i) {
50         if (history->buffer[i] != NULL) {
51             free(history->buffer[i]);
52         }
53     }
54
55     RETURN_LT0(history->lt);
56 }
57
58 int history_push(History *history, const char *command)
59 {
60     trace_assert(history);
61     trace_assert(command);
62
63     const size_t next_begin = (history->begin + 1) % history->capacity;
64
65     if (history->buffer[history->begin] != NULL) {
66         free(history->buffer[history->begin]);
67     }
68
69     history->buffer[history->begin] = string_duplicate(command, NULL);
70
71     if (history->buffer[history->begin] == NULL) {
72         return -1;
73     }
74
75     history->begin = next_begin;
76     history->cursor = next_begin;
77
78     return 0;
79 }
80
81 const char *history_current(History *history)
82 {
83     trace_assert(history);
84     return history->buffer[history->cursor];
85 }
86
87 void history_prev(History *history)
88 {
89     trace_assert(history);
90     if (history->cursor == 0) {
91         history->cursor = history->capacity - 1;
92     } else {
93         history->cursor--;
94     }
95 }
96
97 void history_next(History *history)
98 {
99     trace_assert(history);
100     history->cursor = (history->cursor + 1) % history->capacity;
101 }