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
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.
28 /* Do special things on first frame */
29 static uint_fast8_t first_time
= 1;
34 /* Max line length to accept as command */
35 static size_t bufsize
= 1 << 11;
37 /* Memory which must be passed back to clav.c, then freed */
38 static void *free_this
= 0;
42 ui_init(struct quiver
*i_q
)
49 /* Acknowledge a successful load */
51 ui_respond_successful_load(const char *filename
)
53 printf("Loaded %s\n", filename
);
58 /* Acknowledge a successful save */
60 ui_respond_successful_save(const char *filename
)
62 printf("Saved to %s\n", filename
);
67 /* Deal with the fact that the quiver was changed */
69 ui_respond_quiver_change(void)
86 /* Record that a frame has been started */
93 /* Draw a frame, sleep to framelimit */
105 "------------------------------------------------------------\n");
106 printf("help This message\n");
107 printf("print Display the quiver\n");
108 printf("mutate <num> Mutate at <num>\n");
110 "mutatename <str> Mutate at vertex with name <str>\n");
111 printf("delete <num> Delete vertex <num>\n");
113 "delete <num1> <num2> Delete edges between <num> and <num>\n");
115 "vertex <v> Create vertex with name <v>, fatness 1\n");
117 "edge <num1> <num2> <p>/<q> Add an edge from <num> to <num>, weight <p>/<q>\n");
118 printf("rename <num> <str> Rename vertex <num> to <str>\n");
119 printf("renamename <str1> <str2> Rename vertex <str1> to <str2>\n");
121 "incfat <num> Increase fatness of vertex <num> by 1\n");
123 "decfat <num> Decrease fatness of vertex <num> by 1\n");
124 printf("save <str> Write quiver to file <str>\n");
125 printf("load <str> Load quiver from file <str>\n");
126 printf("quit Quit\n");
128 "------------------------------------------------------------\n");
131 /* Print current quiver */
137 struct rational
*e
= 0;
138 size_t line_length
= 0;
140 printf("Vertices:\n");
141 printf("%*s | Name\n-----------\n", 4, "i");
143 for (j
= 0; j
< q
->v_num
; ++j
) {
144 printf("%*llu | %s\n", 4, (long long unsigned) j
, q
->v
[j
].name
);
148 printf("Edges (i -> j):\n");
149 line_length
= printf("%*s| ", 4, "i\\j");
151 for (j
= 0; j
< q
->v_num
; ++j
) {
152 line_length
+= printf("%*llu", 5, (long long unsigned) j
);
157 for (j
= 0; j
< line_length
; ++j
) {
161 for (i
= 0; i
< q
->v_num
; ++i
) {
162 printf("\n %*llu| ", 3, (long long unsigned) i
);
164 for (j
= 0; j
< q
->v_num
; ++j
) {
165 e
= &(q
->e
[i
* q
->v_len
+ j
]);
168 printf("%*s", 5, "");
169 } else if (e
->q
== 1) {
170 printf("%*lld", 5, (long long int) e
->p
);
172 printf("%*lld/%llu", 3, (long long int) e
->p
,
173 (long long unsigned) e
->q
);
182 /* Check for `help' */
184 check_help(char *buf
)
186 return strcmp(buf
, "help");
189 /* Check for `print' */
191 check_print(char *buf
)
193 return strcmp(buf
, "print");
196 /* Check for `quit' */
198 check_quit(char *buf
)
200 return strcmp(buf
, "quit");
203 /* Check for `mutate' */
205 check_mutate(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
210 if (strncmp(buf
, "mutate", 6)) {
216 if (sscanf(buf
, "mutate %zu%c", &i
, &dummy
) != 1) {
217 printf("Type `help' to see how to use `mutate'\n");
223 printf("Cannot mutate at %zu: not in quiver\n", i
);
228 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
233 /* Check for `mutatename' */
235 check_mutatename(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
242 if (!(s
= malloc(1024))) {
247 if (strncmp(buf
, "mutatename", 10)) {
253 if (sscanf(buf
, "mutatename %1023s %c", s
, &dummy
) != 1) {
254 printf("Type `help' to see how to use `mutatename'\n");
258 for (size_t j
= 0; j
< q
->v_num
; ++j
) {
259 if (!(strcmp(q
->v
[j
].name
, s
))) {
266 printf("Cannot mutate at %s: not in quiver\n", s
);
271 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
278 /* Check for `delete' */
280 check_delete(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
286 if (strncmp(buf
, "delete", 6)) {
291 int r
= sscanf(buf
, "delete %zu %zu%c", &i
, &j
, &dummy
);
295 printf("Type `help' to see how to use `delete'\n");
302 printf("Cannot delete %zu: not in quiver\n", i
);
306 *e
= (struct ui_event
) { .type
= ET_DELETE_VERTEX
,
313 "Cannot delete edges between %zu and %zu: not in quiver\n",
318 *e
= (struct ui_event
) { .type
= ET_DELETE_EDGE
,
319 .idx_1
= i
, .idx_2
= j
};
326 /* Check for `vertex' */
328 check_vertex(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
334 if (!(s
= malloc(1024))) {
339 if (strncmp(buf
, "vertex", 6)) {
345 if (sscanf(buf
, "vertex %1023s %c", s
, &dummy
) != 1) {
346 printf("Type `help' to see how to use `vertex'\n");
350 *e
= (struct ui_event
) { .type
= ET_NEW_VERTEX
, .z
= 0x8282b2, .str
=
362 /* Check for `edge' */
364 check_edge(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
373 if (strncmp(buf
, "edge", 4)) {
378 int r
= sscanf(buf
, "edge %zu %zu %d %c %d%c", &i
, &j
, &a
, &slash
, &b
,
385 printf("Type `help' to see how to use `edge'\n");
392 printf("Cannot add edge from %zu to %zu: not in quiver\n", i
,
399 printf("Cannot add edge of weight %d/%d: division by zero\n", a
,
410 if (a
<= INT_FAST8_MIN
||
411 a
>= INT_FAST8_MAX
||
412 b
>= UINT_FAST8_MAX
) {
414 "Cannot add edge of weight %d/%d: representation out of range\n",
420 *e
= (struct ui_event
) { .type
= ET_NEW_EDGE
, .idx_1
= i
, .idx_2
= j
,
426 /* Check for `renamename' */
428 check_renamename(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
432 uint_fast8_t seen
= 0;
438 if (!(s
= malloc(1024))) {
443 if (!(t
= malloc(1024))) {
448 if (strncmp(buf
, "renamename", 10)) {
454 if (sscanf(buf
, "renamename %1023s %1023s %c", s
, t
, &dummy
) != 2) {
455 printf("Type `help' to see how to use `renamename'\n");
459 for (j
= 0; j
< q
->v_num
; ++j
) {
460 if (!(strcmp(q
->v
[j
].name
, s
))) {
467 printf("Cannot rename %s: not in quiver\n", s
);
472 printf("Cannot rename %s: ambiguous\n", s
);
477 *e
= (struct ui_event
) { .type
= ET_RENAME
, .idx_1
= i
, .str
= t
};
490 /* Check for `rename' */
492 check_rename(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
499 if (!(s
= malloc(1024))) {
504 if (strncmp(buf
, "rename", 6)) {
510 if (sscanf(buf
, "rename %zu %1023s %c", &i
, s
, &dummy
) != 2) {
511 printf("Type `help' to see how to use `rename'\n");
516 printf("Cannot rename %zu: not in quiver\n", i
);
521 *e
= (struct ui_event
) { .type
= ET_RENAME
, .idx_1
= i
, .str
= s
};
532 /* Check for `incfat' */
534 check_incfat(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
539 if (strncmp(buf
, "incfat", 6)) {
545 if (sscanf(buf
, "incfat %zu%c", &i
, &dummy
) != 1) {
546 printf("Type `help' to see how to use `incfat'\n");
552 printf("Cannot increase fatness of %zu: not in quiver\n", i
);
557 if (q
->v
[i
].fatness
>= UINT_FAST8_MAX
) {
558 printf("Cannot increase fatness of %zu: unrepresentable\n", i
);
563 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
569 /* Check for `decfat' */
571 check_decfat(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
576 if (strncmp(buf
, "decfat", 6)) {
582 if (sscanf(buf
, "decfat %zu%c", &i
, &dummy
) != 1) {
583 printf("Type `help' to see how to use `decfat'\n");
589 printf("Cannot decrease fatness of %zu: not in quiver\n", i
);
594 if (q
->v
[i
].fatness
<= 1) {
596 "Cannot decrease fatness of %zu: fatness must be positive\n",
602 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
608 /* Check for `save' */
610 check_save(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
616 if (!(s
= malloc(1024))) {
621 if (strncmp(buf
, "save", 4)) {
627 if (sscanf(buf
, "save %1023s %c", s
, &dummy
) != 1) {
628 printf("Type `help' to see how to use `save'\n");
633 printf("Cannot save: some kind of resource allocation error\n");
638 *e
= (struct ui_event
) { .type
= ET_SAVE
, .str
= s
};
649 /* Check for `load' */
651 check_load(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
656 if (!(s
= malloc(1024))) {
664 if (strncmp(buf
, "load", 4)) {
670 if (sscanf(buf
, "load %1023s %c", s
, &dummy
) != 1) {
671 printf("Type `help' to see how to use `load'\n");
677 printf("Cannot load: some kind of resource allocation error\n");
682 *e
= (struct ui_event
) { .type
= ET_LOAD
, .str
= s
};
687 /* Where the meat of this UI is. Read commands until events are needed */
689 ui_get_event(struct ui_event
*e
, uint_fast8_t *more
)
692 uint_fast8_t partial_match
= 0;
703 while (fgets(buf
, bufsize
, stdin
)) {
704 buf
[strcspn(buf
, "\n")] = '\0';
716 if (!check_help(buf
)) {
718 } else if (!check_print(buf
)) {
720 } else if (!check_quit(buf
)) {
722 } else if (!partial_match
&&
723 !check_mutatename(buf
, e
, &partial_match
)) {
725 } else if (!partial_match
&&
726 !check_mutate(buf
, e
, &partial_match
)) {
728 } else if (!partial_match
&&
729 !check_delete(buf
, e
, &partial_match
)) {
731 } else if (!partial_match
&&
732 !check_vertex(buf
, e
, &partial_match
)) {
734 } else if (!partial_match
&&
735 !check_edge(buf
, e
, &partial_match
)) {
737 } else if (!partial_match
&&
738 !check_renamename(buf
, e
, &partial_match
)) {
740 } else if (!partial_match
&&
741 !check_rename(buf
, e
, &partial_match
)) {
743 } else if (!partial_match
&&
744 !check_incfat(buf
, e
, &partial_match
)) {
746 } else if (!partial_match
&&
747 !check_decfat(buf
, e
, &partial_match
)) {
749 } else if (!partial_match
&&
750 !check_save(buf
, e
, &partial_match
)) {
752 } else if (!partial_match
&&
753 !check_load(buf
, e
, &partial_match
)) {
755 } else if (!partial_match
) {
756 printf("Unknown command (try `help')\n");
763 /* ^D works like `quit' */
765 *e
= (struct ui_event
) { .type
= ET_QUIT
};