summaryrefslogtreecommitdiff
path: root/main.c
blob: 111aeed3843dea474286475fb798cbfbb498fa9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* xmenu
 * a simple fuzzy-selection menu made with Xlib
 */

#include <stdio.h>

#define ARENA_IMPL
#define STR_IMPL

#include "arena.h"
#include "dynarr.h"
#include "str.h"
#include "ui.h"

typedef DYNARR(char) DynStr;

int
umod(int a, int b)
{
	if (a < 0) {
		return b + a % b;
	} else {
		return a % b;
	}
}

int
txt_insert(DynStr *s, int i, Str ins)
{
	DA_FIT(s, s->n + ins.n);
	if (i < s->n) {
		memmove(s->v + i + ins.n, s->v + i, s->n - i);
	}
	memcpy(s->v + i, ins.s, ins.n);
	s->n += ins.n;
	return i + ins.n;
}

int
txt_delete(DynStr *s, int i, int n)
{
	if (n > i) n = i;
	if (n > 0) {
		memmove(s->v + i - n, s->v + i, s->n - i);
		s->n -= n;
	}
	return i - n;
}

int
main(int argc, char **argv)
{
	ui_init(argc, argv);

	DynStr input = { 0 };
	int inpi = 0;
	int seli = 0;
	Str optv[] = {
		S("she shit on my thang until i vomit"),
		S("what"),
		S("who are you"),
		S("why are you"),
		S("where'd you come from")
	};
	int optc = sizeof optv / sizeof *optv;
	if (!optc) goto done;
	for (UiEvent ev; ui_wait_event(&ev); ) {
		switch (ev.type) {
		case UI_KEY_DOWN:
			switch (ev.key.key) {
			case UIK_ESCAPE:
				goto done;
			case UIK_BACKSPACE:
				inpi = txt_delete(&input, inpi, 1);
				goto draw;
			case UIK_RETURN: {
				Str o = optv[seli];
				printf("%.*s\n", (int)o.n, o.s);
			} goto done;
			case UIK_DOWN:
				seli = umod(seli + 1, optc);
				goto draw;
			case UIK_UP:
				seli = umod(seli - 1, optc);
				goto draw;
			case UIK_LEFT:
				if (inpi > 0) inpi--;
				goto draw;
			case UIK_RIGHT:
				if (inpi < input.n) inpi++;
				goto draw;
			case UIK_HOME:
				inpi = 0;
				goto draw;
			case UIK_END:
				inpi = input.n;
				goto draw;
			default:
				if (!ev.key.strn) break;
				inpi = txt_insert(&input, inpi, (Str) { ev.key.str, ev.key.strn });
				seli = 0;
				goto draw;
			}
			break;
		case UI_REDRAW:
		draw:
			ui_draw(
				(Str) { input.v, input.n },
				inpi,
				seli,
				optv,
				optc
			);
			break;
		default:
			break;
		}
	}

done:
	ui_fini();

	return 0;
}