From 8698e53a464f336fcd2e92d98614f9c2bd256a8d Mon Sep 17 00:00:00 2001 From: James O'Neill Date: Tue, 28 May 2024 19:28:16 +0900 Subject: [PATCH] Print centerprint messages to the console (#159) Add new function `Con_CenterPrint` which can be used to print messages to the console, without showing onscreen, and with a "horizontal rule" above and below. Use `Con_CenterPrint` to log centerprint messages to the console. ![image](https://github.com/DarkPlacesEngine/darkplaces/assets/424218/8ef0bdc4-7481-4f11-b0a3-d46e4d451c74) Fixes #98 --------- Signed-off-by: bones_was_here Co-authored-by: bones_was_here --- cl_screen.c | 12 +++++- console.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ console.h | 5 +++ 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/cl_screen.c b/cl_screen.c index be140af3..6e40cd1f 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -143,7 +143,14 @@ for a few moments */ void SCR_CenterPrint(const char *str) { - dp_strlcpy (scr_centerstring, str, sizeof (scr_centerstring)); + if (str[0] == '\0') // happens when stepping out of a centreprint trigger on alk1.2 start.bsp + return; + + // Print the message to the console, but only if it's different to the previous message + if (strcmp(str, scr_centerstring)) + Con_CenterPrint(str); + dp_strlcpy(scr_centerstring, str, sizeof(scr_centerstring)); + scr_centertime_off = scr_centertime.value; scr_centertime_start = cl.time; @@ -168,15 +175,18 @@ static void SCR_Centerprint_f (cmd_state_t *cmd) { char msg[MAX_INPUTLINE]; unsigned int i, c, p; + c = Cmd_Argc(cmd); if(c >= 2) { + // Merge all the cprint arguments into one string dp_strlcpy(msg, Cmd_Argv(cmd,1), sizeof(msg)); for(i = 2; i < c; ++i) { dp_strlcat(msg, " ", sizeof(msg)); dp_strlcat(msg, Cmd_Argv(cmd, i), sizeof(msg)); } + c = (unsigned int)strlen(msg); for(p = 0, i = 0; i < c; ++i) { diff --git a/console.c b/console.c index a33264c1..f60b390c 100644 --- a/console.c +++ b/console.c @@ -1503,6 +1503,109 @@ void Con_DPrintf(const char *fmt, ...) } +/** + * @brief Returns a horizontal line + * @details Returns a graphical horizontal line of length len, but never wider than the + * console. Includes a newline, unless len is >= to the console width + * @note Authored by johnfitz + * + * @param[in] len Length of the horizontal line + * + * @return A string of the line + */ +const char *Con_Quakebar(int len, char *bar, size_t barsize) +{ + assert(barsize >= 5); + + len = min(len, (int)barsize - 2); + len = min(len, con_linewidth); + + bar[0] = '\35'; + memset(&bar[1], '\36', len - 2); + bar[len - 1] = '\37'; + + if (len < con_linewidth) + { + bar[len] = '\n'; + bar[len + 1] = 0; + } + else + bar[len] = 0; + + return bar; +} + +/** + * @brief Left-pad a string with spaces to make it appear centered + * @note Authored by johnfitz + * + * @param[in] maxLineLength Center-align + * @param[in] fmt A printf format string + * @param[in] Zero or more values used by fmt + */ +void Con_CenterPrintf(int maxLineLength, const char *fmt, ...) +{ + va_list argptr; + char msg[MAX_INPUTLINE]; // the original message + char line[MAX_INPUTLINE]; // one line from the message + char spaces[21]; // buffer for spaces + char *msgCursor, *lineCursor; + int lineLength, indentSize, msgLength; + + va_start(argptr, fmt); + msgLength = dpvsnprintf(msg, sizeof (msg), fmt, argptr); + va_end(argptr); + + if (msgLength == -1) + { + Con_Printf(CON_WARN "The message given to Con_CenterPrintf was too long\n"); + return; + } + + maxLineLength = min(maxLineLength, con_linewidth); + + for (msgCursor = msg; *msgCursor;) + { + lineCursor = line; // Start a the beginning of the line buffer + + // Walk msg, copying characters into the line buffer until a newline or the end of msg + while (*msgCursor && *msgCursor != '\n') + *lineCursor++ = *msgCursor++; + *lineCursor = 0; + + if (*msgCursor == '\n') + msgCursor++; + + lineLength = strlen(line); + if (lineLength < maxLineLength) + { + indentSize = (maxLineLength - lineLength) / 2; + memset(spaces, ' ', indentSize); + spaces[indentSize] = 0; + Con_MaskPrintf(CON_MASK_HIDENOTIFY, "%s%s\n", spaces, line); + } + else + Con_MaskPrintf(CON_MASK_HIDENOTIFY, "%s\n", line); + } +} + +/** + * @brief Prints a center-aligned message to the console + * @note Authored by johnfitz + * + * @param[in] str A multiline string to print + */ +void Con_CenterPrint(const char *str) +{ + char bar[42]; + + Con_MaskPrintf(CON_MASK_HIDENOTIFY, "%s", Con_Quakebar(40, bar, sizeof(bar))); + Con_CenterPrintf(40, "%s\n", str); + Con_MaskPrintf(CON_MASK_HIDENOTIFY, "%s", bar); +} + + + /* ============================================================================== diff --git a/console.h b/console.h index 8eaabbe2..0f350376 100644 --- a/console.h +++ b/console.h @@ -62,6 +62,11 @@ void Con_DPrint(const char *msg); /// A Con_Printf that only shows up if the "developer" cvar is set void Con_DPrintf(const char *fmt, ...) DP_FUNC_PRINTF(1); + +const char *Con_Quakebar(int len, char *bar, size_t bufsize); +void Con_CenterPrintf(int maxLineLength, const char *fmt, ...) DP_FUNC_PRINTF(2); +void Con_CenterPrint(const char *str); + void Con_Clear_f(cmd_state_t *cmd); void Con_DrawNotify (void); -- 2.39.2