#include #include #include #include #include #include "doc.h" #include "err.h" #include "nav.h" /* pagination */ /* navigation */ /* commands */ struct cmd { char ch; int (*fn)(const char *); }; /* cmd is mutated when trimming strings * returns whether to quit */ int cmd_do(char *cmd, struct nav_state *ns) { switch (*cmd) { case 'q': puts("goodbye!"); return 1; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { errno = 0; unsigned long n = strtoul(cmd, NULL, 10); if (errno) { perr("invalid link number"); } else if (nav_link_nr(ns, n)) { perr("navigation failure"); } } break; case 'b': nav_pg_up(ns); break; case '\0': nav_pg_down(ns); break; case 'r': nav_redraw(ns); break; case 'g': if (nav_to(ns, cmd + 1)) perr("navigation failure"); break; case 'p': nav_prev(ns); break; case 'n': nav_next(ns); break; default: perr("?"); break; } return 0; } void cmd_trim(char *buf, size_t max) { size_t n = strlen(buf); while (n > 0 && isspace(buf[n - 1])) { buf[--n] = 0; } while (n > 1 && isspace(buf[1])) { memmove(&buf[0], &buf[1], n--); } } int cmd_get(char *buf, size_t n) { fputs("* ", stdout); return !!fgets(buf, n, stdin); } int main(int argc, const char **argv) { struct nav_state ns; char cmd_buf[1024]; nav_init(&ns); if (argc == 2) { if (nav_to(&ns, argv[1])) perr("navigation failure"); } else { nav_redraw(&ns); } while (cmd_get(cmd_buf, sizeof cmd_buf)) { cmd_trim(cmd_buf, sizeof cmd_buf); if (cmd_do(cmd_buf, &ns)) { break; } } nav_fini(&ns); return 0; }