aboutsummaryrefslogtreecommitdiff
path: root/main.c
blob: 4f2b4912b8395fb98cc78e6d50e588e7953a2ee4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* main.c - argument handling and wire-up. */
#include "config.h"
#include "core.h"
#include "platform.h"

#include <stdio.h>
#include <string.h>

/* 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;
}