There is a sign flip in how [BFZIII], Remark 2.4 should be implemented
[clav.git] / clav.c
blob611e879a8277c3c25389432faa0abc4521e13279
1 /*
2 * Copyright (c) 2018, 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 <stdint.h>
21 #include <stdio.h>
23 #include "macros.h"
24 #include "quiver.h"
25 #include "ui.h"
27 /* Quit yet? */
28 static uint_fast8_t should_quit = 0;
30 /* Having received some kind of input, change state accordingly */
31 static int
32 state_transition(struct ui_event *e, struct quiver *q)
34 int ret = 0;
35 FILE *f = 0;
36 const char *errstr = 0;
38 switch (e->type) {
39 case ET_QUIT:
40 should_quit = 1;
41 break;
42 case ET_RENAME:
44 if (!e->str ||
45 !e->str[0] ||
46 e->idx_1 >= q->v_num) {
47 break;
48 } else if ((ret = quiver_rename_vertex(q, e->idx_1, e->str,
49 &errstr))) {
50 fprintf(stderr, "%s\n", UBSAFES(errstr));
53 ui_respond_quiver_change();
54 break;
55 case ET_SAVE:
57 if (!e->str ||
58 !e->str[0]) {
59 break;
62 if (!(f = fopen(e->str, "w"))) {
63 ret = errno;
64 perror(L("fopen"));
65 } else if ((ret = quiver_save_to_file(q, f, &errstr))) {
66 fprintf(stderr, "%s\n", UBSAFES(errstr));
67 } else {
68 ui_respond_successful_save(e->str);
71 break;
72 case ET_LOAD:
74 if (!e->str ||
75 !e->str[0]) {
76 break;
79 if (!(f = fopen(e->str, "r"))) {
80 ret = errno;
81 perror(L("fopen"));
82 } else if ((ret = quiver_load_from_file(q, f, &errstr))) {
83 fprintf(stderr, "%s\n", UBSAFES(errstr));
84 } else {
85 ui_respond_successful_load(e->str);
88 ui_respond_quiver_change();
89 break;
90 case ET_MUTATE:
92 if (e->idx_1 < q->v_num) {
93 if ((ret = quiver_mutate(q, e->idx_1, 0, &errstr))) {
94 fprintf(stderr, "%s\n", UBSAFES(errstr));
98 break;
99 case ET_NEW_VERTEX:
101 if (!e->str ||
102 !e->str[0]) {
103 break;
106 if ((ret = quiver_add_vertex(q, 0, e->str, 1, e->int_1,
107 e->int_2, e->z, &errstr))) {
108 fprintf(stderr, "%s\n", UBSAFES(errstr));
111 ui_respond_quiver_change();
112 break;
113 case ET_NEW_EDGE:
115 if (e->idx_1 < q->v_num &&
116 e->idx_2 < q->v_num) {
117 if ((ret = quiver_add_to_edge(q, e->idx_1, e->idx_2,
118 e->a, e->b, &errstr))) {
119 fprintf(stderr, "%s\n", UBSAFES(errstr));
123 break;
124 case ET_DELETE_VERTEX:
126 if (e->idx_1 < q->v_num) {
127 if ((ret = quiver_delete_vertex(q, e->idx_1,
128 &errstr))) {
129 fprintf(stderr, "%s\n", UBSAFES(errstr));
133 ui_respond_quiver_change();
134 break;
135 case ET_DELETE_EDGE:
137 if (e->idx_1 < q->v_num &&
138 e->idx_2 < q->v_num) {
139 size_t i12 = e->idx_1 * q->v_len + e->idx_2;
140 size_t i21 = e->idx_2 * q->v_len + e->idx_1;
142 q->e[i12] = (struct rational) { .p = 0, .q = 1 };
143 q->e[i21] = (struct rational) { .p = 0, .q = 1 };
146 break;
147 case ET_CHANGE_FATNESS:
149 if (e->idx_1 < q->v_num &&
150 q->v[e->idx_1].fatness + e->int_1 > 0 &&
151 q->v[e->idx_1].fatness + e->int_1 < UINT_FAST8_MAX) {
152 if ((ret = quiver_adjust_fatness(q, e->idx_1, e->int_1,
153 &errstr))) {
154 fprintf(stderr, "%s\n", UBSAFES(errstr));
158 break;
159 case ET_CHANGE_COLOR:
161 if (e->idx_1 < q->v_num) {
162 if ((ret = quiver_color_vertex(q, e->idx_1, e->z,
163 &errstr))) {
164 fprintf(stderr, "%s\n", UBSAFES(errstr));
168 break;
169 case ET_NONE:
170 break;
173 if (f) {
174 fclose(f);
177 return ret;
180 /* Main loop */
182 main(int argc, char **argv)
184 int ret;
185 struct quiver q = { 0 };
187 UNUSED(argc);
188 UNUSED(argv);
189 setlocale(LC_ALL, "");
191 if ((ret = ui_init(&q))) {
192 goto done;
195 /* Preload a basic quiver */
196 size_t va, vb, vc;
198 quiver_add_vertex(&q, &va, "A", 1, -50, 50, 0x008282b2, 0);
199 quiver_add_vertex(&q, &vb, "B", 1, 0, -75, 0x008282b2, 0);
200 quiver_add_vertex(&q, &vc, "C", 1, 75, 0, 0x008282b2, 0);
201 quiver_add_to_edge(&q, va, vb, 1, 1, 0);
202 quiver_add_to_edge(&q, vc, va, 1, 1, 0);
204 if ((ret = ui_respond_quiver_change())) {
205 goto done;
208 if ((ret = ui_start_frame())) {
209 goto done;
212 uint_fast8_t more_evs = 0;
213 struct ui_event e = { 0 };
215 while (!should_quit) {
216 /* includes framelimiting delay */
217 if ((ret = ui_finish_frame())) {
218 goto done;
221 more_evs = 1;
223 while (more_evs) {
224 if ((ret = ui_get_event(&e, &more_evs))) {
225 goto done;
228 if (e.type) {
229 state_transition(&e, &q);
233 if ((ret = ui_start_frame())) {
234 goto done;
238 done:
239 ui_teardown();
240 quiver_clean(&q);
242 return ret;