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
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");
120 "incfat <num> Increase fatness of vertex <num> by 1\n");
122 "decfat <num> Decrease fatness of vertex <num> by 1\n");
123 printf("save <str> Write quiver to file <str>\n");
124 printf("load <str> Load quiver from file <str>\n");
125 printf("quit Quit\n");
127 "------------------------------------------------------------\n");
130 /* Print current quiver */
136 struct rational
*e
= 0;
137 size_t line_length
= 0;
139 printf("Vertices:\n");
140 printf("%*s | Name\n-----------\n", 4, "i");
142 for (j
= 0; j
< q
->v_num
; ++j
) {
143 printf("%*llu | %s\n", 4, (long long unsigned) j
, q
->v
[j
].name
);
147 printf("Edges (i -> j):\n");
148 line_length
= printf("%*s| ", 4, "i\\j");
150 for (j
= 0; j
< q
->v_num
; ++j
) {
151 line_length
+= printf("%*llu", 5, (long long unsigned) j
);
156 for (j
= 0; j
< line_length
; ++j
) {
160 for (i
= 0; i
< q
->v_num
; ++i
) {
161 printf("\n %*llu| ", 3, (long long unsigned) i
);
163 for (j
= 0; j
< q
->v_num
; ++j
) {
164 e
= &(q
->e
[i
* q
->v_len
+ j
]);
167 printf("%*s", 5, "");
168 } else if (e
->q
== 1) {
169 printf("%*lld", 5, (long long int) e
->p
);
171 printf("%*lld/%llu", 3, (long long int) e
->p
,
172 (long long unsigned) e
->q
);
181 /* Check for `help' */
183 check_help(char *buf
)
185 return strcmp(buf
, "help");
188 /* Check for `print' */
190 check_print(char *buf
)
192 return strcmp(buf
, "print");
195 /* Check for `quit' */
197 check_quit(char *buf
)
199 return strcmp(buf
, "quit");
202 /* Check for `mutate' */
204 check_mutate(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
209 if (strncmp(buf
, "mutate", 6)) {
215 if (sscanf(buf
, "mutate %zu%c", &i
, &dummy
) != 1) {
216 printf("Type `help' to see how to use `mutate'\n");
222 printf("Cannot mutate at %zu: not in quiver\n", i
);
227 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
232 /* Check for `mutatename' */
234 check_mutatename(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
241 if (!(s
= malloc(1024))) {
246 if (strncmp(buf
, "mutatename", 10)) {
252 if (sscanf(buf
, "mutatename %1023s %c", s
, &dummy
) != 1) {
253 printf("Type `help' to see how to use `mutatename'\n");
257 for (size_t j
= 0; j
< q
->v_num
; ++j
) {
258 if (!(strcmp(q
->v
[j
].name
, s
))) {
265 printf("Cannot mutate at %s: not in quiver\n", s
);
270 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
277 /* Check for `delete' */
279 check_delete(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
285 if (strncmp(buf
, "delete", 6)) {
290 int r
= sscanf(buf
, "delete %zu %zu%c", &i
, &j
, &dummy
);
294 printf("Type `help' to see how to use `delete'\n");
301 printf("Cannot delete %zu: not in quiver\n", i
);
305 *e
= (struct ui_event
) { .type
= ET_DELETE_VERTEX
,
312 "Cannot delete edges between %zu and %zu: not in quiver\n",
317 *e
= (struct ui_event
) { .type
= ET_DELETE_EDGE
,
318 .idx_1
= i
, .idx_2
= j
};
325 /* Check for `vertex' */
327 check_vertex(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
333 if (!(s
= malloc(1024))) {
338 if (strncmp(buf
, "vertex", 6)) {
344 if (sscanf(buf
, "vertex %1023s %c", s
, &dummy
) != 1) {
345 printf("Type `help' to see how to use `vertex'\n");
349 *e
= (struct ui_event
) { .type
= ET_NEW_VERTEX
, .z
= 0x8282b2, .str
=
361 /* Check for `edge' */
363 check_edge(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
372 if (strncmp(buf
, "edge", 4)) {
377 int r
= sscanf(buf
, "edge %zu %zu %d %c %d%c", &i
, &j
, &a
, &slash
, &b
,
384 printf("Type `help' to see how to use `edge'\n");
391 printf("Cannot add edge from %zu to %zu: not in quiver\n", i
,
398 printf("Cannot add edge of weight %d/%d: division by zero\n", a
,
409 if (a
<= INT_FAST8_MIN
||
410 a
>= INT_FAST8_MAX
||
411 b
>= UINT_FAST8_MAX
) {
413 "Cannot add edge of weight %d/%d: representation out of range\n",
419 *e
= (struct ui_event
) { .type
= ET_NEW_EDGE
, .idx_1
= i
, .idx_2
= j
,
425 /* Check for `rename' */
427 check_rename(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
434 if (!(s
= malloc(1024))) {
439 if (strncmp(buf
, "rename", 6)) {
445 if (sscanf(buf
, "rename %zu %1023s %c", &i
, s
, &dummy
) != 2) {
446 printf("Type `help' to see how to use `rename'\n");
451 printf("Cannot rename %zu: not in quiver\n", i
);
456 *e
= (struct ui_event
) { .type
= ET_RENAME
, .idx_1
= i
, .str
= s
};
467 /* Check for `incfat' */
469 check_incfat(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
474 if (strncmp(buf
, "incfat", 6)) {
480 if (sscanf(buf
, "incfat %zu%c", &i
, &dummy
) != 1) {
481 printf("Type `help' to see how to use `incfat'\n");
487 printf("Cannot increase fatness of %zu: not in quiver\n", i
);
492 if (q
->v
[i
].fatness
>= UINT_FAST8_MAX
) {
493 printf("Cannot increase fatness of %zu: unrepresentable\n", i
);
498 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
504 /* Check for `decfat' */
506 check_decfat(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
511 if (strncmp(buf
, "decfat", 6)) {
517 if (sscanf(buf
, "decfat %zu%c", &i
, &dummy
) != 1) {
518 printf("Type `help' to see how to use `decfat'\n");
524 printf("Cannot decrease fatness of %zu: not in quiver\n", i
);
529 if (q
->v
[i
].fatness
<= 1) {
531 "Cannot decrease fatness of %zu: fatness must be positive\n",
537 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
543 /* Check for `save' */
545 check_save(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
551 if (!(s
= malloc(1024))) {
556 if (strncmp(buf
, "save", 4)) {
562 if (sscanf(buf
, "save %1023s %c", s
, &dummy
) != 1) {
563 printf("Type `help' to see how to use `save'\n");
568 printf("Cannot save: some kind of resource allocation error\n");
573 *e
= (struct ui_event
) { .type
= ET_SAVE
, .str
= s
};
584 /* Check for `load' */
586 check_load(char *buf
, struct ui_event
*e
, uint_fast8_t *partial_match
)
591 if (!(s
= malloc(1024))) {
599 if (strncmp(buf
, "load", 4)) {
605 if (sscanf(buf
, "load %1023s %c", s
, &dummy
) != 1) {
606 printf("Type `help' to see how to use `load'\n");
612 printf("Cannot load: some kind of resource allocation error\n");
617 *e
= (struct ui_event
) { .type
= ET_LOAD
, .str
= s
};
622 /* Where the meat of this UI is. Read commands until events are needed */
624 ui_get_event(struct ui_event
*e
, uint_fast8_t *more
)
627 uint_fast8_t partial_match
= 0;
638 while (fgets(buf
, bufsize
, stdin
)) {
639 buf
[strcspn(buf
, "\n")] = '\0';
651 if (!check_help(buf
)) {
653 } else if (!check_print(buf
)) {
655 } else if (!check_quit(buf
)) {
657 } else if (!partial_match
&&
658 !check_mutatename(buf
, e
, &partial_match
)) {
660 } else if (!partial_match
&&
661 !check_mutate(buf
, e
, &partial_match
)) {
663 } else if (!partial_match
&&
664 !check_delete(buf
, e
, &partial_match
)) {
666 } else if (!partial_match
&&
667 !check_vertex(buf
, e
, &partial_match
)) {
669 } else if (!partial_match
&&
670 !check_edge(buf
, e
, &partial_match
)) {
672 } else if (!partial_match
&&
673 !check_rename(buf
, e
, &partial_match
)) {
675 } else if (!partial_match
&&
676 !check_incfat(buf
, e
, &partial_match
)) {
678 } else if (!partial_match
&&
679 !check_decfat(buf
, e
, &partial_match
)) {
681 } else if (!partial_match
&&
682 !check_save(buf
, e
, &partial_match
)) {
684 } else if (!partial_match
&&
685 !check_load(buf
, e
, &partial_match
)) {
687 } else if (!partial_match
) {
688 printf("Unknown command (try `help')\n");
695 /* ^D works like `quit' */
697 *e
= (struct ui_event
) { .type
= ET_QUIT
};