2 * Copyright (c) 2017, 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)
65 /* Record that a frame has been started */
66 int ui_start_frame(void)
71 /* Draw a frame, sleep to framelimit */
72 int ui_finish_frame(void)
78 static void print_help(void)
81 "------------------------------------------------------------\n");
82 printf("help This message\n");
83 printf("print Display the quiver\n");
84 printf("mutate <num> Mutate at <num>\n");
85 printf("delete <num> Delete vertex <num>\n");
87 "delete <num1> <num2> Delete edges between <num> and <num>\n");
89 "vertex Create vertex with name \"v\", fatness 1\n");
91 "edge <num1> <num2> <p>/<q> Add an edge from <num> to <num>, weight <p>/<q>\n");
92 printf("rename <num> <str> Rename vertex <num> to <str>\n");
94 "incfat <num> Increase fatness of vertex <num> by 1\n");
96 "decfat <num> Decrease fatness of vertex <num> by 1\n");
97 printf("save <str> Write quiver to file <str>\n");
98 printf("load <str> Load quiver from file <str>\n");
99 printf("quit Quit\n");
101 "------------------------------------------------------------\n");
104 /* Print current quiver */
105 static void print_quiver(void)
109 struct rational
*e
= 0;
110 size_t line_length
= 0;
112 printf("Vertices:\n");
113 printf("%*s | Name\n-----------\n", 4, "i");
115 for (j
= 0; j
< q
->v_num
; ++j
) {
116 printf("%*llu | %s\n", 4, (long long unsigned) j
, q
->v
[j
].name
);
120 printf("Edges (i -> j):\n");
121 line_length
= printf("%*s| ", 4, "i\\j");
123 for (j
= 0; j
< q
->v_num
; ++j
) {
124 line_length
+= printf("%*llu", 5, (long long unsigned) j
);
129 for (j
= 0; j
< line_length
; ++j
) {
133 for (i
= 0; i
< q
->v_num
; ++i
) {
134 printf("\n %*llu| ", 3, (long long unsigned) i
);
136 for (j
= 0; j
< q
->v_num
; ++j
) {
137 e
= &(q
->e
[i
* q
->v_len
+ j
]);
140 printf("%*s", 5, "");
141 } else if (e
->q
== 1) {
142 printf("%*lld", 5, (long long int) e
->p
);
144 printf("%*lld/%llu", 3, (long long int) e
->p
,
145 (long long unsigned) e
->q
);
154 /* Check for `help' */
155 static int check_help(char *buf
)
157 return strcmp(buf
, "help");
160 /* Check for `print' */
161 static int check_print(char *buf
)
163 return strcmp(buf
, "print");
166 /* Check for `quit' */
167 static int check_quit(char *buf
)
169 return strcmp(buf
, "quit");
172 /* Check for `mutate' */
173 static int check_mutate(char *buf
, struct ui_event
*e
,
174 uint_fast8_t *partial_match
)
179 if (strncmp(buf
, "mutate", 6)) {
185 if (sscanf(buf
, "mutate %zu%c", &i
, &dummy
) != 1) {
186 printf("Type `help' to see how to use `mutate'\n");
192 printf("Cannot mutate at %zu: not in quiver\n", i
);
197 *e
= (struct ui_event
) { .type
= ET_MUTATE
, .idx_1
= i
};
202 /* Check for `delete' */
203 static int check_delete(char *buf
, struct ui_event
*e
,
204 uint_fast8_t *partial_match
)
210 if (strncmp(buf
, "delete", 6)) {
215 int r
= sscanf(buf
, "delete %zu %zu%c", &i
, &j
, &dummy
);
219 printf("Type `help' to see how to use `delete'\n");
226 printf("Cannot delete %zu: not in quiver\n", i
);
230 *e
= (struct ui_event
) { .type
= ET_DELETE_VERTEX
,
237 "Cannot delete edges between %zu and %zu: not in quiver\n",
242 *e
= (struct ui_event
) { .type
= ET_DELETE_EDGE
,
243 .idx_1
= i
, .idx_2
= j
};
250 /* Check for `vertex' */
251 static int check_vertex(char *buf
, struct ui_event
*e
,
252 uint_fast8_t *partial_match
)
256 if (strncmp(buf
, "vertex", 6)) {
262 if (sscanf(buf
, "vertex %c", &dummy
) != 0) {
263 printf("Type `help' to see how to use `vertex'\n");
268 /* XXX: need to allow sending in name and fatness */
269 *e
= (struct ui_event
) { .type
= ET_NEW_VERTEX
};
274 /* Check for `edge' */
275 static int check_edge(char *buf
, struct ui_event
*e
,
276 uint_fast8_t *partial_match
)
285 if (strncmp(buf
, "edge", 4)) {
290 int r
= sscanf(buf
, "edge %zu %zu %d %c %d%c", &i
, &j
, &a
, &slash
, &b
,
297 printf("Type `help' to see how to use `edge'\n");
304 printf("Cannot add edge from %zu to %zu: not in quiver\n", i
,
311 printf("Cannot add edge of weight %d/%d: division by zero\n", a
,
322 if (a
<= INT_FAST8_MIN
||
323 a
>= INT_FAST8_MAX
||
324 b
>= UINT_FAST8_MAX
) {
326 "Cannot add edge of weight %d/%d: representation out of range\n",
332 *e
= (struct ui_event
) { .type
= ET_NEW_EDGE
, .idx_1
= i
, .idx_2
= j
,
338 /* Check for `rename' */
339 static int check_rename(char *buf
, struct ui_event
*e
,
340 uint_fast8_t *partial_match
)
347 if (!(s
= malloc(1024))) {
352 if (strncmp(buf
, "rename", 6)) {
358 if (sscanf(buf
, "rename %zu %1023s %c", &i
, s
, &dummy
) != 2) {
359 printf("Type `help' to see how to use `rename'\n");
364 printf("Cannot rename %zu: not in quiver\n", i
);
369 *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
)
464 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");
481 printf("Cannot save: some kind of resource allocation error\n");
486 *e
= (struct ui_event
) { .type
= ET_SAVE
, .str
= s
};
497 /* Check for `load' */
498 static int check_load(char *buf
, struct ui_event
*e
,
499 uint_fast8_t *partial_match
)
504 if (!(s
= malloc(1024))) {
512 if (strncmp(buf
, "load", 4)) {
518 if (sscanf(buf
, "load %1023s %c", s
, &dummy
) != 1) {
519 printf("Type `help' to see how to use `load'\n");
525 printf("Cannot load: some kind of resource allocation error\n");
530 *e
= (struct ui_event
) { .type
= ET_LOAD
, .str
= s
};
535 /* Where the meat of this UI is. Read commands until events are needed */
536 int ui_get_event(struct ui_event
*e
, uint_fast8_t *more
)
539 uint_fast8_t partial_match
= 0;
550 while (fgets(buf
, bufsize
, stdin
)) {
551 buf
[strcspn(buf
, "\n")] = '\0';
563 if (!check_help(buf
)) {
565 } else if (!check_print(buf
)) {
567 } else if (!check_quit(buf
)) {
569 } else if (!partial_match
&&
570 !check_mutate(buf
, e
, &partial_match
)) {
572 } else if (!partial_match
&&
573 !check_delete(buf
, e
, &partial_match
)) {
575 } else if (!partial_match
&&
576 !check_vertex(buf
, e
, &partial_match
)) {
578 } else if (!partial_match
&&
579 !check_edge(buf
, e
, &partial_match
)) {
581 } else if (!partial_match
&&
582 !check_rename(buf
, e
, &partial_match
)) {
584 } else if (!partial_match
&&
585 !check_incfat(buf
, e
, &partial_match
)) {
587 } else if (!partial_match
&&
588 !check_decfat(buf
, e
, &partial_match
)) {
590 } else if (!partial_match
&&
591 !check_save(buf
, e
, &partial_match
)) {
593 } else if (!partial_match
&&
594 !check_load(buf
, e
, &partial_match
)) {
596 } else if (!partial_match
) {
597 printf("Unknown command (try `help')\n");
604 /* ^D works like `quit' */
606 *e
= (struct ui_event
) { .type
= ET_QUIT
};