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
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;
41 int ui_init(struct quiver
*i_q
)
48 /* Deal with the fact that the quiver was changed */
49 int ui_respond_quiver_change(void)
60 /* Record that a frame has been started */
61 int ui_start_frame(void)
66 /* Draw a frame, sleep to framelimit */
67 int ui_finish_frame(void)
73 static void print_help(void)
76 "------------------------------------------------------------\n");
77 printf("help This message\n");
78 printf("print Display the quiver\n");
79 printf("mutate <num> Mutate at <num>\n");
80 printf("delete <num> Delete vertex <num>\n");
82 "delete <num1> <num2> Delete edges between <num> and <num>\n");
84 "vertex Create vertex with name \"v\", fatness 1\n");
86 "edge <num1> <num2> <p>/<q> Add an edge from <num> to <num>, weight <p>/<q>\n");
87 printf("rename <num> <str> Rename vertex <num> to <str>\n");
89 "incfat <num> Increase fatness of vertex <num> by 1\n");
91 "decfat <num> Decrease fatness of vertex <num> by 1\n");
92 printf("save <str> Write quiver to file <str>\n");
93 printf("load <str> Load quiver from file <str>\n");
94 printf("quit Quit\n");
96 "------------------------------------------------------------\n");
99 /* Print current quiver */
100 static void print_quiver(void)
104 struct rational
*e
= 0;
105 size_t line_length
= 0;
107 printf("Vertices:\n");
108 printf("%*s | Name\n-----------\n", 4, "i");
110 for (j
= 0; j
< q
->v_num
; ++j
) {
111 printf("%*llu | %s\n", 4, (long long unsigned) j
, q
->v
[j
].name
);
115 printf("Edges (i -> j):\n");
116 line_length
= printf("%*s| ", 4, "i\\j");
118 for (j
= 0; j
< q
->v_num
; ++j
) {
119 line_length
+= printf("%*llu", 5, (long long unsigned) j
);
124 for (j
= 0; j
< line_length
; ++j
) {
128 for (i
= 0; i
< q
->v_num
; ++i
) {
129 printf("\n %*llu| ", 3, (long long unsigned) i
);
131 for (j
= 0; j
< q
->v_num
; ++j
) {
132 e
= &(q
->e
[i
* q
->v_len
+ j
]);
135 printf("%*s", 5, "");
136 } else if (e
->q
== 1) {
137 printf("%*lld", 5, (long long int) e
->p
);
139 printf("%*lld/%llu", 3, (long long int) e
->p
,
140 (long long unsigned) e
->q
);
149 /* Check for `help' */
150 static int check_help(char *buf
)
152 return strcmp(buf
, "help");
155 /* Check for `print' */
156 static int check_print(char *buf
)
158 return strcmp(buf
, "print");
161 /* Check for `quit' */
162 static int check_quit(char *buf
)
164 return strcmp(buf
, "quit");
167 /* Check for `mutate' */
168 static int check_mutate(char *buf
, struct ui_event
*e
,
169 uint_fast8_t *partial_match
)
174 if (strncmp(buf
, "mutate", 6)) {
180 if (sscanf(buf
, "mutate %zu%c", &i
, &dummy
) != 1) {
181 printf("Type `help' to see how to use `mutate'\n");
187 printf("Cannot mutate at %zu: not in quiver\n", i
);
192 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
197 /* Check for `delete' */
198 static int check_delete(char *buf
, struct ui_event
*e
,
199 uint_fast8_t *partial_match
)
205 if (strncmp(buf
, "delete", 6)) {
210 int r
= sscanf(buf
, "delete %zu %zu%c", &i
, &j
, &dummy
);
214 printf("Type `help' to see how to use `delete'\n");
221 printf("Cannot delete %zu: not in quiver\n", i
);
225 *e
= (struct ui_event
) { .type
= ET_DELETE_VERTEX
,
232 "Cannot delete edges between %zu and %zu: not in quiver\n",
237 *e
= (struct ui_event
) { .type
= ET_DELETE_EDGE
,
238 .idx_1
= i
, .idx_2
= j
};
245 /* Check for `vertex' */
246 static int check_vertex(char *buf
, struct ui_event
*e
,
247 uint_fast8_t *partial_match
)
251 if (strncmp(buf
, "vertex", 6)) {
257 if (sscanf(buf
, "vertex %c", &dummy
) != 0) {
258 printf("Type `help' to see how to use `vertex'\n");
263 /* XXX: need to allow sending in name and fatness */
264 *e
= (struct ui_event
) { .type
= ET_NEW_VERTEX
};
269 /* Check for `edge' */
270 static int check_edge(char *buf
, struct ui_event
*e
,
271 uint_fast8_t *partial_match
)
280 if (strncmp(buf
, "edge", 4)) {
285 int r
= sscanf(buf
, "edge %zu %zu %d %c %d%c", &i
, &j
, &a
, &slash
, &b
,
292 printf("Type `help' to see how to use `edge'\n");
299 printf("Cannot add edge from %zu to %zu: not in quiver\n", i
,
306 printf("Cannot add edge of weight %d/%d: division by zero\n", a
,
317 if (a
<= INT_FAST8_MIN
||
318 a
>= INT_FAST8_MAX
||
319 b
>= UINT_FAST8_MAX
) {
321 "Cannot add edge of weight %d/%d: representation out of range\n",
327 *e
= (struct ui_event
) { .type
= ET_NEW_EDGE
, .idx_1
= i
, .idx_2
= j
,
333 /* Check for `rename' */
334 static int check_rename(char *buf
, struct ui_event
*e
,
335 uint_fast8_t *partial_match
)
341 if (!(s
= malloc(1024))) {
347 if (strncmp(buf
, "rename", 6)) {
353 if (sscanf(buf
, "rename %zu %1023s %c", &i
, s
, &dummy
) != 2) {
354 printf("Type `help' to see how to use `rename'\n");
361 printf("Cannot rename %zu: not in quiver\n", i
);
369 "Cannot rename %zu: some kind of resource allocation error\n",
375 *e
= (struct ui_event
) { .type
= ET_RENAME
, .idx_1
= i
, .str
= s
};
380 /* Check for `incfat' */
381 static int check_incfat(char *buf
, struct ui_event
*e
,
382 uint_fast8_t *partial_match
)
387 if (strncmp(buf
, "incfat", 6)) {
393 if (sscanf(buf
, "incfat %zu%c", &i
, &dummy
) != 1) {
394 printf("Type `help' to see how to use `incfat'\n");
400 printf("Cannot increase fatness of %zu: not in quiver\n", i
);
405 if (q
->v
[i
].fatness
>= UINT_FAST8_MAX
) {
406 printf("Cannot increase fatness of %zu: unrepresentable\n", i
);
411 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
417 /* Check for `decfat' */
418 static int check_decfat(char *buf
, struct ui_event
*e
,
419 uint_fast8_t *partial_match
)
424 if (strncmp(buf
, "decfat", 6)) {
430 if (sscanf(buf
, "decfat %zu%c", &i
, &dummy
) != 1) {
431 printf("Type `help' to see how to use `decfat'\n");
437 printf("Cannot decrease fatness of %zu: not in quiver\n", i
);
442 if (q
->v
[i
].fatness
<= 1) {
444 "Cannot decrease fatness of %zu: fatness must be positive\n",
450 *e
= (struct ui_event
) { .type
= ET_CHANGE_FATNESS
, .idx_1
= i
, .int_1
=
456 /* Check for `save' */
457 static int check_save(char *buf
, struct ui_event
*e
,
458 uint_fast8_t *partial_match
)
463 if (!(s
= malloc(1024))) {
469 if (strncmp(buf
, "save", 4)) {
475 if (sscanf(buf
, "save %1023s %c", s
, &dummy
) != 1) {
476 printf("Type `help' to see how to use `save'\n");
483 printf("Cannot save: some kind of resource allocation error\n");
488 *e
= (struct ui_event
) { .type
= ET_SAVE
, .str
= s
};
493 /* Check for `load' */
494 static int check_load(char *buf
, struct ui_event
*e
,
495 uint_fast8_t *partial_match
)
500 if (!(s
= malloc(1024))) {
506 if (strncmp(buf
, "load", 4)) {
512 if (sscanf(buf
, "load %1023s %c", s
, &dummy
) != 1) {
513 printf("Type `help' to see how to use `load'\n");
520 printf("Cannot load: some kind of resource allocation error\n");
525 *e
= (struct ui_event
) { .type
= ET_LOAD
, .str
= s
};
530 /* Where the meat of this UI is. Read commands until events are needed */
531 int ui_get_event(struct ui_event
*e
, uint_fast8_t *more
)
534 uint_fast8_t partial_match
= 0;
550 while (fgets(buf
, bufsize
, stdin
)) {
551 buf
[strcspn(buf
, "\n")] = '\0';
558 if (!check_help(buf
)) {
560 } else if (!check_print(buf
)) {
562 } else if (!check_quit(buf
)) {
564 } else if (!partial_match
&&
565 !check_mutate(buf
, e
, &partial_match
)) {
567 } else if (!partial_match
&&
568 !check_delete(buf
, e
, &partial_match
)) {
570 } else if (!partial_match
&&
571 !check_vertex(buf
, e
, &partial_match
)) {
573 } else if (!partial_match
&&
574 !check_edge(buf
, e
, &partial_match
)) {
576 } else if (!partial_match
&&
577 !check_rename(buf
, e
, &partial_match
)) {
579 } else if (!partial_match
&&
580 !check_incfat(buf
, e
, &partial_match
)) {
582 } else if (!partial_match
&&
583 !check_decfat(buf
, e
, &partial_match
)) {
585 } else if (!partial_match
&&
586 !check_save(buf
, e
, &partial_match
)) {
588 } else if (!partial_match
&&
589 !check_load(buf
, e
, &partial_match
)) {
591 } else if (!partial_match
) {
592 printf("Unknown command (try `help')\n");
599 /* ^D works like `quit' */
601 *e
= (struct ui_event
) { .type
= ET_QUIT
};