paint.demo.c (3471B)
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 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 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 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 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 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 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 }