/* main.c - argument handling and wire-up. */ #include "config.h" #include "core.h" #include "platform.h" #include #include /* Canonical version lives in the Makefile (VERSION), injected via -D; a * release build stamps the git tag in that way. */ #ifndef MOUSEBOARD_VERSION #define MOUSEBOARD_VERSION "0-dev" #endif static const char usage[] = "usage: mouseboard [options]\n" "\n" "Draw a labelled grid, type a label to pick a cell, refine by\n" "bisection (u/i/j/k), then click (m=left , =middle .=right ;=double\n" "v=drag). Esc cancels, Backspace undoes.\n" "\n" " --config PATH config file (default $XDG_CONFIG_HOME/mouseboard/config)\n" " --cell-size N target coarse-cell size in pixels\n" " --cols N --rows N explicit grid instead of cell-size\n" " --alphabet STR label characters\n" " --opacity N backdrop opacity 0..100 (100 = solid)\n" " --opacity-fg N label/grid/crosshair opacity 0..100\n" " --dry-run print 'x y action' instead of clicking\n" " --selftest run offline logic checks and exit\n" " -h, --help this help\n" " -V, --version version\n"; /* Flags taking a value; each one sets a config key. */ static const struct { const char *flag, *key; } opts[] = { { "--cell-size", "cell_size" }, { "--cols", "cols" }, { "--rows", "rows" }, { "--alphabet", "alphabet" }, { "--opacity", "opacity_bg" }, { "--opacity-fg", "opacity_fg" }, }; int main(int argc, char **argv) { platform_early_init(); struct config cfg; config_defaults(&cfg); const char *cfgpath = NULL; /* set only by --config */ int dry = 0; /* Pass 1: handle exit-early flags and locate the config path. */ for (int i = 1; i < argc; i++) { const char *a = argv[i]; if (!strcmp(a, "-h") || !strcmp(a, "--help")) { fputs(usage, stdout); return 0; } if (!strcmp(a, "-V") || !strcmp(a, "--version")) { printf("mouseboard %s\n", MOUSEBOARD_VERSION); return 0; } if (!strcmp(a, "--selftest")) return core_selftest(); if (!strcmp(a, "--config")) { if (++i >= argc) { fprintf(stderr, "mouseboard: %s needs an argument\n", a); return 2; } cfgpath = argv[i]; } } /* Load the file (CLI flags below override it). */ int lr = config_load_file(&cfg, cfgpath ? cfgpath : config_default_path()); if (lr == -1 && cfgpath) { fprintf(stderr, "mouseboard: %s: not found\n", cfgpath); return 2; } if (lr == -2) return 2; /* Pass 2: apply CLI overrides. */ for (int i = 1; i < argc; i++) { const char *a = argv[i]; if (!strcmp(a, "--config")) { i++; continue; } if (!strcmp(a, "--dry-run")) { dry = 1; continue; } const char *key = NULL; for (size_t o = 0; o < sizeof opts / sizeof opts[0]; o++) if (!strcmp(a, opts[o].flag)) key = opts[o].key; if (!key) { fprintf(stderr, "mouseboard: unknown option %s\n", a); fputs(usage, stderr); return 2; } if (++i >= argc) { fprintf(stderr, "mouseboard: %s needs an argument\n", a); return 2; } if (config_set(&cfg, key, argv[i])) { fprintf(stderr, "mouseboard: %s: bad value '%s'\n", a, argv[i]); return 2; } } const char *invalid = config_validate(&cfg); if (invalid) { fprintf(stderr, "mouseboard: invalid configuration: %s\n", invalid); return 2; } config_apply_opacity(&cfg); struct platform *p = platform_init(); if (!p) return 2; int rc = core_run(p, &cfg, dry); p->teardown(p); return rc; }