Working copy of CLI client
[clav.git] / clav.c
blob3df249304f508cc1aca57d40590a5d65086ab12a
1 /*
2 * Copyright (c) 2016, 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 state_transition(struct ui_event *e, struct quiver *q)
33 int ret = 0;
34 FILE *f = 0;
35 const char *errstr = 0;
37 switch (e->type) {
38 case ET_QUIT:
39 should_quit = 1;
40 break;
41 case ET_RENAME:
43 if (!e->str ||
44 !e->str[0] ||
45 e->idx_1 >= q->v_num) {
46 break;
47 } else if ((ret = quiver_rename_vertex(q, e->idx_1, e->str,
48 &errstr))) {
49 fprintf(stderr, "%s\n", UBSAFES(errstr));
52 ui_respond_quiver_change();
53 break;
54 case ET_SAVE:
56 if (!e->str ||
57 !e->str[0]) {
58 break;
61 if (!(f = fopen(e->str, "w"))) {
62 ret = errno;
63 perror(L("fopen"));
64 } else if ((ret = quiver_save_to_file(q, f, &errstr))) {
65 fprintf(stderr, "%s\n", UBSAFES(errstr));
68 break;
69 case ET_LOAD:
71 if (!e->str ||
72 !e->str[0]) {
73 break;
76 if (!(f = fopen(e->str, "r"))) {
77 ret = errno;
78 perror(L("fopen"));
79 } else if ((ret = quiver_load_from_file(q, f, &errstr))) {
80 fprintf(stderr, "%s\n", UBSAFES(errstr));
83 ui_respond_quiver_change();
84 break;
85 case ET_MUTATE:
87 if (e->idx_1 < q->v_num) {
88 if ((ret = quiver_mutate(q, e->idx_1, 0, &errstr))) {
89 fprintf(stderr, "%s\n", UBSAFES(errstr));
93 break;
94 case ET_NEW_VERTEX:
96 /* XXX: Allow setting name and fatness before creation */
97 if ((ret = quiver_add_vertex(q, 0, "v", 1, e->int_1, e->int_2,
98 &errstr))) {
99 fprintf(stderr, "%s\n", UBSAFES(errstr));
102 ui_respond_quiver_change();
103 break;
104 case ET_NEW_EDGE:
106 if (e->idx_1 < q->v_num &&
107 e->idx_2 < q->v_num) {
108 if ((ret = quiver_add_to_edge(q, e->idx_1, e->idx_2,
109 e->a, e->b, &errstr))) {
110 fprintf(stderr, "%s\n", UBSAFES(errstr));
114 break;
115 case ET_DELETE_VERTEX:
117 if (e->idx_1 < q->v_num) {
118 if ((ret = quiver_delete_vertex(q, e->idx_1,
119 &errstr))) {
120 fprintf(stderr, "%s\n", UBSAFES(errstr));
124 ui_respond_quiver_change();
125 break;
126 case ET_DELETE_EDGE:
128 if (e->idx_1 < q->v_num &&
129 e->idx_2 < q->v_num) {
130 size_t i12 = e->idx_1 * q->v_len + e->idx_2;
131 size_t i21 = e->idx_2 * q->v_len + e->idx_1;
133 q->e[i12] = (struct rational) { .p = 0, .q = 1 };
134 q->e[i21] = (struct rational) { .p = 0, .q = 1 };
137 break;
138 case ET_CHANGE_FATNESS:
140 if (e->idx_1 < q->v_num &&
141 q->v[e->idx_1].fatness + e->int_1 > 0 &&
142 q->v[e->idx_1].fatness + e->int_1 < UINT_FAST8_MAX) {
143 if ((ret = quiver_adjust_fatness(q, e->idx_1, e->int_1,
144 &errstr))) {
145 fprintf(stderr, "%s\n", UBSAFES(errstr));
149 break;
150 case ET_NONE:
151 break;
154 return ret;
157 /* Main loop */
158 int main(int argc, char **argv)
160 int ret;
161 struct quiver q = { 0 };
163 UNUSED(argc);
164 UNUSED(argv);
165 setlocale(LC_ALL, "");
167 if ((ret = ui_init(&q))) {
168 goto done;
171 /* Preload a basic quiver */
172 size_t va, vb, vc;
174 quiver_add_vertex(&q, &va, "A", 1, -50, 50, 0);
175 quiver_add_vertex(&q, &vb, "B", 1, 0, -75, 0);
176 quiver_add_vertex(&q, &vc, "C", 1, 75, 0, 0);
177 quiver_add_to_edge(&q, va, vb, 1, 1, 0);
178 quiver_add_to_edge(&q, vc, va, 1, 1, 0);
180 if ((ret = ui_respond_quiver_change())) {
181 goto done;
184 if ((ret = ui_start_frame())) {
185 goto done;
188 uint_fast8_t more_evs = 0;
189 struct ui_event e = { 0 };
191 while (!should_quit) {
192 /* includes framelimiting delay */
193 if ((ret = ui_finish_frame())) {
194 goto done;
197 more_evs = 1;
199 while (more_evs) {
200 if ((ret = ui_get_event(&e, &more_evs))) {
201 goto done;
204 if (e.type) {
205 state_transition(&e, &q);
209 if ((ret = ui_start_frame())) {
210 goto done;
214 done:
215 ui_teardown();
217 return ret;