static cmd_function_t *cmd_functions; // possible commands to execute
+/*
+========
+Cmd_List
+
+ CmdList Added by EvilTypeGuy eviltypeguy@qeradiant.com
+ Thanks to Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
+
+========
+*/
+void Cmd_List_f (void)
+{
+ cmd_function_t *cmd;
+ char *partial;
+ int len;
+ int count;
+
+ if (Cmd_Argc() > 1) {
+ partial = Cmd_Argv (1);
+ len = strlen(partial);
+ } else {
+ partial = NULL;
+ len = 0;
+ }
+
+ count = 0;
+ for (cmd = cmd_functions; cmd; cmd = cmd->next) {
+ if (partial && strncmp(partial, cmd->name, len))
+ continue;
+ Con_Printf ("%s\n", cmd->name);
+ count++;
+ }
+
+ Con_Printf ("%i Command%s", count, (count > 1) ? "s" : "");
+ if (partial)
+ Con_Printf(" beginning with \"%s\"", partial);
+
+ Con_Printf ("\n\n");
+}
+
/*
============
Cmd_Init
Cmd_AddCommand ("alias",Cmd_Alias_f);
Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
Cmd_AddCommand ("wait", Cmd_Wait_f);
+ Cmd_AddCommand ("cmdlist", Cmd_List_f); // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
+ Cmd_AddCommand ("cvarlist", Cvar_List_f); // 2000-01-09 CmdList, CvarList commands
+ // By Matthias "Maddes" Buecher
}
/*
Cmd_Args
============
*/
-char *Cmd_Args (void)
+char *Cmd_Args (void)
{
return cmd_args;
}
return NULL;
// check functions
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
- if (!strncmp (partial,cmd->name, len))
+ for (cmd = cmd_functions; cmd; cmd = cmd->next)
+ if (!strncmp(partial, cmd->name, len))
return cmd->name;
return NULL;
}
+/*
+ Cmd_CompleteCountPossible
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+int
+Cmd_CompleteCountPossible (char *partial)
+{
+ cmd_function_t *cmd;
+ int len;
+ int h;
+
+ h = 0;
+ len = strlen(partial);
+
+ if (!len)
+ return 0;
+
+ // Loop through the command list and count all partial matches
+ for (cmd = cmd_functions; cmd; cmd = cmd->next)
+ if (!strncasecmp(partial, cmd->name, len))
+ h++;
+
+ return h;
+}
+
+/*
+ Cmd_CompleteBuildList
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+char **
+Cmd_CompleteBuildList (char *partial)
+{
+ cmd_function_t *cmd;
+ int len = 0;
+ int bpos = 0;
+ int sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (char *);
+ char **buf;
+
+ len = strlen(partial);
+ buf = malloc(sizeofbuf + sizeof (char *));
+ // Loop through the alias list and print all matches
+ for (cmd = cmd_functions; cmd; cmd = cmd->next)
+ if (!strncasecmp(partial, cmd->name, len))
+ buf[bpos++] = cmd->name;
+
+ buf[bpos] = NULL;
+ return buf;
+}
+
+/*
+ Cmd_CompleteAlias
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+char
+*Cmd_CompleteAlias (char * partial)
+{
+ cmdalias_t *alias;
+ int len;
+
+ len = strlen(partial);
+
+ if (!len)
+ return NULL;
+
+ // Check functions
+ for (alias = cmd_alias; alias; alias = alias->next)
+ if (!strncasecmp(partial, alias->name, len))
+ return alias->name;
+
+ return NULL;
+}
+
+/*
+ Cmd_CompleteAliasCountPossible
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+int
+Cmd_CompleteAliasCountPossible (char *partial)
+{
+ cmdalias_t *alias;
+ int len;
+ int h;
+
+ h = 0;
+
+ len = strlen(partial);
+
+ if (!len)
+ return 0;
+
+ // Loop through the command list and count all partial matches
+ for (alias = cmd_alias; alias; alias = alias->next)
+ if (!strncasecmp(partial, alias->name, len))
+ h++;
+
+ return h;
+}
+
+/*
+ Cmd_CompleteAliasBuildList
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+char **
+Cmd_CompleteAliasBuildList (char *partial)
+{
+ cmdalias_t *alias;
+ int len = 0;
+ int bpos = 0;
+ int sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (char *);
+ char **buf;
+
+ len = strlen(partial);
+ buf = malloc(sizeofbuf + sizeof (char *));
+ // Loop through the alias list and print all matches
+ for (alias = cmd_alias; alias; alias = alias->next)
+ if (!strncasecmp(partial, alias->name, len))
+ buf[bpos++] = alias->name;
+
+ buf[bpos] = NULL;
+ return buf;
+}
+
/*
============
Cmd_ExecuteString
return 0;
}
+
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
+int Cmd_CompleteAliasCountPossible (char *partial);
+char **Cmd_CompleteAliasBuildList (char *partial);
+int Cmd_CompleteCountPossible (char *partial);
+char **Cmd_CompleteBuildList (char *partial);
+char *Cmd_CompleteAlias (char *partial);
+// Enhanced console completion by Fett erich@heintz.com
+// Added by EvilTypeGuy eviltypeguy@qeradiant.com
+
int Cmd_Argc (void);
char *Cmd_Argv (int arg);
char *Cmd_Args (void);
int con_backscroll; // lines up from bottom to display
int con_current; // where next message will be printed
int con_x; // offset in current line for next print
-char *con_text=0;
+char *con_text = 0;
-cvar_t con_notifytime = {"con_notifytime","3"}; //seconds
+cvar_t con_notifytime = {"con_notifytime","3"}; //seconds
cvar_t logfile = {"logfile","0"};
#define NUM_CON_TIMES 4
float con_times[NUM_CON_TIMES]; // realtime time the line was generated
- // for transparent notify lines
+ // for transparent notify lines
int con_vislines;
qboolean con_debuglog;
-#define MAXCMDLINE 256
+#define MAXCMDLINE 256
extern char key_lines[32][MAXCMDLINE];
extern int edit_line;
extern int key_linepos;
+extern int key_insert;
qboolean con_initialized;
-int con_notifylines; // scan lines to clear for notify lines
+int con_notifylines; // scan lines to clear for notify lines
extern void M_Menu_Main_f (void);
Con_DrawInput
The input line scrolls horizontally if typing goes beyond the right edge
+
+Modified by EvilTypeGuy eviltypeguy@qeradiant.com
================
*/
void Con_DrawInput (void)
{
int y;
char *text;
+ char editlinecopy[256];
if (key_dest != key_console && !con_forcedup)
return; // don't draw anything
- text = key_lines[edit_line];
+ text = strcpy(editlinecopy, key_lines[edit_line]);
+ y = strlen(text);
+
+ // Advanced Console Editing by Radix radix@planetquake.com
+ // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
+ // use strlen of edit_line instead of key_linepos to allow editing
+ // of early characters w/o erasing
+
+ // add the cursor frame
+ if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
+ text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
-// add the cursor frame
- text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
+ text[key_linepos + 1] = 0; // LordHavoc: null terminate, rather than padding with spaces
+ // text[key_linepos] = 10 + ((int)(realtime*con_cursorspeed) & 1);
- text[key_linepos+1] = 0; // LordHavoc: null terminate, rather than padding with spaces
-// fill out remainder with spaces
-// for (i=key_linepos+1 ; i< con_linewidth ; i++)
-// text[i] = ' ';
+
+ // fill out remainder with spaces
+ // for (i=key_linepos+1 ; i< con_linewidth ; i++)
+ // text[i] = ' ';
-// prestep if horizontally scrolling
+ // prestep if horizontally scrolling
if (key_linepos >= con_linewidth)
text += 1 + key_linepos - con_linewidth;
-// draw it
- y = con_vislines-16;
+ // draw it
+ y = con_vislines - 16;
+
+ // for (i=0 ; i<con_linewidth ; i++)
+ // Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
-// for (i=0 ; i<con_linewidth ; i++)
-// Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
// LordHavoc: speedup
Draw_String(8, con_vislines - 16, text, con_linewidth);
-// remove cursor
+ // remove cursor
key_lines[edit_line][key_linepos] = 0;
}
if (drawinput)
Con_DrawInput ();
}
+
+/*
+ Con_DisplayList
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ MEGA Thanks to Taniwha
+
+*/
+void
+Con_DisplayList(char **list)
+{
+ int i = 0;
+ int pos = 0;
+ int len = 0;
+ int maxlen = 0;
+ int width = (con_linewidth - 4);
+ char **walk = list;
+
+ while (*walk) {
+ len = strlen(*walk);
+ if (len > maxlen)
+ maxlen = len;
+ walk++;
+ }
+ maxlen += 1;
+
+ while (*list) {
+ len = strlen(*list);
+ if (pos + maxlen >= width) {
+ Con_Printf("\n");
+ pos = 0;
+ }
+
+ Con_Printf("%s", *list);
+ for (i = 0; i < (maxlen - len); i++)
+ Con_Printf(" ");
+
+ pos += maxlen;
+ list++;
+ }
+
+ if (pos)
+ Con_Printf("\n\n");
+}
+
+/*
+ Con_CompleteCommandLine
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+void
+Con_CompleteCommandLine (void)
+{
+ char *cmd = "";
+ char *s;
+ int c, v, a, i;
+ int cmd_len;
+ char **list[3] = {0, 0, 0};
+
+ s = key_lines[edit_line] + 1;
+ // Count number of possible matches
+ c = Cmd_CompleteCountPossible(s);
+ v = Cvar_CompleteCountPossible(s);
+ a = Cmd_CompleteAliasCountPossible(s);
+
+ if (!(c + v + a)) // No possible matches
+ return;
+
+ if (c + v + a == 1) {
+ if (c)
+ list[0] = Cmd_CompleteBuildList(s);
+ else if (v)
+ list[0] = Cvar_CompleteBuildList(s);
+ else
+ list[0] = Cmd_CompleteAliasBuildList(s);
+ cmd = *list[0];
+ cmd_len = strlen (cmd);
+ } else {
+ if (c)
+ cmd = *(list[0] = Cmd_CompleteBuildList(s));
+ if (v)
+ cmd = *(list[1] = Cvar_CompleteBuildList(s));
+ if (a)
+ cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
+
+ cmd_len = strlen (s);
+ do {
+ for (i = 0; i < 3; i++) {
+ char ch = cmd[cmd_len];
+ char **l = list[i];
+ if (l) {
+ while (*l && (*l)[cmd_len] == ch)
+ l++;
+ if (*l)
+ break;
+ }
+ }
+ if (i == 3)
+ cmd_len++;
+ } while (i == 3);
+ // 'quakebar'
+ Con_Printf("\n\35");
+ for (i = 0; i < con_linewidth - 4; i++)
+ Con_Printf("\36");
+ Con_Printf("\37\n");
+
+ // Print Possible Commands
+ if (c) {
+ Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
+ Con_DisplayList(list[0]);
+ }
+
+ if (v) {
+ Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
+ Con_DisplayList(list[1]);
+ }
+
+ if (a) {
+ Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
+ Con_DisplayList(list[2]);
+ }
+ return;
+ }
+
+ if (cmd) {
+ strncpy(key_lines[edit_line] + 2, cmd, cmd_len);
+ key_linepos = cmd_len + 2;
+ if (c + v + a == 1) {
+ key_lines[edit_line][key_linepos] = ' ';
+ key_linepos++;
+ }
+ key_lines[edit_line][key_linepos] = 0;
+ }
+ for (i = 0; i < 3; i++)
+ if (list[i])
+ free (list[i]);
+}
+
void Con_DrawNotify (void);
void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);
+
+// wrapper function to attempt to either complete the command line
+// or to list possible matches grouped by type
+// (i.e. will display possible variables, aliases, commands
+// that match what they've typed so far)
+void Con_CompleteCommandLine(void);
+
+// Generic libs/util/console.c function to display a list
+// formatted in columns on the console
+void Con_DisplayList(char **list);
+
}
+/*
+ CVar_CompleteCountPossible
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+
+*/
+int
+Cvar_CompleteCountPossible (char *partial)
+{
+ cvar_t *cvar;
+ int len;
+ int h;
+
+ h = 0;
+ len = strlen(partial);
+
+ if (!len)
+ return 0;
+
+ // Loop through the cvars and count all possible matches
+ for (cvar = cvar_vars; cvar; cvar = cvar->next)
+ if (!strncasecmp(partial, cvar->name, len))
+ h++;
+
+ return h;
+}
+
+/*
+ CVar_CompleteBuildList
+
+ New function for tab-completion system
+ Added by EvilTypeGuy
+ Thanks to Fett erich@heintz.com
+ Thanks to taniwha
+
+*/
+char **
+Cvar_CompleteBuildList (char *partial)
+{
+ cvar_t *cvar;
+ int len = 0;
+ int bpos = 0;
+ int sizeofbuf = (Cvar_CompleteCountPossible (partial) + 1) * sizeof (char *);
+ char **buf;
+
+ len = strlen(partial);
+ buf = malloc(sizeofbuf + sizeof (char *));
+ // Loop through the alias list and print all matches
+ for (cvar = cvar_vars; cvar; cvar = cvar->next)
+ if (!strncasecmp(partial, cvar->name, len))
+ buf[bpos++] = cvar->name;
+
+ buf[bpos] = NULL;
+ return buf;
+}
+
/*
============
Cvar_Set
Qprintf (f, "%s \"%s\"\n", var->name, var->string);
}
+
+// Added by EvilTypeGuy eviltypeguy@qeradiant.com
+// 2000-01-09 CvarList command By Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
+/*
+=========
+Cvar_List
+=========
+*/
+void Cvar_List_f (void)
+{
+ cvar_t *cvar;
+ char *partial;
+ int len;
+ int count;
+
+ if (Cmd_Argc() > 1) {
+ partial = Cmd_Argv (1);
+ len = strlen(partial);
+ } else {
+ partial = NULL;
+ len = 0;
+ }
+
+ count = 0;
+ for (cvar = cvar_vars; cvar; cvar = cvar->next) {
+ if (partial && strncmp (partial,cvar->name,len))
+ continue;
+
+ Con_Printf ("%s is \"%s\"\n", cvar->name, cvar->string);
+ count++;
+ }
+
+ Con_Printf ("%i cvar(s)", count);
+ if (partial)
+ Con_Printf (" beginning with \"%s\"", partial);
+ Con_Printf ("\n");
+}
+// 2000-01-09 CvarList command by Maddes
cvar_t *Cvar_FindVar (char *var_name);
extern cvar_t *cvar_vars;
+
+int Cvar_CompleteCountPossible (char *partial);
+char **Cvar_CompleteBuildList (char *partial);
+// Added by EvilTypeGuy - functions for tab completion system
+// Thanks to Fett erich@heintz.com
+// Thanks to taniwha
+
+void Cvar_List_f (void);
+// Prints a list of Cvars including a count of them to the user console
+// Referenced in cmd.c in Cmd_Init hence it's inclusion here
+// Added by EvilTypeGuy eviltypeguy@qeradiant.com
+// Thanks to Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
+
#define MAXCMDLINE 256
char key_lines[32][MAXCMDLINE];
int key_linepos;
-int shift_down=false;
+int shift_down = false;
int key_lastpress;
+int key_insert; // insert key toggle (for editing)
-int edit_line=0;
-int history_line=0;
+int edit_line = 0;
+int history_line = 0;
keydest_t key_dest;
*/
void Key_Console (int key)
{
- char *cmd;
-
if (key == K_ENTER)
{
Cbuf_AddText (key_lines[edit_line]+1); // skip the >
edit_line = (edit_line + 1) & 31;
history_line = edit_line;
key_lines[edit_line][0] = ']';
+ key_lines[edit_line][1] = 0; // EvilTypeGuy: null terminate
key_linepos = 1;
if (cls.state == ca_disconnected)
SCR_UpdateScreen (); // force an update, because the command
- // may take some time
+ // may take some time
return;
}
if (key == K_TAB)
- { // command completion
- cmd = Cmd_CompleteCommand (key_lines[edit_line]+1);
- if (!cmd)
- cmd = Cvar_CompleteVariable (key_lines[edit_line]+1);
- if (cmd)
- {
- strcpy (key_lines[edit_line]+1, cmd);
- key_linepos = strlen(cmd)+1;
- key_lines[edit_line][key_linepos] = ' ';
- key_linepos++;
- key_lines[edit_line][key_linepos] = 0;
- return;
- }
+ {
+ // Enhanced command completion
+ // by EvilTypeGuy eviltypeguy@qeradiant.com
+ // Thanks to Fett, Taniwha
+ Con_CompleteCommandLine();
}
- if (key == K_BACKSPACE || key == K_LEFTARROW)
+ // Advanced Console Editing by Radix radix@planetquake.com
+ // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
+
+ // left arrow will just move left one without erasing, backspace will
+ // actually erase charcter
+ if (key == K_LEFTARROW)
+ {
+ if (key_linepos > 1)
+ key_linepos--;
+ return;
+ }
+
+ if (key == K_BACKSPACE) // delete char before cursor
{
if (key_linepos > 1)
+ {
+ strcpy(key_lines[edit_line] + key_linepos - 1, key_lines[edit_line] + key_linepos);
key_linepos--;
+ }
+ return;
+ }
+
+ if (key == K_DEL) // delete char on cursor
+ {
+ if (key_linepos < strlen(key_lines[edit_line]))
+ strcpy(key_lines[edit_line] + key_linepos, key_lines[edit_line] + key_linepos + 1);
+ return;
+ }
+
+
+ // if we're at the end, get one character from previous line,
+ // otherwise just go right one
+ if (key == K_RIGHTARROW)
+ {
+ if (strlen(key_lines[edit_line]) == key_linepos)
+ {
+ if (strlen(key_lines[(edit_line + 31) & 31]) <= key_linepos)
+ return; // no character to get
+
+ key_lines[edit_line][key_linepos] = key_lines[(edit_line + 31) & 31][key_linepos];
+ key_linepos++;
+ key_lines[edit_line][key_linepos] = 0;
+ }
+ else
+ key_linepos++;
+
+ return;
+ }
+
+ if (key == K_INS) // toggle insert mode
+ {
+ key_insert ^= 1;
return;
}
+ // End Advanced Console Editing
+
if (key == K_UPARROW)
{
do
if (key < 32 || key > 127)
return; // non printable
+
+
if (key_linepos < MAXCMDLINE-1)
{
+ int i;
+
+ if (key_insert) // check insert mode
+ {
+ // can't do strcpy to move string to right
+ i = strlen(key_lines[edit_line]) - 1;
+
+ if (i == 254)
+ i--;
+
+ for (; i >= key_linepos; i--)
+ key_lines[edit_line][i + 1] = key_lines[edit_line][i];
+ }
+
+ // only null terminate if at the end
+ i = key_lines[edit_line][key_linepos];
key_lines[edit_line][key_linepos] = key;
key_linepos++;
- key_lines[edit_line][key_linepos] = 0;
- }
+ if (!i)
+ key_lines[edit_line][key_linepos] = 0;
+ }
}
//============================================================================
consolekeys[K_UPARROW] = true;
consolekeys[K_DOWNARROW] = true;
consolekeys[K_BACKSPACE] = true;
+ consolekeys[K_DEL] = true;
+ consolekeys[K_INS] = true;
consolekeys[K_PGUP] = true;
consolekeys[K_PGDN] = true;
consolekeys[K_SHIFT] = true;