Esempio n. 1
0
File: keys.c Progetto: Slipyx/r1q2
/*
====================
Key_Console

Interactive line editing and console scrollback
====================
*/
void Key_Console (int key)
{

	switch ( key )
	{
	case K_KP_SLASH:
		key = '/';
		break;
	case K_KP_MINUS:
		key = '-';
		break;
	case K_KP_PLUS:
		key = '+';
		break;
	case K_KP_HOME:
		key = '7';
		break;
	case K_KP_UPARROW:
		key = '8';
		break;
	case K_KP_PGUP:
		key = '9';
		break;
	case K_KP_LEFTARROW:
		key = '4';
		break;
	case K_KP_5:
		key = '5';
		break;
	case K_KP_RIGHTARROW:
		key = '6';
		break;
	case K_KP_END:
		key = '1';
		break;
	case K_KP_DOWNARROW:
		key = '2';
		break;
	case K_KP_PGDN:
		key = '3';
		break;
	case K_KP_INS:
		key = '0';
		break;
	case K_KP_DEL:
		key = '.';
		break;
	}

	if ( ( toupper( key ) == 'V' && keydown[K_CTRL] ) ||
		 ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && keydown[K_SHIFT] ) )
	{
		char *cbd;
		
		if ( ( cbd = Sys_GetClipboardData() ) != 0 )
		{
			int		i;
			char	*p, *s;

			p = cbd;
			while ((p = strchr (p, '\r')) != NULL)
				p[0] = ' ';

			//r1: multiline paste
			p = strrchr (cbd, '\n');
			if (p)
			{
				s = strrchr (p, '\n');
				if (s)
				{
					s[0] = 0;
					p++;
					if (cbd[0])
					{
						Cbuf_AddText (cbd);
						Cbuf_AddText ("\n");
						Com_Printf ("%s\n", LOG_GENERAL, cbd);
					}
				}
			}
			else
				p = cbd;
			
			i = (int)strlen( p );

			//r1: save byte for null terminator!!
			if ( i + key_linepos >= MAXCMDLINE - 1)
				i = MAXCMDLINE - key_linepos - 1;

			if ( i > 0 )
			{
				p[i]=0;
				strcat( key_lines[edit_line], p );
				key_linepos += i;
			}
			free( cbd );
		}

		return;
	}

	if ( key == 'l' ) 
	{
		if ( keydown[K_CTRL] )
		{
			Cbuf_AddText ("clear\n");
			return;
		}
	}

	if ( key == K_ENTER || key == K_KP_ENTER )
	{	// backslash text are commands, else chat
		if (key_lines[edit_line][1] == '\\' || key_lines[edit_line][1] == '/')
			Cbuf_AddText (key_lines[edit_line]+2);	// skip the >
		else
			Cbuf_AddText (key_lines[edit_line]+1);	// valid command

		Cbuf_AddText ("\n");
		Com_Printf ("%s\n", LOG_CLIENT,key_lines[edit_line]);
		edit_line = (edit_line + 1) & 31;
		history_line = edit_line;
		memset (key_lines[edit_line], 0, sizeof(key_lines[edit_line]));
		key_lines[edit_line][0] = ']';
		//key_lines[edit_line][1] = '\0';
		key_linepos = 1;
		if (cls.state == ca_disconnected)
			SCR_UpdateScreen ();	// force an update, because the command
									// may take some time
		return;
	}

	//r1: command completion stolen from proquake
	if (key == K_TAB)
	{	// command completion
		if (cl_cmdcomplete->intvalue == 1)
		{
			const char *cmd;
			int len, i;
			char *fragment;
			cvar_t *var;
			const char *best = "~";
			const char *least = "~";

			len = (int)strlen(key_lines[edit_line]);
			for (i = 0 ; i < len - 1 ; i++)
			{
				if (key_lines[edit_line][i] == ' ')
					return;
			}
			fragment = key_lines[edit_line] + 1;

			len--;
			for (var = cvar_vars->next ; var ; var = var->next)
			{
				if (strcmp(var->name, fragment) >= 0 && strcmp(best, var->name) > 0)
					best = var->name;
				if (strcmp(var->name, least) < 0)
					least = var->name;
			}
			cmd = Cmd_CompleteCommand(fragment);
			//if (strcmp(cmd, fragment) >= 0 && strcmp(best, cmd) > 0)
			if (cmd)
				best = cmd;
			if (best[0] == '~')
			{
				cmd = Cmd_CompleteCommand(" ");
				if (strcmp(cmd, least) < 0)
					best = cmd;
				else
					best = least;
			}

			//r1: maybe completing cvar/cmd from net?
			snprintf(key_lines[edit_line], sizeof(key_lines[edit_line])-1, "]%s ", best);
			key_lines[edit_line][sizeof(key_lines[edit_line])-1] = 0;

			key_linepos = (int)strlen(key_lines[edit_line]);
		}
		else if (cl_cmdcomplete->value == 2)
		{
			Key_CompleteCommand();
		}
		else
		{
			Key_CompleteCommandOld();
		}
		return;
	}

	if ( key == K_LEFTARROW )
	{
		if (key_linepos > 1)
			key_linepos--;
		return;
	}

	if (key == K_RIGHTARROW)
	{
		if (key_lines[edit_line][key_linepos])
			key_linepos++;
		return;
	}
	
	if ( ( key == K_BACKSPACE ) || ( ( key == 'h' ) && ( keydown[K_CTRL] ) ) )
	{
		if (key_linepos > 1)
		{
			memmove (key_lines[edit_line] + key_linepos-1, key_lines[edit_line] + key_linepos, sizeof(key_lines[edit_line])-key_linepos);
			key_linepos--;
		}
		return;
	}

	if ( key == K_DEL )
	{
		memmove (key_lines[edit_line] + key_linepos, key_lines[edit_line] + key_linepos + 1, sizeof(key_lines[edit_line])-key_linepos-1);
		return;
	}

	if ( ( key == K_UPARROW ) || ( key == K_KP_UPARROW ) ||
		 ( ( key == 'p' ) && keydown[K_CTRL] ) )
	{
		do
		{
			history_line = (history_line - 1) & 31;
		} while (history_line != edit_line
				&& !key_lines[history_line][1]);
		if (history_line == edit_line)
			history_line = (edit_line+1)&31;
		strcpy(key_lines[edit_line], key_lines[history_line]);
		key_linepos = (int)strlen(key_lines[edit_line]);
		return;
	}

	if ( ( key == K_DOWNARROW ) || ( key == K_KP_DOWNARROW ) ||
		 ( ( key == 'n' ) && keydown[K_CTRL] ) )
	{
		if (history_line == edit_line) return;
		do
		{
			history_line = (history_line + 1) & 31;
		}
		while (history_line != edit_line
			&& !key_lines[history_line][1]);
		if (history_line == edit_line)
		{
			key_lines[edit_line][0] = ']';
			key_lines[edit_line][1] = '\0';
			key_linepos = 1;
		}
		else
		{
			strcpy(key_lines[edit_line], key_lines[history_line]);
			key_linepos = (int)strlen(key_lines[edit_line]);
		}
		return;
	}

	if (key == K_PGUP || key == K_KP_PGUP )
	{
		con.display -= 2;
		return;
	}

	if (key == K_PGDN || key == K_KP_PGDN ) 
	{
		con.display += 2;
		if (con.display > con.current)
			con.display = con.current;
		return;
	}

	if (key == K_HOME || key == K_KP_HOME )
	{
		if (keydown[K_CTRL] || !key_lines[edit_line][1] || key_linepos == 1)
			con.display = con.current - con.totallines + 10;
		else
			key_linepos = 1;
		return;
	}

	if (key == K_END || key == K_KP_END )
	{
		int		len;

		len = (int)strlen(key_lines[edit_line]);

		if (keydown[K_CTRL] || !key_lines[edit_line][1] || key_linepos == len)
			con.display = con.current;
		else
			key_linepos = len;
		return;
	}
	
	if (key < 32 || key > 127)
		return;	// non printable
		
	if (key_linepos < MAXCMDLINE-1)
	{
		int		last;
		int		length;

		length = (int)strlen(key_lines[edit_line]);

		if (length >= MAXCMDLINE-1)
			return;

		last = key_lines[edit_line][length];

		memmove (key_lines[edit_line] + key_linepos+1, key_lines[edit_line] + key_linepos, length - key_linepos);

		key_lines[edit_line][key_linepos] = (char)key;
		key_linepos++;

		if (!last)
			key_lines[edit_line][length+1] = 0;
	}
}
Esempio n. 2
0
/**
 * @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;
}
Esempio n. 3
0
char *Sys_ConsoleInput (void)
{
	int		c;

	if (consolewindowhandle)
	{
		MSG msg;
		while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (!GetMessage (&msg, NULL, 0, 0))
				return NULL;
      		TranslateMessage (&msg);
      		DispatchMessage (&msg);
		}
		return NULL;
	}

#ifdef SUBSERVERS
	if (SSV_IsSubServer())
	{
		DWORD avail;
		static char	text[1024];
		static int textpos = 0;

		HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
		if (!PeekNamedPipe(input, NULL, 0, NULL, &avail, NULL))
		{
			SV_FinalMessage("Cluster shut down\n");
			Cmd_ExecuteString("quit force", RESTRICT_LOCAL);
		}
		else if (avail)
		{
			if (avail > sizeof(text)-1-textpos)
				avail = sizeof(text)-1-textpos;
			if (ReadFile(input, text+textpos, avail, &avail, NULL))
			{
				textpos += avail;
				while(textpos >= 2)
				{
					unsigned short len = text[0] | (text[1]<<8);
					if (textpos >= len && len >= 2)
					{
						memcpy(net_message.data, text+2, len-2);
						net_message.cursize = len-2;
						MSG_BeginReading (msg_nullnetprim);

						SSV_ReadFromControlServer();
						
						memmove(text, text+len, textpos - len);
						textpos -= len;
					}
					else
						break;
				}
			}

		}
		return NULL;
	}
#endif

	// read a line out
	while (_kbhit())
	{
		c = _getch();
		if (c == '\r')
		{
			coninput_text[coninput_len] = 0;
			putch ('\n');
			putch (']');
			coninput_len = 0;
			return coninput_text;
		}
		if (c == 8)
		{
			if (coninput_len)
			{
				putch (c);
				putch (' ');
				putch (c);
				coninput_len--;
				coninput_text[coninput_len] = 0;
			}
			continue;
		}
		if (c == '\t')
		{
			int i;
			char *s = Cmd_CompleteCommand(coninput_text, true, true, 0, NULL);
			if(s)
			{
				for (i = 0; i < coninput_len; i++)
					putch('\b');
				for (i = 0; i < coninput_len; i++)
					putch(' ');
				for (i = 0; i < coninput_len; i++)
					putch('\b');

				strcpy(coninput_text, s);
				coninput_len = strlen(coninput_text);
				printf("%s", coninput_text);
			}
			continue;
		}
		putch (c);
		coninput_text[coninput_len] = c;
		coninput_len++;
		coninput_text[coninput_len] = 0;
		if (coninput_len == sizeof(coninput_text))
			coninput_len = 0;
	}

	return NULL;
}