display.c (5996B)
1 #include <ctype.h> 2 #include <stddef.h> 3 #include <string.h> 4 5 #include <pane/pane.h> 6 #include <pane/utils.h> 7 8 #include "anki.h" 9 #include "display.h" 10 11 #define USTART L'\u2654' 12 13 wchar_t convert(char l) { 14 if (l == ' ') 15 return ' '; 16 int p = piece_get_index(l); 17 return (p >= 0) ? p + USTART : L'!'; 18 } 19 20 void board_display(widget_T widget) { 21 size_t i, j; 22 Pane_T pane = widget->pane; 23 boardInfo_T info = (boardInfo_T)widget->info; 24 boardStyle_T style = (boardStyle_T)widget->style; 25 game_T game = (game_T)widget->data->payload; 26 Board_T board = game->boards[game->display_current]; 27 28 UNUSED(info); 29 30 int bg_color, fg_color, dark; 31 size_t x_start = centerHorisontal(pane, 16); 32 size_t y_start = centerVertical(pane, 8); 33 for (i = 0; i < 8; i++) { 34 for (j = 0; j < 8; j++) { 35 dark = style->square_dark; 36 if (game->pass) 37 dark = style->pass; 38 else if (game->fail) 39 dark = style->fail; 40 bg_color = ((i + j) % 2) ? dark : style->square_light; 41 fg_color = style->piece; 42 #ifndef NO_UNICODE 43 tb_set_cell(x_start + 2 * i, y_start + j, 44 convert(Board_atIndex(board, j, i)), fg_color, bg_color); 45 #else 46 tb_set_cell(x_start + 2 * i, y_start + j, Board_atIndex(board, j, i), 47 fg_color, bg_color); 48 #endif 49 tb_set_cell(x_start + 2 * i + 1, y_start + j, ' ', fg_color, bg_color); 50 } 51 } 52 53 /* display_grave(Board_grave(board, 'w'), y++, startx); */ 54 /* display_grave(Board_grave(board, 'b'), y++, startx); */ 55 56 if (style->annotation) { 57 char *files = "A B C D E F G H"; 58 char *ranks = "87654321"; 59 if (style->annotation & 8) 60 tb_print(x_start, y_start - 1, TB_GREEN, 0, files); 61 if (style->annotation & 2) 62 tb_print(x_start, y_start + 8, TB_GREEN, 0, files); 63 for (i = 0; i < 8; i++) { 64 if (style->annotation & 1) 65 tb_printf(x_start - 2, y_start + i, TB_GREEN, 0, "%c", ranks[i]); 66 if (style->annotation & 4) 67 tb_printf(x_start + 17, y_start + i, TB_GREEN, 0, "%c", ranks[i]); 68 } 69 } 70 71 if (style->border) { 72 tb_printf(x_start, y_start - 1, 0, style->border, " "); 73 tb_printf(x_start, y_start + 8, 0, style->border, " "); 74 for (i = y_start - 1; i < y_start + 9; i++) { 75 tb_printf(x_start - 2, i, 0, style->border, " "); 76 tb_printf(x_start + 16, i, 0, style->border, " "); 77 } 78 } 79 80 tb_printf(x_start, pane_y(pane) + pane_height(pane) - 1, TB_GREEN, 0, "%*s", 81 BUFF_SIZE, game->buffer); 82 83 tb_present(); 84 } 85 86 int game_handleInput(data_T data, struct tb_event ev) { 87 game_T game = (game_T)data->payload; 88 89 switch (ev.key) { 90 case TB_KEY_ARROW_LEFT: 91 if (game->display_current > 0) 92 game->display_current--; 93 return INPUT_HANDLED; 94 case TB_KEY_ARROW_RIGHT: 95 if (game->display_current < game->move_current) 96 game->display_current++; 97 return INPUT_HANDLED; 98 case TB_KEY_ARROW_UP: 99 game->display_current = 0; 100 return INPUT_HANDLED; 101 case TB_KEY_ARROW_DOWN: 102 game->display_current = game->move_current; 103 return INPUT_HANDLED; 104 case TB_KEY_ENTER: 105 if (game->move_current == game->moves_num) { 106 anki_grade(game->pass); 107 return (game->review_next()) ? INPUT_HANDLED : INPUT_REFORM; 108 } 109 110 if (game->buffer_crnt) { 111 if (strcmp(game->buffer, game->moves[game->move_current + 1]) != 0) { 112 game->move_fail = game->move_current + 1; 113 game->move_current = game->moves_num; 114 game->fail = 1; 115 } else { 116 game->display_current = ++game->move_current; 117 118 if (game->move_current == game->moves_num) 119 game->pass = 1; 120 121 memset(game->buffer, '\0', BUFF_SIZE); 122 game->buffer_crnt = 0; 123 } 124 } 125 return INPUT_HANDLED; 126 case TB_KEY_BACKSPACE: 127 case TB_KEY_BACKSPACE2: 128 CLAMP(game->buffer_crnt, 1, BUFF_SIZE + 1); 129 game->buffer[--game->buffer_crnt] = '\0'; 130 return INPUT_HANDLED; 131 default: { 132 char *valid = "abcdefgh12345678KQRBNPx#+O-!?="; 133 if (strchr(valid, ev.ch)) { 134 if (game->buffer_crnt < BUFF_SIZE) 135 game->buffer[game->buffer_crnt++] = ev.ch; 136 return INPUT_HANDLED; 137 } 138 switch (ev.ch) { 139 case 'r': 140 case 'R': 141 return (game->review_next()) ? INPUT_HANDLED : INPUT_REFORM; 142 } 143 } 144 } 145 146 return INPUT_IGNORED; 147 } 148 149 void move_display(game_T game, movesStyle_T style, size_t move_index, 150 char *move, int x, int y) { 151 int color, background; 152 color = (game->move_start == move_index) ? TB_GREEN : style->foreground; 153 color = (game->move_fail == move_index) ? TB_RED : color; 154 background = 155 (game->display_current == move_index) ? style->active : style->background; 156 tb_printf(x, y, color, background, "%*s", style->move_padding, move); 157 } 158 159 void moves_display(widget_T widget) { 160 size_t i; 161 Pane_T pane = widget->pane; 162 movesInfo_T info = (movesInfo_T)widget->info; 163 movesStyle_T style = (movesStyle_T)widget->style; 164 game_T game = (game_T)widget->data->payload; 165 166 if (!widget->inited) { 167 widget->inited = 1; 168 info->list = widgetList_new(widget->pane, game->moves_num / 2 + 1); 169 } 170 171 widgetList_T list = info->list; 172 int display_row = ACLAMP(((int)game->display_current - 1) / 2, 0, 173 ((int)game->moves_num / 2)); 174 widgetList_cacl(list, display_row); 175 176 pane_clear(pane, 0); 177 int x = centerHorisontal(pane, 2 * style->move_padding + style->num_padding), 178 y = pane_y(pane); 179 size_t index_end = 180 MIN(list->index_start + list->display_num, (game->move_current + 1) / 2); 181 for (i = list->index_start; i < index_end; i++, y++) { 182 tb_printf(x, y, style->foreground, style->background, "%d.", i + 1); 183 move_display(game, style, i * 2 + 1, game->moves[i * 2 + 1], 184 x + style->num_padding, y); 185 if (i * 2 + 2 <= game->move_current) 186 move_display(game, style, i * 2 + 2, game->moves[i * 2 + 2], 187 x + style->num_padding + style->move_padding, y); 188 } 189 }