main.c (6168B)
1 #include <ctype.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #define TB_IMPL 7 #define TB_OPT_TRUECOLOR 8 9 #include <cii/except.h> 10 #include <cii/mem.h> 11 #include <pane/menu.h> 12 #include <pane/pane.h> 13 #include <pane/utils.h> 14 #include <pane/widgets.h> 15 16 #include "anki.h" 17 #include "board.h" 18 #include "display.h" 19 20 /* static char *profile = NULL; */ 21 22 void set_selectDeck(void); 23 void set_selectProfile(void); 24 void profile_selected(char *name, int ignore); 25 void deck_selected(char *name, int ignore); 26 27 void start(void); 28 void stop(void); 29 30 struct widget_T error_widget = { 31 .pane = NULL, 32 .callback = widgetCenter_print, 33 .title = "Error", 34 }; 35 36 struct menuInfo_T mainMenuInfo; 37 struct menuStyle_T mainMenuStyle = { 38 .separator = "<------------->", 39 .padding = 2, 40 .spacing = 1, 41 }; 42 struct widget_T mainMenu_widget = { 43 .pane = NULL, 44 .callback = pane_menu, 45 .title = "Main Menu", 46 .style = &mainMenuStyle, 47 .info = &mainMenuInfo, 48 }; 49 50 menu_T anki_to_menu(const char **(*getter)(size_t *), menuItem_select_f select, 51 menu_back_f back) { 52 size_t i, size; 53 const char **profiles = getter(&size); 54 55 menu_T menu = menu_new(size, back); 56 for (i = 0; i < size; i++) { 57 menu->items[i].select_f = select; 58 menu->items[i].name = profiles[i]; 59 } 60 61 return menu; 62 } 63 64 struct boardInfo_T boardInfo; 65 struct boardStyle_T boardStyle = { 66 .square_dark = TB_GREEN, 67 .square_light = TB_WHITE, 68 .piece = TB_BLACK, 69 .pass = TB_BLUE, 70 .fail = TB_RED, 71 .border = 0, 72 .annotation = 3, 73 }; 74 struct widget_T board_widget = { 75 .pane = NULL, 76 .callback = board_display, 77 .title = "Board", 78 .style = &boardStyle, 79 .info = &boardInfo, 80 }; 81 82 #define MOVE_PADDING 8 83 84 struct movesInfo_T movesInfo; 85 struct movesStyle_T movesStyle = { 86 .move_padding = MOVE_PADDING, 87 .num_padding = 4, 88 .foreground = TB_WHITE, 89 .background = 0, 90 .active = TB_BLUE, 91 }; 92 struct widget_T moves_widget = { 93 .pane = NULL, 94 .callback = moves_display, 95 .title = "Moves", 96 .style = &movesStyle, 97 .info = &movesInfo, 98 }; 99 100 void title_callback(widget_T widget) { 101 game_T game = (game_T)widget->data->payload; 102 titleInfo_T info = (titleInfo_T)widget->info; 103 titleStyle_T style = (titleStyle_T)widget->style; 104 105 data_T data = data_new(card_name(game->card), NULL); 106 widget_setData(info->subwidget, data); 107 info->subwidget->pane = widget->pane; 108 info->subwidget->callback(info->subwidget); 109 110 UNUSED(style); 111 } 112 113 struct widget_T center_widget = { 114 .pane = NULL, 115 .callback = widgetCenter_print, 116 .title = "Title", 117 }; 118 119 struct titleInfo_T titleInfo = { 120 .subwidget = ¢er_widget, 121 }; 122 123 struct titleStyle_T titleStyle; 124 125 struct widget_T title_widget = { 126 .pane = NULL, 127 .callback = title_callback, 128 .title = "Title", 129 .style = &titleStyle, 130 .info = &titleInfo, 131 }; 132 133 void done_review(void) { 134 char message[] = 135 "You have finished all of the reviews for this deck. Please " 136 "check back later!"; 137 struct tb_event ev; 138 data_T data = data_new(message, NULL); 139 widget_setData(&error_widget, data); 140 widget_activate(&error_widget, MAIN); 141 error_widget.callback(&error_widget); 142 tb_poll_event(&ev); 143 if (ev.ch == 'q' || ev.key == TB_KEY_ESC) 144 stop(); 145 } 146 147 void review_finished(void) { 148 149 pane_unsplit(MAIN); 150 pane_clear(MAIN, 0); 151 152 done_review(); 153 set_selectDeck(); 154 widget_activate(&mainMenu_widget, MAIN); 155 } 156 157 int review_card(void) { 158 char *fen; 159 size_t moves_num, i; 160 161 card_T card = anki_current_card(); 162 163 if (card == NULL) { 164 review_finished(); 165 return 0; 166 } 167 168 char **moves = Move_list(card_pgn(card), &moves_num); 169 game_T game = game_new(moves_num); 170 171 int white = 1; 172 game->boards[0] = (fen = card_fen(card)) ? Board_from_FEN(fen) : Board_new(); 173 for (i = 1; i <= moves_num; i++, white = !white) 174 game->boards[i] = Board_play(game->boards[i - 1], moves[i], white); 175 176 game->card = card; 177 game->review_next = review_card; 178 game->move_start = game->move_current = game->display_current = 179 atoi(card_start(card)); 180 game->moves = moves; 181 182 data_T data = data_new(game, game_handleInput); 183 widget_setData(&board_widget, data); 184 widget_setData(&moves_widget, data); 185 widget_setData(&title_widget, data); 186 187 return 1; 188 } 189 190 void deck_selected(char *name, int ignore) { 191 UNUSED(ignore); 192 Pane_T *children1, *children2; 193 194 anki_load_deck(name); 195 196 if (anki_current_card()) { 197 pane_clear(MAIN, 1); 198 children1 = pane_vsplit(MAIN, 2, -5, 1); 199 children2 = pane_split(children1[1], 2, -(MOVE_PADDING * 3 + 4), 2); 200 201 review_card(); 202 203 widget_activate(&title_widget, children1[0]); 204 widget_activate(&moves_widget, children2[0]); 205 widget_activate(&board_widget, children2[1]); 206 } else { 207 done_review(); 208 set_selectDeck(); 209 widget_activate(&mainMenu_widget, MAIN); 210 } 211 } 212 213 void profile_selected(char *name, int ignore) { 214 UNUSED(ignore); 215 /* if (!profile) */ 216 /* profile = malloc(100 * sizeof(char)); */ 217 /* strcpy(profile, name); */ 218 anki_load_profile(name); 219 set_selectDeck(); 220 } 221 222 void set_selectProfile() { 223 menu_T menu = anki_to_menu(anki_get_profiles, profile_selected, stop); 224 data_T data = data_new(menu, menu_hadleInput); 225 widget_setData(&mainMenu_widget, data); 226 } 227 228 void set_selectDeck() { 229 menu_T menu = anki_to_menu(anki_get_decks, deck_selected, set_selectProfile); 230 data_T data = data_new(menu, menu_hadleInput); 231 widget_setData(&mainMenu_widget, data); 232 } 233 234 int main(void) { 235 start(); 236 { 237 set_selectProfile(); 238 widget_activate(&mainMenu_widget, MAIN); 239 pane_event_loop(); 240 } 241 stop(); 242 243 return 0; 244 } 245 246 void stop(void) { 247 anki_stop(); 248 pane_stop(); 249 exit(1); 250 } 251 252 void start(void) { 253 struct tb_event ev; 254 char message[] = "Can't start anki, make sure it's running and try again"; 255 256 pane_start(0); 257 data_T data = data_new(message, NULL); 258 widget_setData(&error_widget, data); 259 widget_activate(&error_widget, MAIN); 260 261 TRY { anki_start(); } 262 EXCEPT(ANKIE_CONNECT) { 263 error_widget.callback(&error_widget); 264 tb_poll_event(&ev); 265 if (ev.ch == 'q' || ev.key == TB_KEY_ESC) 266 stop(); 267 start(); 268 } 269 ELSE { 270 stop(); 271 RERAISE; 272 } 273 END_TRY; 274 }