Reformat
[clav.git] / clav.c
blob34835e9a70cd3abf38256f79774fe6d094bf1e9e
1 /*
2 * Copyright (c) 2016-2019, S. Gilles <sgilles@math.umd.edu>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
7 * in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <errno.h>
19 #include <locale.h>
20 #include <stdarg.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <unistd.h>
25 #include "macros.h"
26 #include "quiver.h"
27 #include "ui.h"
29 /* Quit yet? */
30 static uint_fast8_t should_quit = 0;
32 /* if (verbose) printf(...); */
33 static void
34 history(int verbose, const char *format, ...)
36 va_list arglist;
38 if (!verbose) {
39 return;
42 printf("action: ");
43 va_start(arglist, format);
44 vprintf(format, arglist);
45 va_end(arglist);
46 printf("\n");
49 /* Having received some kind of input, change state accordingly */
50 static int
51 state_transition(struct ui_event *e, struct quiver *q, int verbose)
53 int ret = 0;
54 FILE *f = 0;
55 const char *errstr = 0;
57 switch (e->type) {
58 case ET_QUIT:
59 should_quit = 1;
60 history(verbose, "quit");
61 break;
62 case ET_RENAME:
64 if (!e->str ||
65 !e->str[0] ||
66 e->idx_1 >= q->v_num) {
67 break;
70 history(verbose, "rename \"%s\" to \"%s\"", q->v[e->idx_1].name,
71 e->str);
73 if ((ret = quiver_rename_vertex(q, e->idx_1, e->str,
74 &errstr))) {
75 fprintf(stderr, "%s\n", UBSAFES(errstr));
78 ui_respond_quiver_change();
79 break;
80 case ET_SAVE:
82 if (!e->str ||
83 !e->str[0]) {
84 break;
87 history(verbose, "save to \"%s\"", e->str);
89 if (!(f = fopen(e->str, "w"))) {
90 ret = errno;
91 perror(L("fopen"));
92 } else if ((ret = quiver_save_to_file(q, f, &errstr))) {
93 fprintf(stderr, "%s\n", UBSAFES(errstr));
94 } else {
95 ui_respond_successful_save(e->str);
98 break;
99 case ET_LOAD:
101 if (!e->str ||
102 !e->str[0]) {
103 break;
106 history(verbose, "load from \"%s\"", e->str);
108 if (!(f = fopen(e->str, "r"))) {
109 ret = errno;
110 perror(L("fopen"));
111 } else if ((ret = quiver_load_from_file(q, f, &errstr))) {
112 fprintf(stderr, "%s\n", UBSAFES(errstr));
113 } else {
114 ui_respond_successful_load(e->str);
117 ui_respond_quiver_change();
118 break;
119 case ET_MUTATE:
121 if (e->idx_1 < q->v_num) {
122 history(verbose, "mutate at \"%s\" (%zu)",
123 q->v[e->idx_1].name, e->idx_1);
125 if ((ret = quiver_mutate(q, e->idx_1, 0, &errstr))) {
126 fprintf(stderr, "%s\n", UBSAFES(errstr));
130 break;
131 case ET_NEW_VERTEX:
133 if (!e->str ||
134 !e->str[0]) {
135 break;
138 history(verbose, "new vertex \"%s\" at (%d, %d)", e->str,
139 e->int_1, e->int_2);
141 if ((ret = quiver_add_vertex(q, 0, e->str, 1, e->int_1,
142 e->int_2, e->z, &errstr))) {
143 fprintf(stderr, "%s\n", UBSAFES(errstr));
146 ui_respond_quiver_change();
147 break;
148 case ET_NEW_EDGE:
150 if (e->idx_1 < q->v_num &&
151 e->idx_2 < q->v_num) {
152 history(verbose,
153 "add edge from \"%s\" (%zu) to \"%s\" (%zu), weight %d/%d",
154 q->v[e->idx_1].name, e->idx_1,
155 q->v[e->idx_2].name,
156 e->idx_2, (int) e->a, (int) e->b);
158 if ((ret = quiver_add_to_edge(q, e->idx_1, e->idx_2,
159 e->a, e->b, &errstr))) {
160 fprintf(stderr, "%s\n", UBSAFES(errstr));
164 break;
165 case ET_DELETE_VERTEX:
167 if (e->idx_1 < q->v_num) {
168 history(verbose, "delete vertex \"%s\" (%zu)",
169 q->v[e->idx_1].name, e->idx_1);
171 if ((ret = quiver_delete_vertex(q, e->idx_1,
172 &errstr))) {
173 fprintf(stderr, "%s\n", UBSAFES(errstr));
177 ui_respond_quiver_change();
178 break;
179 case ET_DELETE_EDGE:
181 if (e->idx_1 < q->v_num &&
182 e->idx_2 < q->v_num) {
183 size_t i12 = e->idx_1 * q->v_len + e->idx_2;
184 size_t i21 = e->idx_2 * q->v_len + e->idx_1;
186 history(verbose,
187 "remove edge between \"%s\" (%zu) and \"%s\" (%zu)",
188 q->v[e->idx_1].name, e->idx_1,
189 q->v[e->idx_2].name,
190 e->idx_2);
191 q->e[i12] = (struct rational) { .p = 0, .q = 1 };
192 q->e[i21] = (struct rational) { .p = 0, .q = 1 };
195 break;
196 case ET_CHANGE_FATNESS:
198 if (e->idx_1 < q->v_num &&
199 q->v[e->idx_1].fatness + e->int_1 > 0 &&
200 q->v[e->idx_1].fatness + e->int_1 < UINT_FAST8_MAX) {
201 history(verbose,
202 "change fatness of vertex \"%s\" (%zu) to %d",
203 q->v[e->idx_1].name, e->idx_1,
204 q->v[e->idx_1].fatness +
205 e->int_1);
207 if ((ret = quiver_adjust_fatness(q, e->idx_1, e->int_1,
208 &errstr))) {
209 fprintf(stderr, "%s\n", UBSAFES(errstr));
213 break;
214 case ET_CHANGE_COLOR:
216 if (e->idx_1 < q->v_num) {
217 history(verbose,
218 "change color of vertex \"%s\" (%zu) to %#010lx",
219 q->v[e->idx_1].name, e->idx_1, (long int) e->z);
221 if ((ret = quiver_color_vertex(q, e->idx_1, e->z,
222 &errstr))) {
223 fprintf(stderr, "%s\n", UBSAFES(errstr));
227 break;
228 case ET_NONE:
229 break;
232 if (f) {
233 fclose(f);
236 return ret;
239 /* Main loop */
241 main(int argc, char **argv)
243 int ret = 1;
244 struct quiver q = { 0 };
245 int opt;
246 int verbose = 0;
247 const char *initial_file = 0;
249 UNUSED(argc);
250 UNUSED(argv);
251 setlocale(LC_ALL, "");
253 while ((opt = getopt(argc, argv, "vf:")) != -1) {
254 switch (opt) {
255 case 'v':
256 verbose = 1;
257 break;
258 case 'f':
259 initial_file = optarg;
260 break;
264 if ((ret = ui_init(&q))) {
265 goto done;
268 /* Preload a basic quiver */
269 if (initial_file) {
270 FILE *f = 0;
272 if ((f = fopen(initial_file, "r"))) {
273 if (!(quiver_load_from_file(&q, f, 0))) {
274 if ((ret = ui_respond_successful_load(
275 initial_file))) {
276 goto done;
280 fclose(f);
282 } else {
283 size_t va, vb, vc;
285 quiver_add_vertex(&q, &va, "A", 1, -50, 50, 0x008282b2, 0);
286 quiver_add_vertex(&q, &vb, "B", 1, 0, -75, 0x008282b2, 0);
287 quiver_add_vertex(&q, &vc, "C", 1, 75, 0, 0x008282b2, 0);
288 quiver_add_to_edge(&q, va, vb, 1, 1, 0);
289 quiver_add_to_edge(&q, vc, va, 1, 1, 0);
292 if ((ret = ui_respond_quiver_change())) {
293 goto done;
296 if ((ret = ui_start_frame())) {
297 goto done;
300 uint_fast8_t more_evs = 0;
301 struct ui_event e = { 0 };
303 while (!should_quit) {
304 /* includes framelimiting delay */
305 if ((ret = ui_finish_frame())) {
306 goto done;
309 more_evs = 1;
311 while (more_evs) {
312 if ((ret = ui_get_event(&e, &more_evs))) {
313 goto done;
316 if (e.type) {
317 state_transition(&e, &q, verbose);
321 if ((ret = ui_start_frame())) {
322 goto done;
326 done:
327 ui_teardown();
328 quiver_clean(&q);
330 return ret;