1 #include "../termbox.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 static int curCol = 0;
7 static int curRune = 0;
8 static struct tb_cell *backbuf;
9 static int bbw = 0, bbh = 0;
10
11 static const uint32_t runes[] = {
12 0x20, // ' '
13 0x2591, // '░'
14 0x2592, // '▒'
15 0x2593, // '▓'
16 0x2588, // '█'
17 };
18
19 #define len(a) (sizeof(a)/sizeof(a[0]))
20
21 static const uint16_t colors[] = {
22 TB_BLACK,
23 TB_RED,
24 TB_GREEN,
25 TB_YELLOW,
26 TB_BLUE,
27 TB_MAGENTA,
28 TB_CYAN,
29 TB_WHITE,
30 };
31
updateAndDrawButtons(int * current,int x,int y,int mx,int my,int n,void (* attrFunc)(int,uint32_t *,uint16_t *,uint16_t *))32 void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, void (*attrFunc)(int, uint32_t*, uint16_t*, uint16_t*)) {
33 int lx = x;
34 int ly = y;
35 for (int i = 0; i < n; i++) {
36 if (lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1) {
37 *current = i;
38 }
39 uint32_t r;
40 uint16_t fg, bg;
41 (*attrFunc)(i, &r, &fg, &bg);
42 tb_change_cell(lx+0, ly+0, r, fg, bg);
43 tb_change_cell(lx+1, ly+0, r, fg, bg);
44 tb_change_cell(lx+2, ly+0, r, fg, bg);
45 tb_change_cell(lx+3, ly+0, r, fg, bg);
46 tb_change_cell(lx+0, ly+1, r, fg, bg);
47 tb_change_cell(lx+1, ly+1, r, fg, bg);
48 tb_change_cell(lx+2, ly+1, r, fg, bg);
49 tb_change_cell(lx+3, ly+1, r, fg, bg);
50 lx += 4;
51 }
52 lx = x;
53 ly = y;
54 for (int i = 0; i < n; i++) {
55 if (*current == i) {
56 uint16_t fg = TB_RED | TB_BOLD;
57 uint16_t bg = TB_DEFAULT;
58 tb_change_cell(lx+0, ly+2, '^', fg, bg);
59 tb_change_cell(lx+1, ly+2, '^', fg, bg);
60 tb_change_cell(lx+2, ly+2, '^', fg, bg);
61 tb_change_cell(lx+3, ly+2, '^', fg, bg);
62 }
63 lx += 4;
64 }
65 }
66
runeAttrFunc(int i,uint32_t * r,uint16_t * fg,uint16_t * bg)67 void runeAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
68 *r = runes[i];
69 *fg = TB_DEFAULT;
70 *bg = TB_DEFAULT;
71 }
72
colorAttrFunc(int i,uint32_t * r,uint16_t * fg,uint16_t * bg)73 void colorAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
74 *r = ' ';
75 *fg = TB_DEFAULT;
76 *bg = colors[i];
77 }
78
updateAndRedrawAll(int mx,int my)79 void updateAndRedrawAll(int mx, int my) {
80 tb_clear();
81 if (mx != -1 && my != -1) {
82 backbuf[bbw*my+mx].ch = runes[curRune];
83 backbuf[bbw*my+mx].fg = colors[curCol];
84 }
85 memcpy(tb_cell_buffer(), backbuf, sizeof(struct tb_cell)*bbw*bbh);
86 int h = tb_height();
87 updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), runeAttrFunc);
88 updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), colorAttrFunc);
89 tb_present();
90 }
91
reallocBackBuffer(int w,int h)92 void reallocBackBuffer(int w, int h) {
93 bbw = w;
94 bbh = h;
95 if (backbuf)
96 free(backbuf);
97 backbuf = calloc(sizeof(struct tb_cell), w*h);
98 }
99
main(int argv,char ** argc)100 int main(int argv, char **argc) {
101 (void)argc; (void)argv;
102 int code = tb_init();
103 if (code < 0) {
104 fprintf(stderr, "termbox init failed, code: %d\n", code);
105 return -1;
106 }
107
108 tb_select_input_mode(TB_INPUT_ESC | TB_INPUT_MOUSE);
109 int w = tb_width();
110 int h = tb_height();
111 reallocBackBuffer(w, h);
112 updateAndRedrawAll(-1, -1);
113 for (;;) {
114 struct tb_event ev;
115 int mx = -1;
116 int my = -1;
117 int t = tb_poll_event(&ev);
118 if (t == -1) {
119 tb_shutdown();
120 fprintf(stderr, "termbox poll event error\n");
121 return -1;
122 }
123
124 switch (t) {
125 case TB_EVENT_KEY:
126 if (ev.key == TB_KEY_ESC) {
127 tb_shutdown();
128 return 0;
129 }
130 break;
131 case TB_EVENT_MOUSE:
132 if (ev.key == TB_KEY_MOUSE_LEFT) {
133 mx = ev.x;
134 my = ev.y;
135 }
136 break;
137 case TB_EVENT_RESIZE:
138 reallocBackBuffer(ev.w, ev.h);
139 break;
140 }
141 updateAndRedrawAll(mx, my);
142 }
143 }
144