AmendHub

Download:

jcs

/

subtext

/

amendments

/

387

settings: Make struct_editor use session_menu

Take args for menu additions, and use numbers for struct members
instead of letters

jcs made amendment 387 about 1 year ago
--- settings.c Mon Mar 6 17:09:53 2023 +++ settings.c Fri Mar 10 20:11:33 2023 @@ -17,6 +17,7 @@ #include <stdio.h> #include <string.h> +#include "ansi.h" #include "subtext.h" #include "db.h" #include "focusable.h" @@ -44,263 +45,265 @@ void view_editor_save(struct focusable *focusable, Eve short struct_editor(struct session *s, const struct struct_field *fields, - const size_t nfields, void *data, size_t dsize, void **result, + const size_t nfields, const struct session_menu_option *extra_opts, + size_t nextra_opts, void *data, size_t dsize, void **result, char *title, char *prompt) { + static const struct session_menu_option opts[] = { + { '#', "", "Edit setting [#]" }, + { 's', "Ss", "Save and return to main menu" }, + { 'q', "QqXx", "Discard changes and return to main menu" }, + { '?', "?", "List menu options" }, + }; + struct session_menu_option *dopts = NULL, *opt; const struct struct_field *sf; long lval; char co, initial[20]; char *input = NULL, *new_data; - short n, i, sval; - bool found, any_changes = false; + size_t nopts; + short n, j, i, sval, on, ret; + bool any_changes, done, show_list; unsigned short c; - session_printf(s, "{{B}}Editor: %s{{/B}}\r\n", title); - session_flush(s); - new_data = xmalloc(dsize); if (new_data == NULL) goto done; memcpy(new_data, data, dsize); + + nopts = nitems(opts) + nextra_opts; + dopts = xcalloc(sizeof(struct session_menu_option), nopts); + if (dopts == NULL) + return; + if (extra_opts != NULL) + memcpy(dopts, extra_opts, + sizeof(struct session_menu_option) * nextra_opts); + memcpy(dopts + nextra_opts, opts, sizeof(opts)); + + session_printf(s, "{{B}}Editor: %s{{/B}}\r\n", title); + session_flush(s); + + any_changes = false; + show_list = true; + done = false; + ret = -1; -print_options: - for (n = 0; n < nfields; n++) { - sf = &fields[n]; - - if (n > 9) - co = 'A' + (n - 10); - else - co = '0' + n; - - session_printf(s, "{{B}}%c{{/B}}: %s [", co, sf->name); - - switch (sf->type) { - case CONFIG_TYPE_STRING: - session_printf(s, "%s", new_data + sf->off); - break; - case CONFIG_TYPE_PASSWORD: - i = strlen(new_data + sf->off); - while (i) { - session_output(s, "*", 1); - i--; + while (!done && !s->ending) { + if (show_list) { + for (n = 0; n < nfields; n++) { + sf = &fields[n]; + + session_printf(s, "{{B}}%d{{/B}}: %s [", n + 1, sf->name); + + switch (sf->type) { + case CONFIG_TYPE_STRING: + session_printf(s, "%s", new_data + sf->off); + break; + case CONFIG_TYPE_PASSWORD: + i = strlen(new_data + sf->off); + while (i) { + session_output(s, "*", 1); + i--; + } + break; + case CONFIG_TYPE_SHORT: + sval = CHARS_TO_SHORT(new_data[sf->off], + new_data[sf->off + 1]); + session_printf(s, "%d", sval); + break; + case CONFIG_TYPE_LONG: + lval = CHARS_TO_LONG(new_data[sf->off], + new_data[sf->off + 1], new_data[sf->off + 2], + new_data[sf->off + 3]); + session_printf(s, "%ld", lval); + break; + case CONFIG_TYPE_BOOLEAN: + session_printf(s, "%s", + new_data[sf->off] == 0 ? "false" : "true"); + break; + case CONFIG_TYPE_IP: { + char ip_str[16]; + lval = CHARS_TO_LONG(new_data[sf->off], + new_data[sf->off + 1], new_data[sf->off + 2], + new_data[sf->off + 3]); + if (lval == 0) + session_printf(s, "0.0.0.0"); + else { + long2ip(lval, ip_str); + session_printf(s, "%s", ip_str); + } + break; + } + } + + session_printf(s, "]\r\n"); } - break; - case CONFIG_TYPE_SHORT: - sval = CHARS_TO_SHORT(new_data[sf->off], new_data[sf->off + 1]); - session_printf(s, "%d", sval); - break; - case CONFIG_TYPE_LONG: - lval = CHARS_TO_LONG(new_data[sf->off], new_data[sf->off + 1], - new_data[sf->off + 2], new_data[sf->off + 3]); - session_printf(s, "%ld", lval); - break; - case CONFIG_TYPE_BOOLEAN: - session_printf(s, "%s", - new_data[sf->off] == 0 ? "false" : "true"); - break; - case CONFIG_TYPE_IP: { - char ip_str[16]; - lval = CHARS_TO_LONG(new_data[sf->off], new_data[sf->off + 1], - new_data[sf->off + 2], new_data[sf->off + 3]); - if (lval == 0) - session_printf(s, "0.0.0.0"); - else { - long2ip(lval, ip_str); - session_printf(s, "%s", ip_str); - } - break; } - } - session_printf(s, "]\r\n"); - } - - session_printf(s, "{{B}}S{{/B}}: Save and return to main menu\r\n"); - session_printf(s, "{{B}}Q{{/B}}: Discard changes and return to main menu\r\n"); - session_printf(s, "{{B}}?{{/B}}: Print menu of options\r\n"); + c = session_menu(s, NULL, prompt, dopts, nopts, show_list, + "Option #", &on); + show_list = false; - for (;;) { - session_printf(s, "{{B}}%s>{{/B}} ", prompt); - session_flush(s); - -get_menu_option: - c = session_input_char(s); - if (s->ending) { - any_changes = false; + switch (c) { + case 's': goto done; - } - if (c == '\r' || c == 0 || c > 255) - goto get_menu_option; - - session_printf(s, "%c\r\n", c); - session_flush(s); - - if (c == '?') - goto print_options; - if (c == 'S' || c == 's') - break; - if (c == 'Q' || c == 'q') { + case 'q': any_changes = false; goto done; - } - - found = false; - sf = NULL; - for (n = 0; n < nfields; n++) { - sf = &fields[n]; - - if (n <= 9 && c == '0' + n) { - found = true; + case '?': + show_list = true; + break; + case '#': + if (on < 1 || on > nfields) { + session_printf(s, "Invalid option\r\n"); + session_flush(s); break; } - if (n > 9 && (c == 'A' + (n - 10) || c == 'a' + (n - 10))) { - found = true; - break; - } - } - - if (!found) { - session_printf(s, "Invalid option ({{B}}?{{/B}} for help)\r\n"); - session_flush(s); - continue; - } + sf = &fields[on - 1]; get_input: - session_printf(s, "{{B}}%s:{{/B}} ", sf->name); - session_flush(s); - - switch (sf->type) { - case CONFIG_TYPE_STRING: - case CONFIG_TYPE_PASSWORD: - input = session_field_input(s, sf->max, 50, new_data + sf->off, - false, (sf->type == CONFIG_TYPE_PASSWORD ? '*' : 0)); - session_output(s, "\r\n", 2); + session_printf(s, "{{B}}%s:{{/B}} ", sf->name); session_flush(s); - if (input == NULL || s->ending) + + switch (sf->type) { + case CONFIG_TYPE_STRING: + case CONFIG_TYPE_PASSWORD: + input = session_field_input(s, sf->max, 50, + new_data + sf->off, false, + (sf->type == CONFIG_TYPE_PASSWORD ? '*' : 0)); + session_output(s, "\r\n", 2); + session_flush(s); + if (input == NULL || s->ending) + break; + + if (strlen(input) >= sf->max) { + session_printf(s, + "%s is too long (%d max, ^C to cancel)", sf->name, + sf->max - 1); + xfree(&input); + goto get_input; + } + strlcpy(new_data + sf->off, input, sf->max); + any_changes = true; break; - - if (strlen(input) >= sf->max) { - session_printf(s, - "%s is too long (%d max, ^C to cancel)", sf->name, - sf->max - 1); - xfree(&input); - goto get_input; - } - strlcpy(new_data + sf->off, input, sf->max); - any_changes = true; - break; - case CONFIG_TYPE_SHORT: - case CONFIG_TYPE_LONG: - if (sf->type == CONFIG_TYPE_LONG) { + case CONFIG_TYPE_SHORT: + case CONFIG_TYPE_LONG: + if (sf->type == CONFIG_TYPE_LONG) { + lval = CHARS_TO_LONG(new_data[sf->off], + new_data[sf->off + 1], new_data[sf->off + 2], + new_data[sf->off + 3]); + snprintf(initial, sizeof(initial), "%ld", lval); + } else { + sval = CHARS_TO_SHORT(new_data[sf->off], + new_data[sf->off + 1]); + snprintf(initial, sizeof(initial), "%d", sval); + } + input = session_field_input(s, 10, 10, initial, false, 0); + session_output(s, "\r\n", 2); + session_flush(s); + if (input == NULL || s->ending) + break; + + lval = atol(input); + if (lval < sf->min) { + session_printf(s, + "%s must be %ld or higher (^C to cancel)\r\n", + sf->name, sf->min); + xfree(&input); + goto get_input; + } + if (lval > sf->max) { + session_printf(s, + "%s must be %lu or less (^C to cancel)\r\n", + sf->name, sf->max); + xfree(&input); + goto get_input; + } + if (sf->type == CONFIG_TYPE_LONG) { + new_data[sf->off] = (lval >> 24) & 0xff; + new_data[sf->off + 1] = (lval >> 16) & 0xff; + new_data[sf->off + 2] = (lval >> 8) & 0xff; + new_data[sf->off + 3] = lval & 0xff; + } else { + sval = lval; + new_data[sf->off] = (sval >> 8) & 0xff; + new_data[sf->off + 1] = sval & 0xff; + } + any_changes = true; + break; + case CONFIG_TYPE_BOOLEAN: + if (new_data[sf->off]) + session_printf(s, "[Y/n] "); + else + session_printf(s, "[y/N] "); + session_flush(s); + + for (;;) { + c = session_input_char(s); + if (s->ending) + break; + if (c == '\r' && new_data[sf->off]) + c = 'y'; + else if (c == '\r' && new_data[sf->off] == 0) + c = 'n'; + if (c == 'y' || c == 'Y') { + new_data[sf->off] = 1; + any_changes = true; + session_printf(s, "%c\r\n", c); + break; + } + if (c == 'n' || c == 'N') { + new_data[sf->off] = 0; + any_changes = true; + session_printf(s, "%c\r\n", c); + break; + } + } + break; + case CONFIG_TYPE_IP: { + char ip_str[16]; lval = CHARS_TO_LONG(new_data[sf->off], new_data[sf->off + 1], new_data[sf->off + 2], new_data[sf->off + 3]); - snprintf(initial, sizeof(initial), "%ld", lval); - } else { - sval = CHARS_TO_SHORT(new_data[sf->off], - new_data[sf->off + 1]); - snprintf(initial, sizeof(initial), "%d", sval); - } - input = session_field_input(s, 10, 10, initial, false, 0); - session_output(s, "\r\n", 2); - session_flush(s); - if (input == NULL || s->ending) - break; - - lval = atol(input); - if (lval < sf->min) { - session_printf(s, - "%s must be %ld or higher (^C to cancel)\r\n", sf->name, - sf->min); - xfree(&input); - goto get_input; - } - if (lval > sf->max) { - session_printf(s, - "%s must be %lu or less (^C to cancel)\r\n", sf->name, - sf->max); - xfree(&input); - goto get_input; - } - if (sf->type == CONFIG_TYPE_LONG) { + if (lval == 0) + snprintf(initial, sizeof(initial), "0.0.0.0"); + else { + long2ip(lval, ip_str); + snprintf(initial, sizeof(initial), "%s", ip_str); + } + + input = session_field_input(s, 16, 16, initial, false, 0); + session_output(s, "\r\n", 2); + session_flush(s); + if (input == NULL || s->ending) + break; + + if (input[0] == '\0') { + lval = 0; + xfree(&input); + } else { + lval = ip2long(input); + xfree(&input); + if (lval == 0) { + session_printf(s, + "Invalid IP address (^C to cancel)\r\n"); + goto get_input; + } + } new_data[sf->off] = (lval >> 24) & 0xff; new_data[sf->off + 1] = (lval >> 16) & 0xff; new_data[sf->off + 2] = (lval >> 8) & 0xff; new_data[sf->off + 3] = lval & 0xff; - } else { - sval = lval; - new_data[sf->off] = (sval >> 8) & 0xff; - new_data[sf->off + 1] = sval & 0xff; + any_changes = true; + break; } - any_changes = true; - break; - case CONFIG_TYPE_BOOLEAN: - if (new_data[sf->off]) - session_printf(s, "[Y/n] "); - else - session_printf(s, "[y/N] "); - session_flush(s); - - for (;;) { - c = session_input_char(s); - if (s->ending) - break; - if (c == '\r' && new_data[sf->off]) - c = 'y'; - else if (c == '\r' && new_data[sf->off] == 0) - c = 'n'; - if (c == 'y' || c == 'Y') { - new_data[sf->off] = 1; - any_changes = true; - session_printf(s, "%c\r\n", c); - break; - } - if (c == 'n' || c == 'N') { - new_data[sf->off] = 0; - any_changes = true; - session_printf(s, "%c\r\n", c); - break; - } } break; - case CONFIG_TYPE_IP: { - char ip_str[16]; - lval = CHARS_TO_LONG(new_data[sf->off], new_data[sf->off + 1], - new_data[sf->off + 2], new_data[sf->off + 3]); - if (lval == 0) - snprintf(initial, sizeof(initial), "0.0.0.0"); - else { - long2ip(lval, ip_str); - snprintf(initial, sizeof(initial), "%s", ip_str); - } - - input = session_field_input(s, 16, 16, initial, false, 0); - session_output(s, "\r\n", 2); - session_flush(s); - if (input == NULL || s->ending) - break; - - if (input[0] == '\0') { - lval = 0; - xfree(&input); - } else { - lval = ip2long(input); - xfree(&input); - if (lval == 0) { - session_printf(s, - "Invalid IP address (^C to cancel)\r\n"); - goto get_input; - } - } - new_data[sf->off] = (lval >> 24) & 0xff; - new_data[sf->off + 1] = (lval >> 16) & 0xff; - new_data[sf->off + 2] = (lval >> 8) & 0xff; - new_data[sf->off + 3] = lval & 0xff; - any_changes = true; + default: + ret = c; + done = true; break; } - } if (s->ending) { any_changes = false; @@ -308,14 +311,16 @@ get_input: } } -done: +done: + xfree(&dopts); + if (any_changes) { *result = new_data; return 0; } else { xfree(&new_data); *result = NULL; - return -1; + return ret; } } --- settings.h Mon Mar 6 17:09:30 2023 +++ settings.h Fri Mar 10 15:22:18 2023 @@ -37,7 +37,8 @@ struct struct_field { }; short struct_editor(struct session *s, const struct struct_field *fields, - const size_t nfields, void *data, size_t dsize, void **result, + const size_t nfields, const struct session_menu_option *extra_opts, + size_t nextra_opts, void *data, size_t dsize, void **result, char *title, char *prompt); void view_editor_show(size_t id, char *title);