From 2f8737d97365eab201ffdac39507d79a470406de Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 20 Nov 2018 14:11:10 +0100 Subject: [PATCH] Improved formatting of terminal help messages. --- client/common/cmdline.c | 136 +++++++++++++++++++++++++++++----------- client/common/cmdline.h | 39 ++++++------ 2 files changed, 119 insertions(+), 56 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 9024b68a7..d175e83ef 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -71,6 +71,65 @@ BOOL freerdp_client_print_buildconfig(void) return TRUE; } +static char* print_token(char* text, int start_offset, int* current, int limit, + const char delimiter) +{ + int len = (int)strlen(text); + + if (*current < start_offset) + *current += printf("%*c", (start_offset - *current), ' '); + + if (*current + len > limit) + { + int x; + + for (x = MIN(len, limit - start_offset); x > 1; x--) + { + if (text[x] == delimiter) + { + printf("%.*s\n", x, text); + *current = 0; + return &text[x]; + } + } + + return NULL; + } + + *current += printf("%s", text); + return NULL; +} + +static int print_optionals(const char* text, int start_offset, int current) +{ + const size_t limit = 80; + char* str = _strdup(text); + char* cur = print_token(str, start_offset, ¤t, limit, '['); + + while (cur) + cur = print_token(cur, start_offset, ¤t, limit, '['); + + free(str); + return current; +} + +static int print_description(const char* text, int start_offset, int current) +{ + const size_t limit = 80; + char* str = _strdup(text); + char* cur = print_token(str, start_offset, ¤t, limit, ' '); + + while (cur) + { + cur++; + cur = print_token(cur, start_offset, ¤t, limit, ' '); + } + + free(str); + current += (size_t) printf("\n"); + return current; +} + static void freerdp_client_print_command_line_args(COMMAND_LINE_ARGUMENT_A* arg) { if (!arg) @@ -78,46 +137,45 @@ static void freerdp_client_print_command_line_args(COMMAND_LINE_ARGUMENT_A* arg) do { - if (arg->Flags & COMMAND_LINE_VALUE_FLAG) - { - printf(" %s", "/"); - printf("%-20s", arg->Name); - printf("\t%s\n", arg->Text); - } - else if ((arg->Flags & COMMAND_LINE_VALUE_REQUIRED) - || (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL)) - { - BOOL overlong = FALSE; - printf(" %s", "/"); + int pos = 0; + const int description_offset = 30 + 8; + if (arg->Flags & COMMAND_LINE_VALUE_BOOL) + pos += printf(" %s%s", arg->Default ? "-" : "+", arg->Name); + else + pos += printf(" /%s", arg->Name); + + if ((arg->Flags & COMMAND_LINE_VALUE_REQUIRED) + || (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL)) + { if (arg->Format) { - size_t length = (strlen(arg->Name) + strlen(arg->Format) + 2); - if (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL) - length += 2; - - if (length >= 20 + 8 + 8) - overlong = TRUE; - - if (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL) - printf("%s[:%s]", arg->Name, overlong ? "..." : arg->Format); + { + pos += printf("[:"); + pos = print_optionals(arg->Format, pos, pos); + pos += printf("]"); + } else - printf("%s:%s", arg->Name, overlong ? "..." : arg->Format); - } - else - { - printf("%-20s", arg->Name); - } + { + pos += printf(":"); + pos = print_optionals(arg->Format, pos, pos); + } - printf("\t%s\n", arg->Text); - } - else if (arg->Flags & COMMAND_LINE_VALUE_BOOL) - { - printf(" %s", arg->Default ? "-" : "+"); - printf("%-20s", arg->Name); - printf("\t%s %s\n", arg->Default ? "Disable" : "Enable", arg->Text); + if (pos > description_offset) + { + printf("\n"); + pos = 0; + } + } } + + pos += printf("%*c", (description_offset - pos), ' '); + + if (arg->Flags & COMMAND_LINE_VALUE_BOOL) + pos += printf("%s ", arg->Default ? "Disable" : "Enable"); + + print_description(arg->Text, description_offset, pos); } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); } @@ -1323,21 +1381,22 @@ static void activate_smartcard_logon_rdp(rdpSettings* settings) * @param v2: pointer to output v2 * @return if the parsing was successful */ -static BOOL parseSizeValue(const char *input, unsigned long *v1, unsigned long *v2) +static BOOL parseSizeValue(const char* input, unsigned long* v1, unsigned long* v2) { - const char *xcharpos; - char *endPtr; + const char* xcharpos; + char* endPtr; unsigned long v; - errno = 0; v = strtoul(input, &endPtr, 10); if ((v == 0 || v == ULONG_MAX) && (errno != 0)) return FALSE; + if (v1) *v1 = v; xcharpos = strchr(input, 'x'); + if (!xcharpos || xcharpos != endPtr) return FALSE; @@ -1349,6 +1408,7 @@ static BOOL parseSizeValue(const char *input, unsigned long *v1, unsigned long * if (*endPtr != '\0') return FALSE; + if (v2) *v2 = v; @@ -1576,12 +1636,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "size") { - p = strchr(arg->Value, 'x'); if (p) { unsigned long w, h; + if (!parseSizeValue(arg->Value, &w, &h) || (w > UINT16_MAX) || (h > UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; diff --git a/client/common/cmdline.h b/client/common/cmdline.h index 7f1d9e03f..f41720e26 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -51,7 +51,7 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "cert-tofu", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Automatically accept certificate on first connect" }, { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Client Hostname to send to server" }, { "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Redirect clipboard" }, - { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "rfx|nsc|jpeg", NULL, NULL, -1, NULL, "Bitmap codec cache" }, + { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "[rfx|nsc|jpeg]", NULL, NULL, -1, NULL, "Bitmap codec cache" }, { "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "compression" }, { "compression-level", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Compression level (0,1,2)" }, { "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "credentials delegation" }, @@ -73,14 +73,14 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Number of frame acknowledgement" }, { "from-stdin", COMMAND_LINE_VALUE_OPTIONAL, "force", NULL, NULL, -1, NULL, "Read credentials from stdin. With the prompt is done before connection, otherwise on server request." }, { "g", COMMAND_LINE_VALUE_REQUIRED, "[:]", NULL, NULL, -1, NULL, "Gateway Hostname" }, - { "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "direct|detect", NULL, NULL, -1, "gum", "Gateway usage method" }, + { "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "[direct|detect]", NULL, NULL, -1, "gum", "Gateway usage method" }, { "gd", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway domain" }, { "gdi", COMMAND_LINE_VALUE_REQUIRED, "sw|hw", NULL, NULL, -1, NULL, "GDI rendering" }, { "geometry", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Geometry tracking channel" }, { "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" }, #ifdef WITH_GFX_H264 - { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX|AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, - { "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" }, + { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "[RFX|AVC420|AVC444]", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, + { "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "[AVC420|AVC444]", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" }, #else { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, #endif @@ -90,8 +90,8 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "glyph-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Glyph cache (experimental)" }, { "gp", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway password" }, { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab keyboard" }, - { "gt", COMMAND_LINE_VALUE_REQUIRED, "rpc|http|auto", NULL, NULL, -1, NULL, "Gateway transport type" }, - { "gu", COMMAND_LINE_VALUE_REQUIRED, "[\\] or [@]", NULL, NULL, -1, NULL, "Gateway username" }, + { "gt", COMMAND_LINE_VALUE_REQUIRED, "[rpc|http|auto]", NULL, NULL, -1, NULL, "Gateway transport type" }, + { "gu", COMMAND_LINE_VALUE_REQUIRED, "[[\\]|[@]]", NULL, NULL, -1, NULL, "Gateway username" }, { "gat", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway Access Token" }, { "h", COMMAND_LINE_VALUE_REQUIRED, "", "768", NULL, -1, NULL, "Height" }, { "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" }, @@ -109,7 +109,7 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard type" }, { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Load balance info" }, { "log-filters", COMMAND_LINE_VALUE_REQUIRED, ":[,:[,...]]", NULL, NULL, -1, NULL, "Set logger filters, see wLog(7) for details" }, - { "log-level", COMMAND_LINE_VALUE_REQUIRED, "OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE", NULL, NULL, -1, NULL, "Set the default log level, see wLog(7) for details" }, + { "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]", NULL, NULL, -1, NULL, "Set the default log level, see wLog(7) for details" }, { "max-fast-path-size", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Specify maximum fast-path update size" }, { "max-loop-time", COMMAND_LINE_VALUE_REQUIRED, "