2 65c49665 2024-01-23 op * Copyright (c) 2021, 2024 Omar Polo <op@omarpolo.com>
4 2051e653 2021-03-13 op * Permission to use, copy, modify, and distribute this software for any
5 2051e653 2021-03-13 op * purpose with or without fee is hereby granted, provided that the above
6 2051e653 2021-03-13 op * copyright notice and this permission notice appear in all copies.
8 2051e653 2021-03-13 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 2051e653 2021-03-13 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 2051e653 2021-03-13 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 2051e653 2021-03-13 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 2051e653 2021-03-13 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 2051e653 2021-03-13 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 2051e653 2021-03-13 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 786e6deb 2021-07-21 op #include "compat.h"
19 2051e653 2021-03-13 op #include <stdlib.h>
20 65c49665 2024-01-23 op #include <string.h>
22 65c49665 2024-01-23 op #include "hist.h"
25 65c49665 2024-01-23 op TAILQ_HEAD(mhist, hist_item) head;
29 65c49665 2024-01-23 op struct hist_item *cur;
32 65c49665 2024-01-23 op struct hist_item {
34 65c49665 2024-01-23 op size_t line_off;
35 65c49665 2024-01-23 op size_t current_off;
36 65c49665 2024-01-23 op TAILQ_ENTRY(hist_item) entries;
40 65c49665 2024-01-23 op hist_new(int flags)
42 65c49665 2024-01-23 op struct hist *hist;
44 65c49665 2024-01-23 op if ((hist = calloc(1, sizeof(*hist))) == NULL)
45 65c49665 2024-01-23 op return (NULL);
47 65c49665 2024-01-23 op TAILQ_INIT(&hist->head);
48 65c49665 2024-01-23 op hist->flags = flags;
49 65c49665 2024-01-23 op hist->off = -1;
50 65c49665 2024-01-23 op return (hist);
54 65c49665 2024-01-23 op hist_free(struct hist *hist)
56 65c49665 2024-01-23 op if (hist == NULL)
59 65c49665 2024-01-23 op hist_erase(hist);
64 65c49665 2024-01-23 op hist_erase_from(struct hist *hist, struct hist_item *h)
66 65c49665 2024-01-23 op struct hist_item *next;
68 65c49665 2024-01-23 op while (h != NULL) {
69 65c49665 2024-01-23 op next = TAILQ_NEXT(h, entries);
72 65c49665 2024-01-23 op TAILQ_REMOVE(&hist->head, h, entries);
80 65c49665 2024-01-23 op hist_erase(struct hist *hist)
82 65c49665 2024-01-23 op hist_erase_from(hist, TAILQ_FIRST(&hist->head));
84 65c49665 2024-01-23 op hist->size = 0;
85 65c49665 2024-01-23 op hist->off = -1;
86 65c49665 2024-01-23 op hist->cur = NULL;
90 65c49665 2024-01-23 op hist_size(struct hist *hist)
92 65c49665 2024-01-23 op return (hist->size);
96 65c49665 2024-01-23 op hist_off(struct hist *hist)
98 65c49665 2024-01-23 op if (hist->off == -1)
100 65c49665 2024-01-23 op return (hist->off);
104 65c49665 2024-01-23 op hist_cur(struct hist *hist)
106 65c49665 2024-01-23 op if (hist->cur == NULL)
107 65c49665 2024-01-23 op return (NULL);
108 65c49665 2024-01-23 op return (hist->cur->str);
112 65c49665 2024-01-23 op hist_cur_offs(struct hist *hist, size_t *line, size_t *curr)
117 65c49665 2024-01-23 op if (hist->cur == NULL)
120 65c49665 2024-01-23 op *line = hist->cur->line_off;
121 65c49665 2024-01-23 op *curr = hist->cur->current_off;
126 65c49665 2024-01-23 op hist_set_cur(struct hist *hist, const char *str)
130 65c49665 2024-01-23 op if (hist->cur == NULL)
133 65c49665 2024-01-23 op if ((d = strdup(str)) == NULL)
136 65c49665 2024-01-23 op free(hist->cur->str);
137 65c49665 2024-01-23 op hist->cur->str = d;
142 65c49665 2024-01-23 op hist_set_offs(struct hist *hist, size_t line, size_t curr)
144 65c49665 2024-01-23 op if (hist->cur == NULL)
147 65c49665 2024-01-23 op hist->cur->line_off = line;
148 65c49665 2024-01-23 op hist->cur->current_off = line;
153 65c49665 2024-01-23 op hist_nth(struct hist *hist, size_t n)
156 65c49665 2024-01-23 op struct hist_item *h;
159 65c49665 2024-01-23 op TAILQ_FOREACH(h, &hist->head, entries) {
160 65c49665 2024-01-23 op if (i++ == n)
161 65c49665 2024-01-23 op return (h->str);
163 65c49665 2024-01-23 op return (NULL);
167 65c49665 2024-01-23 op hist_prev(struct hist *hist)
169 65c49665 2024-01-23 op struct hist_item *h;
170 65c49665 2024-01-23 op int wrap = hist->flags & HIST_WRAP;
172 65c49665 2024-01-23 op if (hist->cur == NULL && !wrap)
173 65c49665 2024-01-23 op return (NULL);
175 65c49665 2024-01-23 op if (hist->cur == NULL ||
176 65c49665 2024-01-23 op (h = TAILQ_PREV(hist->cur, mhist, entries)) == NULL) {
177 65c49665 2024-01-23 op if (!wrap || (h = TAILQ_LAST(&hist->head, mhist)) == NULL)
178 65c49665 2024-01-23 op return (NULL);
179 65c49665 2024-01-23 op hist->off = hist->size - 1;
183 65c49665 2024-01-23 op hist->cur = h;
184 65c49665 2024-01-23 op return (h->str);
188 65c49665 2024-01-23 op hist_next(struct hist *hist)
190 65c49665 2024-01-23 op struct hist_item *h;
191 65c49665 2024-01-23 op int wrap = hist->flags & HIST_WRAP;
193 65c49665 2024-01-23 op if (hist->cur == NULL && !wrap)
194 65c49665 2024-01-23 op return (NULL);
196 65c49665 2024-01-23 op if (hist->cur == NULL ||
197 65c49665 2024-01-23 op (h = TAILQ_NEXT(hist->cur, entries)) == NULL) {
198 65c49665 2024-01-23 op if (!wrap || (h = TAILQ_FIRST(&hist->head)) == NULL)
199 65c49665 2024-01-23 op return (NULL);
200 65c49665 2024-01-23 op hist->off = 0;
204 65c49665 2024-01-23 op hist->cur = h;
205 65c49665 2024-01-23 op return (h->str);
209 65c49665 2024-01-23 op hist_seek_start(struct hist *hist)
211 65c49665 2024-01-23 op hist->off = -1;
212 65c49665 2024-01-23 op hist->cur = NULL;
216 65c49665 2024-01-23 op hist_push(struct hist *hist, const char *str)
218 65c49665 2024-01-23 op struct hist_item *h;
220 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
223 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
228 65c49665 2024-01-23 op if (hist->cur != NULL)
229 65c49665 2024-01-23 op hist_erase_from(hist, TAILQ_NEXT(hist->cur, entries));
230 65c49665 2024-01-23 op hist->cur = h;
232 65c49665 2024-01-23 op hist->size++;
233 65c49665 2024-01-23 op TAILQ_INSERT_TAIL(&hist->head, h, entries);
238 65c49665 2024-01-23 op hist_prepend(struct hist *hist, const char *str)
240 65c49665 2024-01-23 op struct hist_item *h;
242 65c49665 2024-01-23 op if (hist->cur == NULL)
245 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
248 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
253 65c49665 2024-01-23 op hist->size++;
255 65c49665 2024-01-23 op TAILQ_INSERT_BEFORE(hist->cur, h, entries);
260 65c49665 2024-01-23 op hist_append(struct hist *hist, const char *str)
262 65c49665 2024-01-23 op struct hist_item *h;
265 65c49665 2024-01-23 op * Not sure. The minibuffer needs to append even when there
266 65c49665 2024-01-23 op * are no items.
268 65c49665 2024-01-23 op if (hist->cur == NULL && !(hist->flags & HIST_WRAP))
271 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
274 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
279 65c49665 2024-01-23 op hist->size++;
280 65c49665 2024-01-23 op TAILQ_INSERT_TAIL(&hist->head, h, entries);