From 383c3f526a035d4d4261114c36c15a42e50e30e4 Mon Sep 17 00:00:00 2001 From: terencehill Date: Sun, 29 Sep 2024 12:51:30 +0200 Subject: [PATCH] Autocompletion by # SHIFT-TAB: display player names above chat line in a floating bar Abort player names cycling after 3 seconds without pressing any key In console don't display "1 possible nick:" while cycling through player names --- cl_screen.c | 14 +----- cl_screen.h | 2 - console.c | 138 ++++++++++++++++++++++++++++++++++++---------------- console.h | 7 ++- keys.c | 31 +++++++----- 5 files changed, 121 insertions(+), 71 deletions(-) diff --git a/cl_screen.c b/cl_screen.c index 72e0d852..4bdb5631 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -132,7 +132,6 @@ int scr_erase_lines; int scr_erase_center; char scr_infobarstring[MAX_INPUTLINE]; float scr_infobartime_off; -qbool scr_infobartime_left_align; /* ============== @@ -583,10 +582,7 @@ static int SCR_DrawInfobarString(int offset) float size = scr_infobar_height.value; len = (int)strlen(scr_infobarstring); - if (scr_infobartime_left_align) - x = 0; - else - x = (vid_conwidth.integer - DrawQ_TextWidth(scr_infobarstring, len, size, size, false, FONT_INFOBAR)) / 2; + x = (vid_conwidth.integer - DrawQ_TextWidth(scr_infobarstring, len, size, size, false, FONT_INFOBAR)) / 2; y = vid_conheight.integer - size - offset; DrawQ_Fill(0, y, vid_conwidth.integer, size, 0, 0, 0, cls.signon == SIGNONS ? 0.5 : 1, 0); DrawQ_String(x, y, scr_infobarstring, len, size, size, 1, 1, 1, 1, 0, NULL, false, FONT_INFOBAR); @@ -688,13 +684,6 @@ static int SCR_InfobarHeight(void) return offset; } -void SCR_Infobar(float bartime, char *barstring, qbool left_align) -{ - scr_infobartime_off = bartime; - dp_strlcpy(scr_infobarstring, barstring, sizeof(scr_infobarstring)); - scr_infobartime_left_align = left_align; -} - /* ============== @@ -707,7 +696,6 @@ static void SCR_InfoBar_f(cmd_state_t *cmd) { scr_infobartime_off = atof(Cmd_Argv(cmd, 1)); dp_strlcpy(scr_infobarstring, Cmd_Argv(cmd, 2), sizeof(scr_infobarstring)); - scr_infobartime_left_align = false; } else { diff --git a/cl_screen.h b/cl_screen.h index c431a9d7..57cfd282 100644 --- a/cl_screen.h +++ b/cl_screen.h @@ -27,7 +27,5 @@ void CL_UpdateScreen(void); qbool R_Stereo_Active(void); qbool R_Stereo_ColorMasking(void); -void SCR_Infobar(float bartime, char *barstring, qbool left_align); - #endif diff --git a/console.c b/console.c index 9acfe146..e1f15d2f 100644 --- a/console.c +++ b/console.c @@ -34,7 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. float con_cursorspeed = 4; // lines up from bottom to display -int hash_completion_player; +int hash_completion_player = -1; +float chat_nicksbar_time; int con_backscroll; conbuffer_t con; @@ -1611,6 +1612,69 @@ void Con_CenterPrint(const char *str) } +void Hash_Completion_Reset(void) +{ + hash_completion_player = -1; +} + +char chat_nicksbarstring[MAX_INPUTLINE]; +void Chat_NicksBar_Build(void) +{ + int initial = hash_completion_player; + int next = initial; + int next_players_count = 3; + + dpsnprintf(chat_nicksbarstring, sizeof(chat_nicksbarstring), "#%d %s", hash_completion_player + 1, cl.scores[hash_completion_player].name); + while(next_players_count >= 0) + { + next = (next + 1) % cl.maxclients; + if (next == initial) + break; + if (cl.scores[next].name[0]) + { + if (next_players_count == 0) + dpsnprintf(chat_nicksbarstring, sizeof(chat_nicksbarstring), "%s^8, ...", chat_nicksbarstring); + else + dpsnprintf(chat_nicksbarstring, sizeof(chat_nicksbarstring), "%s^8, #%d ^7%s", chat_nicksbarstring, next + 1, cl.scores[next].name); + --next_players_count; + } + } + chat_nicksbar_time = 3; +} + +void Chat_NicksBar_Clear(void) +{ + chat_nicksbarstring[0] = 0; +} + +static void Chat_NicksBar_Draw(float ofs_x, float ofs_y) +{ + int len; + float str_width, hash_width, alpha; + float fontsize = con_chatsize.value; + + if (cl.time > cl.oldtime) + chat_nicksbar_time -= cl.time - cl.oldtime; + + if (!chat_nicksbarstring[0] || chat_nicksbar_time <= 0) + { + Hash_Completion_Reset(); + chat_nicksbarstring[0] = 0; + chat_nicksbar_time = 0; + return; + } + + len = (int)strlen(chat_nicksbarstring); + str_width = DrawQ_TextWidth(chat_nicksbarstring, len, fontsize, fontsize, false, FONT_CHAT); + hash_width = DrawQ_TextWidth("#", (int)strlen("#"), fontsize, fontsize, false, FONT_CHAT); + ofs_x -= hash_width; + ofs_y -= fontsize; + alpha = bound(0, chat_nicksbar_time, 0.25) * 4; + DrawQ_Fill(ofs_x - fontsize / 2, ofs_y, str_width + fontsize, fontsize, 0, 0, 0, 0.7 * alpha, 0); + DrawQ_String(ofs_x, ofs_y, chat_nicksbarstring, len, fontsize, fontsize, 1, 1, 1, alpha, 0, NULL, false, FONT_CHAT); +} + + /* ============================================================================== @@ -1740,6 +1804,9 @@ static void Con_DrawInput(qbool is_console, float x, float v, float inputsize) } DrawQ_String(text_start + xo, v, text, 0, inputsize, inputsize, 1.0, 1.0, 1.0, 1.0, 0, &col_out, false, fnt); } + + if (!is_console) + Chat_NicksBar_Draw(text_start + xo, v); } typedef struct @@ -2537,7 +2604,7 @@ static int Nicks_CompleteCountPossible(char *line, int pos, char *s, qbool isCon { int initial; if (hash_completion_player < 0) - hash_completion_player = 0; + hash_completion_player = cl.maxclients - 1; initial = hash_completion_player; while(true) { @@ -2588,7 +2655,7 @@ static int Nicks_CompleteCountPossible(char *line, int pos, char *s, qbool isCon int len = (int) strspn(line+spos+1, "0123456789"); // number of digits if (len > 0) { - hash_completion_player = -1; + Hash_Completion_Reset(); if (line[pos-1] == ' ') ++len; // word lenght EQUAL digits count OR digits count + 1 trailing space @@ -2622,42 +2689,10 @@ static int Nicks_CompleteCountPossible(char *line, int pos, char *s, qbool isCon return count; } -static void Cmd_CompleteNicksPrint(int count, int hash_completion, qbool infobar) +static void Cmd_CompleteNicksPrint(int count) { - if (infobar) - { - char pl_list[MAX_INPUTLINE] = ""; - int initial = hash_completion_player; - int next = initial; - int next_players_count = 3; - - dpsnprintf(pl_list, sizeof(pl_list), "#%d %s", hash_completion_player + 1, Nicks_list[0]); - while(next_players_count >= 0) - { - next = (next + 1) % cl.maxclients; - if (next == initial) - break; - if (cl.scores[next].name[0]) - { - if (next_players_count == 0) - dpsnprintf(pl_list, sizeof(pl_list), "%s^8, ...", pl_list); - else - dpsnprintf(pl_list, sizeof(pl_list), "%s^8, #%d ^7%s", pl_list, next + 1, cl.scores[next].name); - --next_players_count; - } - } - - SCR_Infobar(2, pl_list, true); - return; - } - for(int i = 0; i < count; ++i) - { - if (hash_completion == 1 && hash_completion_player >= 0) - Con_Printf("#%d %s\n", hash_completion_player + 1, Nicks_list[i]); - else - Con_Printf("%s\n", Nicks_list[i]); - } + Con_Printf("%s\n", Nicks_list[i]); } static void Nicks_CutMatchesNormal(int count) @@ -2942,7 +2977,7 @@ static size_t Con_EscapeSpaces(char *dst, const char *src, size_t dsize) Directory support by divVerent Escaping support by bones_was_here */ -int Con_CompleteCommandLine(cmd_state_t *cmd, qbool is_console, int hash_completion) +int Con_CompleteCommandLine(cmd_state_t *cmd, qbool is_console, qbool shift_mode) { const char *text = ""; char *s; @@ -2953,10 +2988,18 @@ int Con_CompleteCommandLine(cmd_state_t *cmd, qbool is_console, int hash_complet int n; // nicks --blub const char *space, *patterns; char vabuf[1024]; + int hash_completion; char *line; int linestart, linepos; unsigned int linesize; + + hash_completion = (shift_mode != 0) ? 1 : (hash_completion_player >= 0 ? 2 : 0); + // 0: normal TAB autocompletion + // 1: SHIFT-TAB after #N autocompletes player N name + // 1: SHIFT-TAB after # cycles through player names (no actual autocompletion) + // 2: TAB after cycling with SHIFT-TAB autocompletes the selected name + if (is_console) { line = key_line; @@ -3212,15 +3255,21 @@ nicks: { if (!is_console && hash_completion == 1 && hash_completion_player >= 0) { - Cmd_CompleteNicksPrint(n, hash_completion, true); // print to infobar + Chat_NicksBar_Build(); n = 0; // cycle player names without autocompleting } else { - Con_Printf("\n%i possible nick%s\n", n, (n > 1) ? "s: " : ":"); - Cmd_CompleteNicksPrint(n, hash_completion, false); if (hash_completion == 1 && hash_completion_player >= 0) + { n = 0; // cycle player names without autocompleting + Con_Printf("#%d %s\n", hash_completion_player + 1, Nicks_list[0]); + } + else + { + Con_Printf("\n%i possible nick%s\n", n, (n > 1) ? "s: " : ":"); + Cmd_CompleteNicksPrint(n); + } } } @@ -3288,6 +3337,13 @@ done: } } + if (hash_completion == 2) // requested autocompletion of player name with TAB + { + Hash_Completion_Reset(); + if (!is_console) + Chat_NicksBar_Clear(); + } + // use strlcat to avoid a buffer overrun line[linepos] = 0; dp_strlcat(line, s2, linesize); diff --git a/console.h b/console.h index 2edb0a0d..3d5994e4 100644 --- a/console.h +++ b/console.h @@ -30,11 +30,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // console // -extern int hash_completion_player; extern int con_totallines; extern int con_backscroll; extern qbool con_initialized; +void Chat_NicksBar_Build(void); +void Chat_NicksBar_Clear(void); +void Hash_Completion_Reset(void); + void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest, qbool proquakeprotocol); void Con_Rcon_Redirect_End(void); void Con_Rcon_Redirect_Abort(void); @@ -81,7 +84,7 @@ size_t GetMapList (const char *s, char *completedname, int completednamebuffersi /// or to list possible matches grouped by type /// (i.e. will display possible variables, aliases, commands /// that match what they've typed so far) -int Con_CompleteCommandLine(cmd_state_t *cmd, qbool is_console, int hash_completion); +int Con_CompleteCommandLine(cmd_state_t *cmd, qbool is_console, qbool shift_mode); /// Generic libs/util/console.c function to display a list /// formatted in columns on the console diff --git a/keys.c b/keys.c index c1f497a0..d98a7785 100644 --- a/keys.c +++ b/keys.c @@ -667,6 +667,7 @@ static const keyname_t keynames[] = { int Key_ClearEditLine(qbool is_console) { + Hash_Completion_Reset(); if (is_console) { key_line[0] = ']'; @@ -676,6 +677,7 @@ int Key_ClearEditLine(qbool is_console) else { chat_buffer[0] = 0; + Chat_NicksBar_Clear(); return 0; } } @@ -864,18 +866,10 @@ int Key_Parse_CommonKeys(cmd_state_t *cmd, qbool is_console, int key, int unicod return linepos; } - if (KM_SHIFT) // SHIFT-TAB after #N autocompletes the name of player N; after # it cycles through player names - return Con_CompleteCommandLine(cmd, is_console, 1); + if (KM_SHIFT) + return Con_CompleteCommandLine(cmd, is_console, true); if (KM_NONE) - { - if (hash_completion_player >= 0) // TAB after # autocompletes the name of hash_completion_player - { - int r = Con_CompleteCommandLine(cmd, is_console, 2); - hash_completion_player = -1; - return r; - } - return Con_CompleteCommandLine(cmd, is_console, 0); - } + return Con_CompleteCommandLine(cmd, is_console, false); } // Advanced Console Editing by Radix radix@planetquake.com @@ -1112,7 +1106,7 @@ static int Key_Convert_NumPadKey(int key) static void Key_Console(cmd_state_t *cmd, int key, int unicode) { - int linepos; + int linepos, prev_linepos; key = Key_Convert_NumPadKey(key); @@ -1123,7 +1117,11 @@ static void Key_Console(cmd_state_t *cmd, int key, int unicode) if (keydown[K_CTRL] && keydown[K_ALT]) goto add_char; + prev_linepos = key_linepos; linepos = Key_Parse_CommonKeys(cmd, true, key, unicode); + if (linepos != prev_linepos) + Hash_Completion_Reset(); + if (linepos >= 0) { key_linepos = linepos; @@ -1310,7 +1308,7 @@ add_char: static void Key_Message (cmd_state_t *cmd, int key, int ascii) { - int linepos; + int linepos, prev_linepos; char vabuf[1024]; key = Key_Convert_NumPadKey(key); @@ -1333,7 +1331,14 @@ Key_Message (cmd_state_t *cmd, int key, int ascii) return; } + prev_linepos = chat_bufferpos; linepos = Key_Parse_CommonKeys(cmd, false, key, ascii); + if (linepos != prev_linepos) + { + Hash_Completion_Reset(); + Chat_NicksBar_Clear(); + } + if (linepos >= 0) { chat_bufferpos = linepos; -- 2.39.2