tmus

TUI Music Player
git clone https://git.sinitax.com/sinitax/tmus
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

history.c (4761B)


      1#include "list.h"
      2#define _GNU_SOURCE
      3
      4#include "history.h"
      5#include "util.h"
      6
      7#include "grapheme.h"
      8
      9#include <string.h>
     10#include <stdlib.h>
     11
     12static struct inputln *history_list_prev(
     13	struct inputln  *cur, const char *search);
     14
     15static struct inputln *history_list_next(
     16	struct inputln  *cur, const char *search);
     17
     18struct inputln *
     19history_list_prev(struct inputln *cur, const char *search)
     20{
     21	struct list_link *iter;
     22	struct inputln *ln;
     23
     24	for (iter = cur->link.prev; iter && iter->prev; iter = iter->prev) {
     25		ln = LIST_UPCAST(iter, struct inputln, link);
     26		if (!search || !*search || strcasestr(ln->buf, search))
     27			return ln;
     28	}
     29
     30	return cur;
     31}
     32
     33struct inputln *
     34history_list_next(struct inputln *cur, const char *search)
     35{
     36	struct list_link *iter;
     37	struct inputln *ln;
     38
     39	iter = cur->link.next;
     40	while (LIST_INNER(iter)) {
     41		ln = LIST_UPCAST(iter, struct inputln, link);
     42		if (!search || !*search || strcasestr(ln->buf, search))
     43			return ln;
     44		iter = iter->next;
     45	}
     46
     47	return cur;
     48}
     49
     50void
     51history_init(struct history *history)
     52{
     53	list_init(&history->list);
     54	history->input = inputln_alloc();
     55	history->sel = history->input;
     56}
     57
     58void
     59history_deinit(struct history *history)
     60{
     61	struct list_link *link;
     62	struct inputln *ln;
     63
     64	link = list_link_pop(&history->input->link);
     65	ln = LIST_UPCAST(link, struct inputln, link);
     66	inputln_free(ln);
     67	history->input = NULL;
     68
     69	list_free_items(&history->list, (list_item_free_fn) inputln_free,
     70		LIST_OFFSET(struct inputln, link));
     71
     72	history->sel = NULL;
     73}
     74
     75void
     76history_submit(struct history *history)
     77{
     78	/* if chose from history free input */
     79	if (history->sel != history->input) {
     80		list_link_pop(&history->input->link);
     81		inputln_free(history->input);
     82	}
     83
     84	/* pop first in case already in history */
     85	list_link_pop(&history->sel->link);
     86	history_add(history, history->sel);
     87
     88	/* create new input buf and add to hist */
     89	history->input = inputln_alloc();
     90	history->sel = history->input;
     91	history_add(history, history->sel);
     92}
     93
     94void
     95history_prev(struct history *history)
     96{
     97	history->sel = history_list_prev(history->sel, history->input->buf);
     98}
     99
    100void
    101history_next(struct history *history)
    102{
    103	history->sel = history_list_next(history->sel, history->input->buf);
    104}
    105
    106void
    107history_add(struct history *history, struct inputln *line)
    108{
    109	struct inputln *ln;
    110	struct list_link *back;
    111
    112	if (list_len(&history->list) == HISTORY_MAX) {
    113		/* pop last item to make space */
    114		back = list_pop_back(&history->list);
    115		ln = LIST_UPCAST(back, struct inputln, link);
    116		inputln_free(ln);
    117	}
    118
    119	list_insert_front(&history->list, &line->link);
    120}
    121
    122void
    123inputln_init(struct inputln *ln)
    124{
    125	ln->buf = NULL;
    126	ln->len = 0;
    127	ln->cap = 0;
    128	ln->cur = 0;
    129	ln->curpos = 0;
    130	ln->link = LIST_LINK_INIT;
    131
    132	inputln_resize(ln, 128);
    133}
    134
    135void
    136inputln_deinit(struct inputln *ln)
    137{
    138	free(ln->buf);
    139}
    140
    141struct inputln *
    142inputln_alloc(void)
    143{
    144	struct inputln *ln;
    145
    146	ln = malloc(sizeof(struct inputln));
    147	if (!ln) ERROR(SYSTEM, "malloc");
    148	inputln_init(ln);
    149
    150	return ln;
    151}
    152
    153void
    154inputln_free(struct inputln *ln)
    155{
    156	inputln_deinit(ln);
    157	free(ln);
    158}
    159
    160void
    161inputln_resize(struct inputln *ln, size_t size)
    162{
    163	ASSERT(size != 0);
    164
    165	ln->cap = size;
    166	ln->buf = realloc(ln->buf, ln->cap * sizeof(char));
    167	if (!ln->buf) ERROR(SYSTEM, "realloc");
    168	ln->len = MIN(ln->len, ln->cap-1);
    169	ln->buf[ln->len] = '\0';
    170}
    171
    172void
    173inputln_left(struct inputln *ln)
    174{
    175	ln->cur = utf8_next_break_left(ln->buf, ln->cur);
    176	ln->curpos = text_width(ln->buf, ln->cur);
    177}
    178
    179void
    180inputln_right(struct inputln *ln)
    181{
    182	ln->cur = utf8_next_break_right(ln->buf, ln->cur);
    183	ln->curpos = text_width(ln->buf, ln->cur);
    184}
    185
    186void
    187inputln_addch(struct inputln *ln, char c)
    188{
    189	int i;
    190
    191	if (ln->len + 1 >= ln->cap) {
    192		ln->cap *= 2;
    193		ln->buf = realloc(ln->buf, ln->cap);
    194	}
    195
    196	for (i = ln->len; i > ln->cur; i--)
    197		ln->buf[i] = ln->buf[i-1];
    198	ln->buf[ln->cur] = c;
    199
    200	ln->len++;
    201	ln->cur++;
    202	ln->buf[ln->len] = '\0';
    203
    204	ln->curpos = text_width(ln->buf, ln->cur);
    205}
    206
    207void
    208inputln_del(struct inputln *ln, int n)
    209{
    210	size_t next;
    211	int i;
    212
    213	if (!ln->cur) return;
    214
    215	next = utf8_next_break_left(ln->buf, ln->cur);
    216	n = ln->cur - next;
    217	for (i = ln->cur; i <= ln->len; i++)
    218		ln->buf[i-n] = ln->buf[i];
    219
    220	ln->len -= n;
    221	ln->cur -= n;
    222	ln->buf[ln->len] = '\0';
    223
    224	ln->curpos = text_width(ln->buf, ln->cur);
    225}
    226
    227void
    228inputln_copy(struct inputln *dst, struct inputln *src)
    229{
    230	if (dst->buf) {
    231		free(dst->buf);
    232		dst->buf = NULL;
    233	}
    234	dst->len = src->len;
    235	dst->buf = astrdup(src->buf);
    236	dst->cap = src->len + 1;
    237	dst->cur = dst->len;
    238	dst->curpos = text_width(dst->buf, dst->len);
    239}
    240
    241void
    242inputln_replace(struct inputln *ln, const char *str)
    243{
    244	ln->len = strlen(str);
    245	if (ln->cap <= ln->len)
    246		inputln_resize(ln, ln->len + 1);
    247	strncpy(ln->buf, str, ln->len + 1);
    248	ln->cur = ln->len;
    249	ln->curpos = text_width(ln->buf, ln->len);
    250}
    251