void Key_CompleteCommandOld (void) { const char *cmd; char *s; s = key_lines[edit_line]+1; if (*s == '\\' || *s == '/') s++; cmd = Cmd_CompleteCommandOld (s); if (!cmd) cmd = Cvar_CompleteVariable (s); if (cmd) { key_lines[edit_line][1] = '/'; strcpy (key_lines[edit_line]+2, cmd); key_linepos = (int)strlen(cmd)+2; key_lines[edit_line][key_linepos] = ' '; key_linepos++; key_lines[edit_line][key_linepos] = 0; return; } }
/** * @brief Console completion for command and variables * @sa Key_CompleteCommand * @sa Cmd_CompleteCommand * @sa Cvar_CompleteVariable * @param[in] s The string to complete * @param[out] target The target buffer of the completed command/cvar * @param[in] bufSize the target buffer size - might not be bigger than MAXCMDLINE * @param[out] pos The position in the buffer after command completion * @param[in] offset The input buffer position to put the completed command to */ bool Com_ConsoleCompleteCommand (const char* s, char* target, size_t bufSize, uint32_t* pos, uint32_t offset) { const char* cmd = nullptr, *cvar = nullptr, *use = nullptr; char cmdLine[MAXCMDLINE] = ""; char cmdBase[MAXCMDLINE] = ""; bool append = true; if (!s[0] || s[0] == ' ') return false; if (s[0] == '\\' || s[0] == '/') { /* maybe we are using the same buffers - and we want to keep the slashes */ if (s == target) offset++; s++; } assert(bufSize <= MAXCMDLINE); assert(pos); /* don't try to search a command or cvar if we are already in the * parameter stage */ if (strstr(s, " ")) { int cntParams; char* tmp; Q_strncpyz(cmdLine, s, sizeof(cmdLine)); /* remove the last whitespace */ cmdLine[strlen(cmdLine) - 1] = '\0'; tmp = cmdBase; while (*s != ' ') *tmp++ = *s++; /* get rid of the whitespace */ s++; /* terminate the string at whitespace position to separate the cmd */ *tmp = '\0'; /* now strip away that part that is not yet completed */ tmp = strrchr(cmdLine, ' '); if (tmp) *tmp = '\0'; cntParams = Cmd_CompleteCommandParameters(cmdBase, s, &cmd); if (cntParams > 1) Com_Printf("\n"); if (cmd) { /* append the found parameter */ Q_strcat(cmdLine, sizeof(cmdLine), " %s", cmd); append = false; use = cmdLine; } else return false; } else { /* Cmd_GenericCompleteFunction uses one static buffer for output, so backup one completion here if available */ static char cmdBackup[MAX_QPATH]; int cntCvar; int cntCmd = Cmd_CompleteCommand(s, &cmd); if (cmd) Q_strncpyz(cmdBackup, cmd, sizeof(cmdBackup)); cntCvar = Cvar_CompleteVariable(s, &cvar); /* complete as much as possible, append only if one single match is found */ if (cntCmd > 0 && !cntCvar) { use = cmd; if (cntCmd != 1) append = false; } else if (!cntCmd && cntCvar > 0) { use = cvar; if (cntCvar != 1) append = false; } else if (cmd && cvar) { int maxLength = std::min(strlen(cmdBackup),strlen(cvar)); int idx = 0; /* try to find similar content of cvar and cmd match */ Q_strncpyz(cmdLine, cmdBackup,sizeof(cmdLine)); for (; idx < maxLength; idx++) { if (cmdBackup[idx] != cvar[idx]) { cmdLine[idx] = '\0'; break; } } if (idx == maxLength) cmdLine[idx] = '\0'; use = cmdLine; append = false; } } if (use) { Q_strncpyz(&target[offset], use, bufSize - offset); *pos = strlen(target); if (append) target[(*pos)++] = ' '; target[*pos] = '\0'; return true; } return false; }