From d386a5b022c81ae8a461c3bc98f963036410fcfa Mon Sep 17 00:00:00 2001 From: girst Date: Fri, 4 Jan 2019 19:16:27 +0100 Subject: [PATCH] add signal handler, atexit, more vimkeys --- README.md | 5 ++-- sol.c | 84 ++++++++++++++++++++++++++++++++++++++++++------------- sol.h | 8 +++++- 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6ace998..af75da8 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,9 @@ play klondike and spider solitaire in your unicode terminal. * TODO: undo: - insert append_undo() in x2y() functions - to encode stack position we need to overload `f.u.n` as index. - * TODO: sigint, sigcont handler! atexit() to avoid inconsistent term state * TODO: cleanup: in `x2y()` functions there is a lot of replication and noise when calculating legal moves, top cards, etc. ### P3 - * TODO: hjkl keyboard mode * TODO: mouse mode * TODO: extreme overlapping: if we are printing a sequence or multiple face down cards, only print `.overlap` lines of the ends, and `1` line for the @@ -38,6 +36,9 @@ play klondike and spider solitaire in your unicode terminal. Cannot reproduce, removed check * DONE: some input functions are in `x2y()` -- move them to `get_cmd()` (req. for mouse, hjkl modes) + * DONE: sigint, sigcont handler! atexit() to avoid inconsistent term state + * DONE: hjkl keyboard mode + * DONE: more vim mode keys (first/last tableu) ## Notes diff --git a/sol.c b/sol.c index 83c7001..12006e3 100644 --- a/sol.c +++ b/sol.c @@ -1,5 +1,7 @@ #define _DEFAULT_SOURCE +#define _POSIX_C_SOURCE /* for sigaction */ #include +#include #include #include #include @@ -118,7 +120,9 @@ int main(int argc, char** argv) { } } - //TODO: signal setup, atexit() + signal_setup(); + atexit (*quit); + newgame: screen_setup(1); @@ -127,14 +131,10 @@ newgame: case GAME_WON: print_table(NO_HI, NO_HI); win_anim(); - if (getchar()=='q') goto quit; + if (getchar()=='q') return 0; goto newgame; - case GAME_QUIT: goto quit; + case GAME_QUIT: return 0; } - -quit: - screen_setup(0); //TODO: handled by atexit() in the future - return 0; } int sol(void) { @@ -151,6 +151,9 @@ int sol(void) { case WON: return GAME_WON; } break; + case CMD_HINT: //TODO: show a possible (and sensible) move + case CMD_HELP: //TODO: display keyhelp + case CMD_JOIN: //TODO: join any pile to here case CMD_INVAL: visbell(); break; case CMD_NEW: return GAME_NEW; case CMD_QUIT: return GAME_QUIT; @@ -159,6 +162,11 @@ int sol(void) { } } +void quit(void) { + screen_setup(0); + //TODO: free undo data structures +} + int find_top(card_t* pile) { int i; for(i=PILE_SIZE-1; i>=0 && !pile[i]; i--); @@ -338,9 +346,6 @@ void remove_if_complete (card_t* pile) { //TODO: cleanup } } int t2t(int from, int to, int opt) { //TODO: in dire need of cleanup - //TODO: segfaulted once on large column - //TODO: sometimes moving doesn't work (ERR when it should be OK) XXX - int top_from = find_top(f.t[from]); int top_to = find_top(f.t[to]); int empty_to = (top_to < 0)? opt: -1; /* empty pile? */ @@ -454,7 +459,12 @@ void cursor_right (struct cursor* cursor) { if (cursor->pile < TAB_MAX) cursor->pile++; cursor->opt = 0; } -#endif //}}} +#endif +void cursor_to (struct cursor* cursor, int pile) { + cursor->pile = pile; + cursor->opt = 0; +} +//}}} #pragma GCC diagnostic pop int get_cmd (int* from, int* to, int* opt) { //TODO: escape sequences (mouse, cursor keys) @@ -494,8 +504,9 @@ from_l: print_table(&active, &inactive); case 'j': cursor_down (&active); goto from_l; case 'k': cursor_up (&active); goto from_l; case 'l': cursor_right(&active); goto from_l; - //TODO: first/last tableu (H/L? 0/^/$?) - //TODO: real cursor keys + case 'H': cursor_to(&active,TAB_1); goto from_l; /* leftmost tableu */ + case 'L': cursor_to(&active,TAB_MAX);goto from_l; /* rigthmost tableu */ + //TODO: real cursor keys, home/end case ' ': /* continue with second cursor */ *from = active.pile; if (*from == STOCK) { @@ -509,11 +520,11 @@ from_l: print_table(&active, &inactive); break; /* misc keys: */ case 'q': return CMD_QUIT; - case 'r': return CMD_NEW; //TODO - case 'H': return CMD_HINT; //TODO - case '?': return CMD_HELP; //TODO - case '/': return CMD_FIND; //TODO: highlight card of given rank (even non-movable) - case '\033': return CMD_INVAL; //TODO: cntlseq + case 'r': return CMD_NEW; + case 'J': return CMD_JOIN; + case 'K': return CMD_HINT; + case '?': return CMD_HELP; + case EOF: return CMD_NONE; /* sent by SIGCONT */ default: return CMD_INVAL; } inactive.pile = *from; /* for direct addressing highlighting */ @@ -528,9 +539,15 @@ to_l: print_table(&active, &inactive); case 'j': cursor_down (&active); goto to_l; case 'k': cursor_up (&active); goto to_l; case 'l': cursor_right(&active); goto to_l; + case 'H': cursor_to(&active,TAB_1); goto to_l; + case 'L': cursor_to(&active,TAB_MAX);goto to_l; + case 'J': /* fallthrough; key makes no sense on destination */ case ' ': *to = active.pile; break; /* continues with the foundation/empty tableu check */ + case 'K': return CMD_HELP; + case 'G'&0x1f: return CMD_NONE; /* cancel move with ^G */ + case EOF: return CMD_NONE; /* sent by SIGCONT */ default: if (t < '0' || t > '9') return CMD_INVAL; if (t == '0') @@ -794,7 +811,7 @@ void screen_setup (int enable) { } } -void raw_mode(int enable) { //{{{ +void raw_mode(int enable) { static struct termios saved_term_mode; struct termios raw_term_mode; @@ -808,6 +825,33 @@ void raw_mode(int enable) { //{{{ } else { tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_term_mode); } -} //}}} +} + +void signal_handler (int signum) { + switch (signum) { + case SIGCONT: + screen_setup(0); + screen_setup(1); + print_table(NO_HI, NO_HI); + break; + case SIGINT: + exit(128+SIGINT); + } +} +void signal_setup(void) { + struct sigaction saction; + + saction.sa_handler = signal_handler; + sigemptyset(&saction.sa_mask); + saction.sa_flags = 0; + if (sigaction(SIGCONT, &saction, NULL) < 0) { + perror ("SIGCONT"); + exit (1); + } + if (sigaction(SIGINT, &saction, NULL) < 0) { + perror ("SIGINT"); + exit (1); + } +} //vim: foldmethod=marker diff --git a/sol.h b/sol.h index 2a787da..31e3820 100644 --- a/sol.h +++ b/sol.h @@ -22,6 +22,9 @@ #define KEYHELP \ "Keybindings:\n" \ " hjkl : move cursor\n" \ + " H, L : move cursor to first/last tableu pile\n" \ + " J, K : join to here, show hint\n" \ + " r, q : new game, quit\n" \ " space : select at cursor\n" \ " return: draw from stock\n" \ DIRECT_ADDR_KEYHELP @@ -115,7 +118,7 @@ enum special_cmds { CMD_NEW, CMD_HINT, CMD_HELP, - CMD_FIND, + CMD_JOIN, }; enum difficulty { @@ -134,6 +137,7 @@ const struct cursor no_hi = {-1, -1}; #define NO_HI &no_hi int sol(void); +void quit(void); int find_top(card_t* pile); int first_movable(card_t* pile); void turn_over(card_t* pile); @@ -164,5 +168,7 @@ void visbell (void); void append_undo (int n, int f, int t); void screen_setup (int enable); void raw_mode(int enable); +void signal_handler (int signum); +void signal_setup(void); #endif -- 2.39.3