2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include "quakedef.h"
# ifdef _WIN32
# include "winquake.h"
# endif
/*
key up events are sent even if in console mode
*/
2009-07-25 11:05:06 +00:00
void Editor_Key ( int key , int unicode ) ;
2013-04-13 08:15:18 +00:00
void Key_ConsoleInsert ( char * instext ) ;
void Key_ClearTyping ( void ) ;
2004-08-23 00:15:46 +00:00
# define KEY_MODIFIERSTATES 8
2013-04-13 08:15:18 +00:00
unsigned char * key_lines [ CON_EDIT_LINES_MASK + 1 ] ;
2004-08-23 00:15:46 +00:00
int key_linepos ;
int shift_down = false ;
int key_lastpress ;
int edit_line = 0 ;
int history_line = 0 ;
2013-10-08 14:28:11 +00:00
unsigned int key_dest_mask ;
qboolean key_dest_console ;
unsigned int key_dest_absolutemouse ;
2004-08-23 00:15:46 +00:00
2014-09-02 02:44:43 +00:00
struct key_cursor_s key_customcursor [ kc_max ] ;
2004-08-23 00:15:46 +00:00
int key_count ; // incremented every key event
2005-07-05 23:46:10 +00:00
char * keybindings [ K_MAX ] [ KEY_MODIFIERSTATES ] ;
qbyte bindcmdlevel [ K_MAX ] [ KEY_MODIFIERSTATES ] ;
qboolean consolekeys [ K_MAX ] ; // if true, can't be rebound while in console
qboolean menubound [ K_MAX ] ; // if true, can't be rebound while in menu
int keyshift [ K_MAX ] ; // key to map to if shift held down in console
int key_repeats [ K_MAX ] ; // if > 1, it is autorepeating
qboolean keydown [ K_MAX ] ;
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
# define MAX_INDEVS 8
char * releasecommand [ K_MAX ] [ MAX_INDEVS ] ; //this is the console command to be invoked when the key is released. should free it.
qbyte releasecommandlevel [ K_MAX ] [ MAX_INDEVS ] ; //and this is the cbuf level it is to be run at.
2004-08-23 00:15:46 +00:00
2006-04-12 00:17:02 +00:00
void Con_Selectioncolour_Callback ( struct cvar_s * var , char * oldvalue ) ;
2007-10-08 12:56:17 +00:00
extern cvar_t con_displaypossibilities ;
2010-07-11 02:22:39 +00:00
cvar_t con_selectioncolour = CVARFC ( " con_selectioncolour " , " 0 " , CVAR_RENDERERCALLBACK , Con_Selectioncolour_Callback ) ;
cvar_t con_echochat = CVAR ( " con_echochat " , " 0 " ) ;
2005-06-14 04:52:10 +00:00
extern cvar_t cl_chatmode ;
2004-08-23 00:15:46 +00:00
static int KeyModifier ( qboolean shift , qboolean alt , qboolean ctrl )
{
int stateset = 0 ;
if ( shift )
stateset | = 1 ;
if ( alt )
stateset | = 2 ;
if ( ctrl )
stateset | = 4 ;
return stateset ;
}
typedef struct
{
char * name ;
int keynum ;
} keyname_t ;
keyname_t keynames [ ] =
{
{ " TAB " , K_TAB } ,
{ " ENTER " , K_ENTER } ,
{ " ESCAPE " , K_ESCAPE } ,
{ " SPACE " , K_SPACE } ,
{ " BACKSPACE " , K_BACKSPACE } ,
{ " UPARROW " , K_UPARROW } ,
{ " DOWNARROW " , K_DOWNARROW } ,
{ " LEFTARROW " , K_LEFTARROW } ,
{ " RIGHTARROW " , K_RIGHTARROW } ,
2013-04-13 08:15:18 +00:00
{ " LALT " , K_LALT } ,
{ " RALT " , K_RALT } ,
2013-05-11 14:02:55 +00:00
{ " LCTRL " , K_LCTRL } ,
{ " RCTRL " , K_RCTRL } ,
{ " LSHIFT " , K_LSHIFT } ,
{ " RSHIFT " , K_RSHIFT } ,
2013-04-13 08:15:18 +00:00
{ " ALT " , K_LALT } , //depricated name
2013-05-11 14:02:55 +00:00
{ " CTRL " , K_CTRL } , //depricated name
{ " SHIFT " , K_SHIFT } , //depricated name
2004-08-23 00:15:46 +00:00
{ " F1 " , K_F1 } ,
{ " F2 " , K_F2 } ,
{ " F3 " , K_F3 } ,
{ " F4 " , K_F4 } ,
{ " F5 " , K_F5 } ,
{ " F6 " , K_F6 } ,
{ " F7 " , K_F7 } ,
{ " F8 " , K_F8 } ,
{ " F9 " , K_F9 } ,
{ " F10 " , K_F10 } ,
{ " F11 " , K_F11 } ,
{ " F12 " , K_F12 } ,
{ " INS " , K_INS } ,
{ " DEL " , K_DEL } ,
{ " PGDN " , K_PGDN } ,
{ " PGUP " , K_PGUP } ,
{ " HOME " , K_HOME } ,
{ " END " , K_END } ,
2004-09-05 23:17:32 +00:00
{ " KP_HOME " , K_KP_HOME } ,
{ " KP_UPARROW " , K_KP_UPARROW } ,
{ " KP_PGUP " , K_KP_PGUP } ,
2004-08-23 00:15:46 +00:00
{ " KP_LEFTARROW " , K_KP_LEFTARROW } ,
2004-09-05 23:17:32 +00:00
{ " KP_5 " , K_KP_5 } ,
2004-08-23 00:15:46 +00:00
{ " KP_RIGHTARROW " , K_KP_RIGHTARROW } ,
2004-09-05 23:17:32 +00:00
{ " KP_END " , K_KP_END } ,
{ " KP_DOWNARROW " , K_KP_DOWNARROW } ,
{ " KP_PGDN " , K_KP_PGDN } ,
{ " KP_ENTER " , K_KP_ENTER } ,
{ " KP_INS " , K_KP_INS } ,
{ " KP_DEL " , K_KP_DEL } ,
{ " KP_SLASH " , K_KP_SLASH } ,
{ " KP_MINUS " , K_KP_MINUS } ,
{ " KP_PLUS " , K_KP_PLUS } ,
{ " KP_NUMLOCK " , K_KP_NUMLOCK } ,
{ " KP_STAR " , K_KP_STAR } ,
2013-12-29 22:48:28 +00:00
{ " KP_MULTIPLY " , K_KP_STAR } ,
2004-09-05 23:17:32 +00:00
{ " KP_EQUALS " , K_KP_EQUALS } ,
2007-10-05 18:08:47 +00:00
//fuhquake compatible.
2004-10-07 13:02:40 +00:00
{ " KP_0 " , K_KP_INS } ,
{ " KP_1 " , K_KP_END } ,
{ " KP_2 " , K_KP_DOWNARROW } ,
{ " KP_3 " , K_KP_PGDN } ,
{ " KP_4 " , K_KP_LEFTARROW } ,
{ " KP_6 " , K_KP_RIGHTARROW } ,
{ " KP_7 " , K_KP_HOME } ,
{ " KP_8 " , K_KP_UPARROW } ,
{ " KP_9 " , K_KP_PGUP } ,
2004-09-05 23:17:32 +00:00
{ " MOUSE1 " , K_MOUSE1 } ,
{ " MOUSE2 " , K_MOUSE2 } ,
{ " MOUSE3 " , K_MOUSE3 } ,
{ " MOUSE4 " , K_MOUSE4 } ,
{ " MOUSE5 " , K_MOUSE5 } ,
2004-10-03 22:52:02 +00:00
{ " MOUSE6 " , K_MOUSE6 } ,
{ " MOUSE7 " , K_MOUSE7 } ,
{ " MOUSE8 " , K_MOUSE8 } ,
2005-06-18 22:30:57 +00:00
{ " MOUSE9 " , K_MOUSE9 } ,
{ " MOUSE10 " , K_MOUSE10 } ,
2004-09-05 23:17:32 +00:00
{ " LWIN " , K_LWIN } ,
{ " RWIN " , K_RWIN } ,
{ " APP " , K_APP } ,
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{ " MENU " , K_APP } ,
{ " SEARCH " , K_SEARCH } ,
{ " POWER " , K_POWER } ,
{ " VOLUP " , K_VOLUP } ,
{ " VOLDOWN " , K_VOLDOWN } ,
2004-08-23 00:15:46 +00:00
{ " JOY1 " , K_JOY1 } ,
{ " JOY2 " , K_JOY2 } ,
{ " JOY3 " , K_JOY3 } ,
{ " JOY4 " , K_JOY4 } ,
{ " AUX1 " , K_AUX1 } ,
{ " AUX2 " , K_AUX2 } ,
{ " AUX3 " , K_AUX3 } ,
{ " AUX4 " , K_AUX4 } ,
{ " AUX5 " , K_AUX5 } ,
{ " AUX6 " , K_AUX6 } ,
{ " AUX7 " , K_AUX7 } ,
{ " AUX8 " , K_AUX8 } ,
{ " AUX9 " , K_AUX9 } ,
{ " AUX10 " , K_AUX10 } ,
{ " AUX11 " , K_AUX11 } ,
{ " AUX12 " , K_AUX12 } ,
{ " AUX13 " , K_AUX13 } ,
{ " AUX14 " , K_AUX14 } ,
{ " AUX15 " , K_AUX15 } ,
{ " AUX16 " , K_AUX16 } ,
{ " AUX17 " , K_AUX17 } ,
{ " AUX18 " , K_AUX18 } ,
{ " AUX19 " , K_AUX19 } ,
{ " AUX20 " , K_AUX20 } ,
{ " AUX21 " , K_AUX21 } ,
{ " AUX22 " , K_AUX22 } ,
{ " AUX23 " , K_AUX23 } ,
{ " AUX24 " , K_AUX24 } ,
{ " AUX25 " , K_AUX25 } ,
{ " AUX26 " , K_AUX26 } ,
{ " AUX27 " , K_AUX27 } ,
{ " AUX28 " , K_AUX28 } ,
{ " AUX29 " , K_AUX29 } ,
{ " AUX30 " , K_AUX30 } ,
{ " AUX31 " , K_AUX31 } ,
{ " AUX32 " , K_AUX32 } ,
{ " PAUSE " , K_PAUSE } ,
{ " MWHEELUP " , K_MWHEELUP } ,
{ " MWHEELDOWN " , K_MWHEELDOWN } ,
2013-05-11 14:02:55 +00:00
{ " PRINTSCREEN " , K_PRINTSCREEN } ,
2004-10-03 10:17:15 +00:00
{ " CAPSLOCK " , K_CAPSLOCK } ,
{ " SCROLLLOCK " , K_SCRLCK } ,
2004-08-23 00:15:46 +00:00
{ " SEMICOLON " , ' ; ' } , // because a raw semicolon seperates commands
2009-04-06 00:34:32 +00:00
{ " TILDE " , ' ~ ' } ,
{ " BACKQUOTE " , ' ` ' } ,
{ " BACKSLASH " , ' \\ ' } ,
2004-08-23 00:15:46 +00:00
{ NULL , 0 }
} ;
2014-02-11 17:51:29 +00:00
# if defined(CSQC_DAT) || defined(MENU_DAT)
int MP_TranslateFTEtoQCCodes ( int code ) ;
void Key_PrintQCDefines ( vfsfile_t * f )
{
int i , j ;
for ( i = 0 ; keynames [ i ] . name ; i + + )
{
for ( j = 0 ; j < i ; j + + )
if ( keynames [ j ] . keynum = = keynames [ i ] . keynum )
break ;
if ( j = = i )
VFS_PRINTF ( f , " #define K_%s \t %i \n " , keynames [ i ] . name , MP_TranslateFTEtoQCCodes ( keynames [ j ] . keynum ) ) ;
}
}
# endif
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
LINE TYPING INTO THE CONSOLE
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2005-03-12 23:40:42 +00:00
qboolean Cmd_IsCommand ( char * line )
2004-08-23 00:15:46 +00:00
{
char command [ 128 ] ;
char * cmd , * s ;
int i ;
2005-03-10 03:55:18 +00:00
s = line ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 127 ; i + + )
2005-03-10 03:55:18 +00:00
if ( s [ i ] < = ' ' | | s [ i ] = = ' ; ' )
2004-08-23 00:15:46 +00:00
break ;
else
command [ i ] = s [ i ] ;
command [ i ] = 0 ;
2012-11-27 03:23:19 +00:00
cmd = Cmd_CompleteCommand ( command , true , false , - 1 , NULL ) ;
2004-08-23 00:15:46 +00:00
if ( ! cmd | | strcmp ( cmd , command ) )
return false ; // just a chat message
return true ;
}
# define COLUMNWIDTH 20
# define MINCOLUMNWIDTH 18
int PaddedPrint ( char * s , int x )
{
2012-03-19 06:30:41 +00:00
Con_Printf ( " ^4%s \t " , s ) ;
2004-08-23 00:15:46 +00:00
x + = strlen ( s ) ;
return x ;
}
int con_commandmatch ;
void CompleteCommand ( qboolean force )
{
char * cmd , * s ;
2012-11-27 03:23:19 +00:00
char * desc ;
2004-08-23 00:15:46 +00:00
s = key_lines [ edit_line ] + 1 ;
if ( * s = = ' \\ ' | | * s = = ' / ' )
s + + ;
2013-04-13 13:41:02 +00:00
for ( cmd = s ; * cmd ; cmd + + )
2004-08-23 00:15:46 +00:00
{
2013-04-13 13:41:02 +00:00
if ( * cmd = = ' ' | | * cmd = = ' \t ' )
break ;
}
if ( * cmd )
cmd = s ;
else
{
//check for singular matches and complete if found
cmd = Cmd_CompleteCommand ( s , true , true , 2 , NULL ) ;
if ( ! cmd | | force )
2004-08-23 00:15:46 +00:00
{
2013-04-13 13:41:02 +00:00
if ( ! force )
cmd = Cmd_CompleteCommand ( s , false , true , 1 , & desc ) ;
else
cmd = Cmd_CompleteCommand ( s , true , true , con_commandmatch , & desc ) ;
if ( cmd )
2004-08-23 00:15:46 +00:00
{
2013-04-13 13:41:02 +00:00
//complete to that (maybe partial) cmd.
Key_ClearTyping ( ) ;
Key_ConsoleInsert ( " / " ) ;
Key_ConsoleInsert ( cmd ) ;
s = key_lines [ edit_line ] + 2 ;
//if its the only match, add a space ready for arguments.
cmd = Cmd_CompleteCommand ( s , true , true , 0 , NULL ) ;
if ( cmd & & ! strcmp ( s , cmd ) )
{
Key_ConsoleInsert ( " " ) ;
}
2013-04-13 08:15:18 +00:00
2013-04-13 13:41:02 +00:00
if ( ! con_commandmatch )
con_commandmatch = 1 ;
2012-11-27 03:23:19 +00:00
2013-04-13 13:41:02 +00:00
if ( desc )
Con_Footerf ( false , " %s: %s " , cmd , desc ) ;
else
Con_Footerf ( false , " " ) ;
return ;
}
2004-08-23 00:15:46 +00:00
}
2013-04-13 13:41:02 +00:00
//complete to a partial match.
cmd = Cmd_CompleteCommand ( s , false , true , 0 , & desc ) ;
if ( cmd )
{
int i = key_lines [ edit_line ] [ 1 ] = = ' / ' ? 2 : 1 ;
if ( i ! = 2 | | strcmp ( key_lines [ edit_line ] + i , cmd ) )
{ //if successful, use that instead.
Key_ClearTyping ( ) ;
Key_ConsoleInsert ( " / " ) ;
Key_ConsoleInsert ( cmd ) ;
s = key_lines [ edit_line ] + 1 ; //readjust to cope with the insertion of a /
if ( * s = = ' \\ ' | | * s = = ' / ' )
s + + ;
}
2005-03-10 03:55:18 +00:00
}
2004-08-23 00:15:46 +00:00
}
con_commandmatch + + ;
2013-04-13 13:41:02 +00:00
cmd = Cmd_CompleteCommand ( s , true , true , con_commandmatch , & desc ) ;
if ( ! cmd )
{
con_commandmatch = 1 ;
cmd = Cmd_CompleteCommand ( s , true , true , con_commandmatch , & desc ) ;
}
if ( cmd )
2012-11-27 03:23:19 +00:00
{
2013-09-06 22:57:44 +00:00
cvar_t * var = Cvar_FindVar ( cmd ) ;
if ( var )
{
if ( desc )
Con_Footerf ( false , " %s %s \n %s " , cmd , var - > string , desc ) ;
else
Con_Footerf ( false , " %s %s " , cmd , var - > string ) ;
}
2013-04-13 13:41:02 +00:00
else
2013-09-06 22:57:44 +00:00
{
if ( desc )
Con_Footerf ( false , " %s: %s " , cmd , desc ) ;
else
Con_Footerf ( false , " " ) ;
}
2012-11-27 03:23:19 +00:00
}
else
{
Con_Footerf ( false , " " ) ;
2004-08-23 00:15:46 +00:00
con_commandmatch = 1 ;
2012-11-27 03:23:19 +00:00
}
2004-08-23 00:15:46 +00:00
}
2005-03-10 03:55:18 +00:00
//lines typed at the main console enter here
void Con_ExecuteLine ( console_t * con , char * line )
{
2008-11-09 22:29:28 +00:00
qboolean waschat = false ;
2013-04-13 08:15:18 +00:00
char deutf8 [ 8192 ] ;
2013-03-12 22:44:00 +00:00
if ( com_parseutf8 . ival < = 0 )
{
unsigned int unicode ;
int err ;
int len = 0 ;
while ( * line )
{
unicode = utf8_decode ( & err , line , & line ) ;
2014-01-13 02:42:25 +00:00
len + = unicode_encode ( deutf8 + len , unicode , sizeof ( deutf8 ) - 1 - len , true ) ;
2013-03-12 22:44:00 +00:00
}
deutf8 [ len ] = 0 ;
line = deutf8 ;
}
2008-11-09 22:29:28 +00:00
2009-02-08 18:42:41 +00:00
con_commandmatch = 1 ;
2012-11-27 03:23:19 +00:00
Con_Footerf ( false , " " ) ;
2009-01-30 04:42:26 +00:00
if ( cls . state > = ca_connected & & cl_chatmode . value = = 2 )
{
waschat = true ;
if ( keydown [ K_CTRL ] )
Cbuf_AddText ( " say_team " , RESTRICT_LOCAL ) ;
else if ( keydown [ K_SHIFT ] )
Cbuf_AddText ( " say " , RESTRICT_LOCAL ) ;
else
waschat = false ;
}
2013-04-13 08:15:18 +00:00
while ( * line = = ' ' )
line + + ;
2009-02-08 18:42:41 +00:00
if ( waschat )
Cbuf_AddText ( line , RESTRICT_LOCAL ) ;
else
{
if ( line [ 0 ] = = ' \\ ' | | line [ 0 ] = = ' / ' )
Cbuf_AddText ( line + 1 , RESTRICT_LOCAL ) ; // skip the >
else if ( cl_chatmode . value = = 2 & & Cmd_IsCommand ( line ) )
Cbuf_AddText ( line , RESTRICT_LOCAL ) ; // valid command
# ifdef Q2CLIENT
else if ( cls . protocol = = CP_QUAKE2 )
Cbuf_AddText ( line , RESTRICT_LOCAL ) ; // send the command to the server via console, and let the server convert to chat
# endif
else if ( * line )
{ // convert to a chat message
if ( ( cl_chatmode . value = = 1 | | ( ( cls . state > = ca_connected & & cl_chatmode . value = = 2 ) & & ( strncmp ( line , " say " , 4 ) ) ) ) )
{
if ( keydown [ K_CTRL ] )
Cbuf_AddText ( " say_team " , RESTRICT_LOCAL ) ;
else
Cbuf_AddText ( " say " , RESTRICT_LOCAL ) ;
waschat = true ;
}
Cbuf_AddText ( line , RESTRICT_LOCAL ) ; // skip the >
2005-03-10 03:55:18 +00:00
}
}
Cbuf_AddText ( " \n " , RESTRICT_LOCAL ) ;
2008-11-09 22:29:28 +00:00
if ( ! waschat | | con_echochat . value )
Con_Printf ( " ]%s \n " , line ) ;
2009-04-01 22:03:56 +00:00
2005-03-10 03:55:18 +00:00
if ( cls . state = = ca_disconnected )
SCR_UpdateScreen ( ) ; // force an update, because the command
// may take some time
}
2006-03-11 00:51:00 +00:00
vec3_t sccolor ;
2006-04-12 00:17:02 +00:00
void Con_Selectioncolour_Callback ( struct cvar_s * var , char * oldvalue )
{
2010-02-06 01:25:04 +00:00
if ( qrenderer ! = QR_NONE )
2006-04-12 00:17:02 +00:00
SCR_StringToRGB ( var - > string , sccolor , 1 ) ;
}
2013-08-21 07:14:39 +00:00
qboolean Key_GetConsoleSelectionBox ( console_t * con , int * sx , int * sy , int * ex , int * ey )
2006-06-04 01:43:52 +00:00
{
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
* sx = * sy = * ex = * ey = 0 ;
2013-08-21 07:14:39 +00:00
if ( con - > mousedown [ 2 ] = = 1 )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
2013-11-21 23:02:28 +00:00
//left-mouse.
//scroll the console with the mouse. trigger links on release.
2013-08-21 07:14:39 +00:00
while ( con - > mousecursor [ 1 ] - con - > mousedown [ 1 ] > 8 & & con - > display - > older )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
2013-08-21 07:14:39 +00:00
con - > mousedown [ 1 ] + = 8 ;
con - > display = con - > display - > older ;
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
}
2013-08-21 07:14:39 +00:00
while ( con - > mousecursor [ 1 ] - con - > mousedown [ 1 ] < - 8 & & con - > display - > newer )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
2013-08-21 07:14:39 +00:00
con - > mousedown [ 1 ] - = 8 ;
con - > display = con - > display - > newer ;
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
}
2012-10-13 00:56:31 +00:00
2013-08-21 07:14:39 +00:00
* sx = con - > mousecursor [ 0 ] ;
* sy = con - > mousecursor [ 1 ] ;
* ex = con - > mousecursor [ 0 ] ;
* ey = con - > mousecursor [ 1 ] ;
2012-10-13 00:56:31 +00:00
return true ;
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
}
2013-08-21 07:14:39 +00:00
else if ( con - > mousedown [ 2 ] = = 2 )
2006-06-04 01:43:52 +00:00
{
2013-11-21 23:02:28 +00:00
//right-mouse
//select. copy-to-clipboard on release.
2013-08-21 07:14:39 +00:00
* sx = con - > mousedown [ 0 ] ;
* sy = con - > mousedown [ 1 ] ;
* ex = con - > mousecursor [ 0 ] ;
* ey = con - > mousecursor [ 1 ] ;
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
return true ;
2006-06-04 01:43:52 +00:00
}
2013-11-21 23:02:28 +00:00
else
{
* sx = con - > mousecursor [ 0 ] ;
* sy = con - > mousecursor [ 1 ] ;
* ex = con - > mousecursor [ 0 ] ;
* ey = con - > mousecursor [ 1 ] ;
return false ;
}
2006-02-06 01:06:17 +00:00
}
2012-10-13 00:56:31 +00:00
/*insert the given text at the console input line at the current cursor pos*/
void Key_ConsoleInsert ( char * instext )
{
int i ;
2013-04-13 08:15:18 +00:00
int len , olen ;
char * old ;
if ( ! * instext )
return ;
old = key_lines [ edit_line ] ;
2012-10-13 00:56:31 +00:00
len = strlen ( instext ) ;
2013-04-13 08:15:18 +00:00
olen = strlen ( old ) ;
key_lines [ edit_line ] = BZ_Malloc ( olen + len + 1 ) ;
memcpy ( key_lines [ edit_line ] , old , key_linepos ) ;
memcpy ( key_lines [ edit_line ] + key_linepos , instext , len ) ;
memcpy ( key_lines [ edit_line ] + key_linepos + len , old + key_linepos , olen - key_linepos + 1 ) ;
Z_Free ( old ) ;
for ( i = key_linepos ; i < key_linepos + len ; i + + )
{
if ( key_lines [ edit_line ] [ i ] = = ' \r ' )
key_lines [ edit_line ] [ i ] = ' ' ;
else if ( key_lines [ edit_line ] [ i ] = = ' \n ' )
key_lines [ edit_line ] [ i ] = ' ; ' ;
}
key_linepos + = len ;
2012-10-13 00:56:31 +00:00
}
2012-11-27 03:23:19 +00:00
void Key_DefaultLinkClicked ( char * text , char * info )
{
char * c ;
/*the engine supports specific default links*/
/*we don't support everything. a: there's no point. b: unbindall links are evil.*/
c = Info_ValueForKey ( info , " player " ) ;
if ( * c )
{
unsigned int player = atoi ( c ) ;
int i ;
2013-12-02 14:30:30 +00:00
if ( player > = cl . allocated_client_slots | | ! * cl . players [ player ] . name )
2012-11-27 03:23:19 +00:00
return ;
c = Info_ValueForKey ( info , " action " ) ;
if ( * c )
{
if ( ! strcmp ( c , " mute " ) )
{
if ( ! cl . players [ player ] . vignored )
{
cl . players [ player ] . vignored = true ;
Con_Printf ( " ^[%s \\ player \\ %i^] muted \n " , cl . players [ player ] . name , player ) ;
}
else
{
cl . players [ player ] . vignored = false ;
Con_Printf ( " ^[%s \\ player \\ %i^] unmuted \n " , cl . players [ player ] . name , player ) ;
}
}
else if ( ! strcmp ( c , " ignore " ) )
{
if ( ! cl . players [ player ] . ignored )
{
cl . players [ player ] . ignored = true ;
cl . players [ player ] . vignored = true ;
Con_Printf ( " ^[%s \\ player \\ %i^] ignored \n " , cl . players [ player ] . name , player ) ;
}
else
{
cl . players [ player ] . ignored = false ;
cl . players [ player ] . vignored = false ;
Con_Printf ( " ^[%s \\ player \\ %i^] unignored \n " , cl . players [ player ] . name , player ) ;
}
}
else if ( ! strcmp ( c , " spec " ) )
{
Cam_TrackPlayer ( 0 , " spectate " , cl . players [ player ] . name ) ;
}
else if ( ! strcmp ( c , " kick " ) )
{
# ifndef CLIENTONLY
if ( sv . active )
{
//use the q3 command, because we can.
Cbuf_AddText ( va ( " \n clientkick %i \n " , player ) , RESTRICT_LOCAL ) ;
}
else
# endif
Cbuf_AddText ( va ( " \n rcon kick %s \n " , cl . players [ player ] . name ) , RESTRICT_LOCAL ) ;
}
else if ( ! strcmp ( c , " ban " ) )
{
# ifndef CLIENTONLY
if ( sv . active )
{
//use the q3 command, because we can.
Cbuf_AddText ( va ( " \n banname %s QuickBan \n " , cl . players [ player ] . name ) , RESTRICT_LOCAL ) ;
}
else
# endif
Cbuf_AddText ( va ( " \n rcon banname %s QuickBan \n " , cl . players [ player ] . name ) , RESTRICT_LOCAL ) ;
}
return ;
}
Con_Footerf ( false , " ^m#^m ^[%s \\ player \\ %i^]: %if %ims " , cl . players [ player ] . name , player , cl . players [ player ] . frags , cl . players [ player ] . ping ) ;
for ( i = 0 ; i < cl . splitclients ; i + + )
{
2013-06-23 02:17:02 +00:00
if ( cl . playerview [ i ] . playernum = = player )
2012-11-27 03:23:19 +00:00
break ;
}
if ( i = = cl . splitclients )
{
extern cvar_t rcon_password ;
if ( cl . spectator | | cls . demoplayback )
{
//we're spectating, or an mvd
Con_Footerf ( true , " ^[Spectate \\ player \\ %i \\ action \\ spec^] " , player ) ;
}
else
{
//we're playing.
2013-06-23 02:17:02 +00:00
if ( cls . protocol = = CP_QUAKEWORLD & & strcmp ( cl . players [ cl . playerview [ 0 ] . playernum ] . team , cl . players [ player ] . team ) )
2012-11-27 03:23:19 +00:00
Con_Footerf ( true , " ^[[Join Team %s] \\ cmd \\ setinfo team %s^] " , cl . players [ player ] . team , cl . players [ player ] . team ) ;
}
Con_Footerf ( true , " ^[%sgnore \\ player \\ %i \\ action \\ ignore^] " , cl . players [ player ] . ignored ? " Uni " : " I " , player ) ;
// if (cl_voip_play.ival)
Con_Footerf ( true , " ^[%sute \\ player \\ %i \\ action \\ mute^] " , cl . players [ player ] . vignored ? " Unm " : " M " , player ) ;
if ( ! cls . demoplayback & & ( * rcon_password . string
# ifndef CLIENTONLY
| | ( sv . state & & svs . clients [ player ] . netchan . remote_address . type ! = NA_LOOPBACK )
# endif
) )
{
Con_Footerf ( true , " ^[Kick \\ player \\ %i \\ action \\ kick^] " , player ) ;
Con_Footerf ( true , " ^[Ban \\ player \\ %i \\ action \\ ban^] " , player ) ;
}
}
else
{
char cmdprefix [ 6 ] ;
snprintf ( cmdprefix , sizeof ( cmdprefix ) , " %i " , i ) ;
//hey look! its you!
if ( cl . spectator | | cls . demoplayback )
{
//need join option here or something
}
else
{
Con_Footerf ( true , " ^[Suicide \\ cmd \\ kill^] " ) ;
# ifndef CLIENTONLY
if ( ! sv . state )
Con_Footerf ( true , " ^[Disconnect \\ cmd \\ disconnect^] " ) ;
if ( cls . allow_cheats | | ( sv . state & & sv . allocated_client_slots = = 1 ) )
# else
Con_Footerf ( true , " ^[Disconnect \\ cmd \\ disconnect^] " ) ;
if ( cls . allow_cheats )
# endif
{
Con_Footerf ( true , " ^[Noclip \\ cmd \\ noclip^] " ) ;
Con_Footerf ( true , " ^[Fly \\ cmd \\ fly^] " ) ;
Con_Footerf ( true , " ^[God \\ cmd \\ god^] " ) ;
Con_Footerf ( true , " ^[Give \\ impulse \\ 9^] " ) ;
}
}
}
return ;
}
2013-03-12 22:35:33 +00:00
c = Info_ValueForKey ( info , " menu " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
2012-11-27 03:23:19 +00:00
{
2013-03-12 22:35:33 +00:00
Cbuf_AddText ( va ( " \n menu_cmd conlink %s \n " , c ) , RESTRICT_LOCAL ) ;
2012-11-27 03:23:19 +00:00
return ;
}
c = Info_ValueForKey ( info , " connect " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n connect %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2013-06-23 02:17:02 +00:00
c = Info_ValueForKey ( info , " join " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n join %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2013-07-13 12:14:32 +00:00
/*c = Info_ValueForKey(info, "url");
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n playfilm %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
} */
2013-06-23 02:17:02 +00:00
c = Info_ValueForKey ( info , " observe " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n observe %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2012-11-27 03:23:19 +00:00
c = Info_ValueForKey ( info , " qtv " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n qtvplay %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
c = Info_ValueForKey ( info , " demo " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n playdemo %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2014-03-30 08:55:06 +00:00
c = Info_ValueForKey ( info , " map " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n map %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2012-11-27 03:23:19 +00:00
c = Info_ValueForKey ( info , " cmd " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n cmd %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
c = Info_ValueForKey ( info , " edit " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n edit %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2012-11-27 03:23:19 +00:00
c = Info_ValueForKey ( info , " impulse " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n impulse %s \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2013-05-03 04:28:08 +00:00
c = Info_ValueForKey ( info , " film " ) ;
if ( * c & & ! strchr ( c , ' ; ' ) & & ! strchr ( c , ' \n ' ) )
{
Cbuf_AddText ( va ( " \n playfilm \" %s \" \n " , c ) , RESTRICT_LOCAL ) ;
return ;
}
2013-03-12 22:35:33 +00:00
c = Info_ValueForKey ( info , " desc " ) ;
if ( * c )
{
Con_Footerf ( false , " %s " , c ) ;
return ;
}
2014-03-30 08:55:06 +00:00
//if there's no info and the text starts with a leading / then insert it as a suggested/completed console command
//skip any leading colour code.
if ( text [ 0 ] = = ' ^ ' & & text [ 1 ] > = ' 0 ' & & text [ 1 ] < = ' 9 ' )
text + = 2 ;
if ( * text = = ' / ' )
2012-11-27 03:23:19 +00:00
{
2014-03-30 08:55:06 +00:00
int tlen = info - text ;
2013-04-13 08:15:18 +00:00
Z_Free ( key_lines [ edit_line ] ) ;
2014-03-30 08:55:06 +00:00
key_lines [ edit_line ] = BZ_Malloc ( tlen + 2 ) ;
2013-04-13 08:15:18 +00:00
key_lines [ edit_line ] [ 0 ] = ' ] ' ;
2014-03-30 08:55:06 +00:00
memcpy ( key_lines [ edit_line ] + 1 , text , tlen ) ;
key_lines [ edit_line ] [ 1 + tlen ] = 0 ;
2012-11-27 03:23:19 +00:00
key_linepos = strlen ( key_lines [ edit_line ] ) ;
return ;
}
}
2013-08-21 07:14:39 +00:00
void Key_ConsoleRelease ( console_t * con , int key , int unicode )
2006-02-06 01:06:17 +00:00
{
2012-10-13 00:56:31 +00:00
char * buffer ;
2014-04-03 02:16:21 +00:00
if ( key = = K_MOUSE1 & & con - > mousedown [ 2 ] = = 1 )
2012-10-13 00:56:31 +00:00
{
2013-08-21 07:14:39 +00:00
con - > mousedown [ 2 ] = 0 ;
if ( abs ( con - > mousedown [ 0 ] - con - > mousecursor [ 0 ] ) < 5 & & abs ( con - > mousedown [ 1 ] - con - > mousecursor [ 1 ] ) < 5 )
2012-10-13 00:56:31 +00:00
{
2013-11-21 23:02:28 +00:00
buffer = Con_CopyConsole ( false , false ) ;
2012-11-27 03:23:19 +00:00
Con_Footerf ( false , " " ) ;
2012-10-13 00:56:31 +00:00
if ( ! buffer )
return ;
if ( keydown [ K_SHIFT ] )
{
int len ;
len = strlen ( buffer ) ;
//strip any trailing dots/elipsis
while ( len > 1 & & ! strcmp ( buffer + len - 1 , " . " ) )
{
len - = 1 ;
buffer [ len ] = 0 ;
}
//strip any enclosing quotes
while ( * buffer = = ' \" ' & & len > 2 & & ! strcmp ( buffer + len - 1 , " \" " ) )
{
len - = 2 ;
memmove ( buffer , buffer + 1 , len ) ;
buffer [ len ] = 0 ;
}
Key_ConsoleInsert ( buffer ) ;
}
else
{
if ( buffer [ 0 ] = = ' ^ ' & & buffer [ 1 ] = = ' [ ' )
{
//looks like it might be a link!
char * end = NULL ;
char * info ;
for ( info = buffer + 2 ; * info ; )
{
if ( info [ 0 ] = = ' ^ ' & & info [ 1 ] = = ' ] ' )
{
break ;
}
if ( * info = = ' \\ ' )
break ;
else if ( info [ 0 ] = = ' ^ ' & & info [ 1 ] = = ' ^ ' )
info + = 2 ;
else
info + + ;
}
for ( end = info ; * end ; )
{
if ( end [ 0 ] = = ' ^ ' & & end [ 1 ] = = ' ] ' )
{
//okay, its a valid link that they clicked
* end = 0 ;
2013-06-23 02:17:02 +00:00
# ifdef PLUGINS
if ( ! Plug_ConsoleLink ( buffer + 2 , info ) )
# endif
2012-10-13 00:56:31 +00:00
# ifdef CSQC_DAT
if ( ! CSQC_ConsoleLink ( buffer + 2 , info ) )
# endif
{
2012-11-27 03:23:19 +00:00
Key_DefaultLinkClicked ( buffer + 2 , info ) ;
2012-10-13 00:56:31 +00:00
}
break ;
}
if ( end [ 0 ] = = ' ^ ' & & end [ 1 ] = = ' ^ ' )
end + = 2 ;
else
end + + ;
}
}
}
Z_Free ( buffer ) ;
}
2012-11-27 03:23:19 +00:00
else
Con_Footerf ( false , " " ) ;
2012-10-13 00:56:31 +00:00
}
2013-08-21 07:14:39 +00:00
if ( key = = K_MOUSE2 & & con - > mousedown [ 2 ] = = 2 )
2006-02-06 01:06:17 +00:00
{
2013-08-21 07:14:39 +00:00
con - > mousedown [ 2 ] = 0 ;
2013-11-21 23:02:28 +00:00
buffer = Con_CopyConsole ( true , false ) ; //don't keep markup if we're copying to the clipboard
2009-07-18 20:24:23 +00:00
if ( ! buffer )
return ;
Sys_SaveClipboard ( buffer ) ;
Z_Free ( buffer ) ;
2006-02-11 02:09:43 +00:00
2006-02-06 01:06:17 +00:00
}
}
2013-03-12 22:44:00 +00:00
//if the referenced (trailing) chevron is doubled up, then it doesn't act as part of any markup and should be ignored for such things.
static qboolean utf_specialchevron ( unsigned char * start , unsigned char * chev )
{
int count = 0 ;
while ( chev > = start )
{
if ( * chev - - = = ' ^ ' )
count + + ;
else
break ;
}
return count & 1 ;
}
2012-10-13 00:56:31 +00:00
//move the cursor one char to the left. cursor must be within the 'start' string.
2013-03-12 22:44:00 +00:00
static unsigned char * utf_left ( unsigned char * start , unsigned char * cursor )
2012-10-13 00:56:31 +00:00
{
if ( cursor = = start )
return cursor ;
2013-03-12 22:44:00 +00:00
if ( 1 ) //com_parseutf8.ival>0)
2012-10-13 00:56:31 +00:00
{
cursor - - ;
while ( ( * cursor & 0xc0 ) = = 0x80 & & cursor > start )
cursor - - ;
}
else
cursor - - ;
2013-03-12 22:44:00 +00:00
//FIXME: should verify that the ^ isn't doubled.
if ( * cursor = = ' ] ' & & cursor > start & & utf_specialchevron ( start , cursor - 1 ) )
2012-10-13 00:56:31 +00:00
{
//just stepped onto a link
2012-11-27 03:23:19 +00:00
unsigned char * linkstart ;
2012-10-13 00:56:31 +00:00
linkstart = cursor - 1 ;
while ( linkstart > = start )
{
2013-03-12 22:44:00 +00:00
//FIXME: should verify that the ^ isn't doubled.
if ( utf_specialchevron ( start , linkstart ) & & linkstart [ 1 ] = = ' [ ' )
2012-10-13 00:56:31 +00:00
return linkstart ;
linkstart - - ;
}
}
return cursor ;
}
//move the cursor one char to the right.
2013-03-12 22:44:00 +00:00
static unsigned char * utf_right ( unsigned char * start , unsigned char * cursor )
2012-10-13 00:56:31 +00:00
{
2013-03-12 22:44:00 +00:00
//FIXME: should make sure this is not doubled.
if ( utf_specialchevron ( start , cursor ) & & cursor [ 1 ] = = ' [ ' )
2012-10-13 00:56:31 +00:00
{
//just stepped over a link
char * linkend ;
linkend = cursor + 2 ;
while ( * linkend )
{
2013-03-12 22:44:00 +00:00
if ( utf_specialchevron ( start , linkend ) & & linkend [ 1 ] = = ' ] ' )
2012-10-13 00:56:31 +00:00
return linkend + 2 ;
else
linkend + + ;
}
return linkend ;
}
2013-03-12 22:44:00 +00:00
if ( 1 ) //com_parseutf8.ival>0)
2012-10-13 00:56:31 +00:00
{
int skip = 1 ;
//figure out the length of the char
if ( ( * cursor & 0xc0 ) = = 0x80 )
skip = 1 ; //error
else if ( ( * cursor & 0xe0 ) = = 0xc0 )
skip = 2 ;
else if ( ( * cursor & 0xf0 ) = = 0xe0 )
skip = 3 ;
else if ( ( * cursor & 0xf1 ) = = 0xf0 )
skip = 4 ;
else if ( ( * cursor & 0xf3 ) = = 0xf1 )
skip = 5 ;
else if ( ( * cursor & 0xf7 ) = = 0xf3 )
skip = 6 ;
else if ( ( * cursor & 0xff ) = = 0xf7 )
skip = 7 ;
else skip = 1 ;
while ( * cursor & & skip )
{
cursor + + ;
skip - - ;
}
}
else if ( * cursor )
cursor + + ;
return cursor ;
}
2013-11-21 23:02:28 +00:00
void Key_EntryInsert ( unsigned char * * line , int * linepos , char * instext )
{
int i ;
int len , olen ;
char * old ;
if ( ! * instext )
return ;
old = ( * line ) ;
len = strlen ( instext ) ;
olen = strlen ( old ) ;
* line = BZ_Malloc ( olen + len + 1 ) ;
memcpy ( * line , old , * linepos ) ;
memcpy ( * line + * linepos , instext , len ) ;
memcpy ( * line + * linepos + len , old + * linepos , olen - * linepos + 1 ) ;
Z_Free ( old ) ;
for ( i = * linepos ; i < * linepos + len ; i + + )
{
if ( ( * line ) [ i ] = = ' \r ' )
( * line ) [ i ] = ' ' ;
else if ( ( * line ) [ i ] = = ' \n ' )
( * line ) [ i ] = ' ; ' ;
}
* linepos + = len ;
}
qboolean Key_EntryLine ( unsigned char * * line , int lineoffset , int * linepos , int key , unsigned int unicode )
{
qboolean ctrl = keydown [ K_LCTRL ] | | keydown [ K_RCTRL ] ;
qboolean shift = keydown [ K_LSHIFT ] | | keydown [ K_RSHIFT ] ;
char utf8 [ 8 ] ;
if ( key = = K_LEFTARROW | | key = = K_KP_LEFTARROW )
{
if ( ctrl )
{
//ignore whitespace if we're at the end of the word
while ( * linepos > 0 & & ( * line ) [ * linepos - 1 ] = = ' ' )
* linepos = utf_left ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
//keep skipping until we find the start of that word
while ( ctrl & & * linepos > lineoffset & & ( * line ) [ * linepos - 1 ] ! = ' ' )
* linepos = utf_left ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
}
else
* linepos = utf_left ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
return true ;
}
if ( key = = K_RIGHTARROW | | key = = K_KP_RIGHTARROW )
{
if ( ( * line ) [ * linepos ] )
{
* linepos = utf_right ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
if ( ctrl )
{
//skip over the word
while ( ( * line ) [ * linepos ] & & ( * line ) [ * linepos ] ! = ' ' )
* linepos = utf_right ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
//as well as any trailing whitespace
while ( ( * line ) [ * linepos ] = = ' ' )
* linepos = utf_right ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( * line ) ;
}
return true ;
}
else
unicode = ' ' ;
}
if ( key = = K_DEL | | key = = K_KP_DEL )
{
if ( ( * line ) [ * linepos ] )
{
int charlen = utf_right ( ( * line ) + lineoffset , ( * line ) + * linepos ) - ( ( * line ) + * linepos ) ;
memmove ( ( * line ) + * linepos , ( * line ) + * linepos + charlen , strlen ( ( * line ) + * linepos + charlen ) + 1 ) ;
return true ;
}
else
key = K_BACKSPACE ;
}
if ( key = = K_BACKSPACE )
{
if ( * linepos > lineoffset )
{
int charlen = ( ( * line ) + * linepos ) - utf_left ( ( * line ) + lineoffset , ( * line ) + * linepos ) ;
memmove ( ( * line ) + * linepos - charlen , ( * line ) + * linepos , strlen ( ( * line ) + * linepos ) + 1 ) ;
* linepos - = charlen ;
}
if ( ! ( * line ) [ lineoffset ] ) //oops?
con_commandmatch = 0 ;
return true ;
}
if ( key = = K_HOME | | key = = K_KP_HOME )
{
* linepos = lineoffset ;
return true ;
}
if ( key = = K_END | | key = = K_KP_END )
{
* linepos = strlen ( * line ) ;
return true ;
}
//beware that windows translates ctrl+c and ctrl+v to a control char
if ( ( ( unicode = = ' C ' | | unicode = = ' c ' | | unicode = = 3 ) & & ctrl ) | | ( ctrl & & key = = K_INS ) )
{
Sys_SaveClipboard ( * line ) ;
return true ;
}
if ( ( ( unicode = = ' V ' | | unicode = = ' v ' | | unicode = = 22 ) & & ctrl ) | | ( shift & & key = = K_INS ) )
{
char * clipText = Sys_GetClipboard ( ) ;
if ( clipText )
{
Key_EntryInsert ( line , linepos , clipText ) ;
Sys_CloseClipboard ( clipText ) ;
}
return true ;
}
if ( unicode < ' ' )
{
//if the user is entering control codes, then the ctrl+foo mechanism is probably unsupported by the unicode input stuff, so give best-effort replacements.
switch ( unicode )
{
case 27 /*'['*/ : unicode = 0xe010 ; break ;
case 29 /*']'*/ : unicode = 0xe011 ; break ;
case 7 /*'g'*/ : unicode = 0xe086 ; break ;
case 18 /*'r'*/ : unicode = 0xe087 ; break ;
case 25 /*'y'*/ : unicode = 0xe088 ; break ;
case 2 /*'b'*/ : unicode = 0xe089 ; break ;
case 19 /*'s'*/ : unicode = 0xe080 ; break ;
case 4 /*'d'*/ : unicode = 0xe081 ; break ;
case 6 /*'f'*/ : unicode = 0xe082 ; break ;
case 1 /*'a'*/ : unicode = 0xe083 ; break ;
case 21 /*'u'*/ : unicode = 0xe01d ; break ;
case 9 /*'i'*/ : unicode = 0xe01e ; break ;
case 15 /*'o'*/ : unicode = 0xe01f ; break ;
case 10 /*'j'*/ : unicode = 0xe01c ; break ;
case 16 /*'p'*/ : unicode = 0xe09c ; break ;
case 13 /*'m'*/ : unicode = 0xe08b ; break ;
case 11 /*'k'*/ : unicode = 0xe08d ; break ;
case 14 /*'n'*/ : unicode = ' \r ' ; break ;
default :
// if (unicode)
// Con_Printf("escape code %i\n", unicode);
//even if we don't print these, we still need to cancel them in the caller.
if ( key = = K_LALT | | key = = K_RALT | |
key = = K_LCTRL | | key = = K_RCTRL | |
key = = K_LSHIFT | | key = = K_RSHIFT )
return true ;
return false ;
}
}
else if ( com_parseutf8 . ival > = 0 ) //don't do this for iso8859-1. the major user of that is hexen2 which doesn't have these chars.
{
if ( ctrl & & ! keydown [ K_RALT ] )
{
if ( unicode > = ' 0 ' & & unicode < = ' 9 ' )
unicode = unicode - ' 0 ' + 0xe012 ; // yellow number
else switch ( unicode )
{
case ' [ ' : unicode = 0xe010 ; break ;
case ' ] ' : unicode = 0xe011 ; break ;
case ' g ' : unicode = 0xe086 ; break ;
case ' r ' : unicode = 0xe087 ; break ;
case ' y ' : unicode = 0xe088 ; break ;
case ' b ' : unicode = 0xe089 ; break ;
case ' ( ' : unicode = 0xe080 ; break ;
case ' = ' : unicode = 0xe081 ; break ;
case ' ) ' : unicode = 0xe082 ; break ;
case ' a ' : unicode = 0xe083 ; break ;
case ' < ' : unicode = 0xe01d ; break ;
case ' - ' : unicode = 0xe01e ; break ;
case ' > ' : unicode = 0xe01f ; break ;
case ' , ' : unicode = 0xe01c ; break ;
case ' . ' : unicode = 0xe09c ; break ;
case ' B ' : unicode = 0xe08b ; break ;
case ' C ' : unicode = 0xe08d ; break ;
case ' n ' : unicode = ' \r ' ; break ;
}
}
if ( keydown [ K_LALT ] & & unicode > 32 & & unicode < 128 )
unicode | = 0xe080 ; // red char
}
unicode = utf8_encode ( utf8 , unicode , sizeof ( utf8 ) - 1 ) ;
if ( unicode )
{
utf8 [ unicode ] = 0 ;
Key_EntryInsert ( line , linepos , utf8 ) ;
return true ;
}
return false ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
Key_Console
Interactive line editing and console scrollback
= = = = = = = = = = = = = = = = = = = =
*/
2013-08-21 07:14:39 +00:00
qboolean Key_Console ( console_t * con , unsigned int unicode , int key )
2004-08-23 00:15:46 +00:00
{
2013-05-11 14:02:55 +00:00
qboolean ctrl = keydown [ K_LCTRL ] | | keydown [ K_RCTRL ] ;
qboolean shift = keydown [ K_LSHIFT ] | | keydown [ K_RSHIFT ] ;
2004-08-23 00:15:46 +00:00
2013-04-13 08:15:18 +00:00
//weirdness for the keypad.
if ( ( unicode > = ' 0 ' & & unicode < = ' 9 ' ) | | unicode = = ' . ' )
key = 0 ;
2013-08-21 07:14:39 +00:00
if ( con - > redirect )
2004-08-23 00:15:46 +00:00
{
if ( key = = K_TAB )
{ // command completion
2013-05-11 14:02:55 +00:00
if ( ctrl | | shift )
2004-08-23 00:15:46 +00:00
{
Con_CycleConsole ( ) ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
}
2013-08-21 07:14:39 +00:00
con - > redirect ( con_current , key ) ;
return true ;
2004-08-23 00:15:46 +00:00
}
2006-02-02 01:13:52 +00:00
2006-02-06 01:06:17 +00:00
if ( ( key = = K_MOUSE1 | | key = = K_MOUSE2 ) )
2006-02-02 01:13:52 +00:00
{
2013-11-21 23:02:28 +00:00
// int xpos = (int)((con->mousecursor[0]*vid.width)/(vid.pixelwidth*8));
int ypos = ( int ) ( ( con - > mousecursor [ 1 ] * vid . height ) / ( vid . pixelheight * 8 ) ) ;
2013-08-21 07:14:39 +00:00
con - > mousedown [ 0 ] = con - > mousecursor [ 0 ] ;
con - > mousedown [ 1 ] = con - > mousecursor [ 1 ] ;
2013-06-26 03:38:27 +00:00
if ( ypos = = 0 & & con_mouseover )
2006-02-02 01:13:52 +00:00
{
2013-06-26 03:38:27 +00:00
if ( key = = K_MOUSE2 )
Con_Destroy ( con_mouseover ) ;
else
con_current = con_mouseover ;
2006-02-02 01:13:52 +00:00
}
2006-02-11 02:09:43 +00:00
else if ( key = = K_MOUSE2 )
2013-08-21 07:14:39 +00:00
con - > mousedown [ 2 ] = 2 ;
2006-02-11 02:09:43 +00:00
else
2013-08-21 07:14:39 +00:00
con - > mousedown [ 2 ] = 1 ;
2006-02-11 02:09:43 +00:00
2013-08-21 07:14:39 +00:00
return true ;
2006-02-02 01:13:52 +00:00
}
2004-08-23 00:15:46 +00:00
2013-04-13 08:15:18 +00:00
if ( key = = K_ENTER | | key = = K_KP_ENTER )
2004-08-23 00:15:46 +00:00
{ // backslash text are commands, else chat
2005-03-10 03:55:18 +00:00
int oldl = edit_line ;
2012-11-27 03:23:19 +00:00
edit_line = ( edit_line + 1 ) & ( CON_EDIT_LINES_MASK ) ;
2004-08-23 00:15:46 +00:00
history_line = edit_line ;
2013-04-13 08:15:18 +00:00
Z_Free ( key_lines [ edit_line ] ) ;
key_lines [ edit_line ] = BZ_Malloc ( 2 ) ;
2004-08-23 00:15:46 +00:00
key_lines [ edit_line ] [ 0 ] = ' ] ' ;
key_lines [ edit_line ] [ 1 ] = ' \0 ' ;
key_linepos = 1 ;
2005-03-10 03:55:18 +00:00
2013-08-21 07:14:39 +00:00
if ( con - > linebuffered )
con - > linebuffered ( con , key_lines [ oldl ] + 1 ) ;
2013-03-12 22:44:00 +00:00
con_commandmatch = 0 ;
2005-03-10 03:55:18 +00:00
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2013-08-21 07:14:39 +00:00
if ( key = = K_SPACE & & ctrl & & con - > commandcompletion )
2004-08-23 00:15:46 +00:00
{
2012-11-27 03:23:19 +00:00
char * txt = key_lines [ edit_line ] + 1 ;
if ( * txt = = ' / ' )
txt + + ;
2013-08-21 07:14:39 +00:00
if ( Cmd_CompleteCommand ( txt , true , true , con - > commandcompletion , NULL ) )
2004-08-23 00:15:46 +00:00
{
CompleteCommand ( true ) ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
}
if ( key = = K_TAB )
{ // command completion
2013-05-11 14:02:55 +00:00
if ( shift )
2004-08-23 00:15:46 +00:00
{
Con_CycleConsole ( ) ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2013-08-21 07:14:39 +00:00
if ( con - > commandcompletion )
2013-05-11 14:02:55 +00:00
CompleteCommand ( ctrl ) ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2012-11-27 03:23:19 +00:00
if ( key ! = K_CTRL & & key ! = K_SHIFT & & con_commandmatch )
2004-08-23 00:15:46 +00:00
con_commandmatch = 1 ;
2013-04-13 08:15:18 +00:00
if ( key = = K_UPARROW | | key = = K_KP_UPARROW )
2004-08-23 00:15:46 +00:00
{
do
{
2012-11-27 03:23:19 +00:00
history_line = ( history_line - 1 ) & CON_EDIT_LINES_MASK ;
2004-08-23 00:15:46 +00:00
} while ( history_line ! = edit_line
& & ! key_lines [ history_line ] [ 1 ] ) ;
if ( history_line = = edit_line )
2012-11-27 03:23:19 +00:00
history_line = ( edit_line + 1 ) & CON_EDIT_LINES_MASK ;
2013-04-13 08:15:18 +00:00
key_lines [ edit_line ] = BZ_Realloc ( key_lines [ edit_line ] , strlen ( key_lines [ history_line ] ) + 1 ) ;
2004-08-23 00:15:46 +00:00
Q_strcpy ( key_lines [ edit_line ] , key_lines [ history_line ] ) ;
key_linepos = Q_strlen ( key_lines [ edit_line ] ) ;
key_lines [ edit_line ] [ 0 ] = ' ] ' ;
2013-03-12 22:44:00 +00:00
if ( ! key_lines [ edit_line ] [ 1 ] )
con_commandmatch = 0 ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2013-04-13 08:15:18 +00:00
if ( key = = K_DOWNARROW | | key = = K_KP_DOWNARROW )
2004-08-23 00:15:46 +00:00
{
2004-10-03 10:17:15 +00:00
if ( history_line = = edit_line )
{
key_lines [ edit_line ] [ 0 ] = ' ] ' ;
key_lines [ edit_line ] [ 1 ] = ' \0 ' ;
key_linepos = 1 ;
2013-03-12 22:44:00 +00:00
con_commandmatch = 0 ;
2013-08-21 07:14:39 +00:00
return true ;
2004-10-03 10:17:15 +00:00
}
2004-08-23 00:15:46 +00:00
do
{
2012-11-27 03:23:19 +00:00
history_line = ( history_line + 1 ) & CON_EDIT_LINES_MASK ;
2004-08-23 00:15:46 +00:00
}
while ( history_line ! = edit_line
& & ! key_lines [ history_line ] [ 1 ] ) ;
if ( history_line = = edit_line )
{
key_lines [ edit_line ] [ 0 ] = ' ] ' ;
2009-10-06 23:37:05 +00:00
key_lines [ edit_line ] [ 1 ] = ' \0 ' ;
2004-08-23 00:15:46 +00:00
key_linepos = 1 ;
}
else
{
2013-04-13 08:15:18 +00:00
key_lines [ edit_line ] = BZ_Realloc ( key_lines [ edit_line ] , strlen ( key_lines [ history_line ] ) + 1 ) ;
2004-08-23 00:15:46 +00:00
Q_strcpy ( key_lines [ edit_line ] , key_lines [ history_line ] ) ;
key_linepos = Q_strlen ( key_lines [ edit_line ] ) ;
}
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2013-04-13 08:15:18 +00:00
if ( key = = K_PGUP | | key = = K_KP_PGUP | | key = = K_MWHEELUP )
2004-08-23 00:15:46 +00:00
{
2009-07-05 18:45:53 +00:00
int i = 2 ;
2013-05-11 14:02:55 +00:00
if ( ctrl )
2009-07-05 18:45:53 +00:00
i = 8 ;
2013-08-21 07:14:39 +00:00
if ( ! con - > display )
return true ;
if ( con - > display = = con - > current )
2009-07-05 18:45:53 +00:00
i + = 2 ; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line
while ( i - - > 0 )
2007-08-05 01:21:18 +00:00
{
2013-08-21 07:14:39 +00:00
if ( con - > display - > older = = NULL )
2009-07-05 18:45:53 +00:00
break ;
2013-08-21 07:14:39 +00:00
con - > display = con - > display - > older ;
2007-08-05 01:21:18 +00:00
}
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2013-04-13 08:15:18 +00:00
if ( key = = K_PGDN | | key = = K_KP_PGDN | | key = = K_MWHEELDOWN )
2004-08-23 00:15:46 +00:00
{
2009-07-05 18:45:53 +00:00
int i = 2 ;
2013-05-11 14:02:55 +00:00
if ( ctrl )
2009-07-05 18:45:53 +00:00
i = 8 ;
2013-08-21 07:14:39 +00:00
if ( ! con - > display )
return true ;
2009-07-05 18:45:53 +00:00
while ( i - - > 0 )
{
2013-08-21 07:14:39 +00:00
if ( con - > display - > newer = = NULL )
2009-07-05 18:45:53 +00:00
break ;
2013-08-21 07:14:39 +00:00
con - > display = con - > display - > newer ;
2009-07-05 18:45:53 +00:00
}
2013-08-21 07:14:39 +00:00
if ( con - > display - > newer & & con - > display - > newer = = con - > current )
con - > display = con - > current ;
return true ;
2004-08-23 00:15:46 +00:00
}
2013-11-21 23:02:28 +00:00
if ( ( key = = K_HOME | | key = = K_KP_HOME ) & & ctrl )
2004-08-23 00:15:46 +00:00
{
2013-11-21 23:02:28 +00:00
con - > display = con - > oldest ;
2013-08-21 07:14:39 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2006-02-01 22:36:12 +00:00
2013-11-21 23:02:28 +00:00
if ( ( key = = K_END | | key = = K_KP_END ) & & ctrl )
2010-05-01 22:47:47 +00:00
{
2013-11-21 23:02:28 +00:00
con - > display = con - > current ;
2013-08-21 07:14:39 +00:00
return true ;
2013-03-12 22:40:16 +00:00
}
2013-08-27 13:18:09 +00:00
2013-11-21 23:02:28 +00:00
return Key_EntryLine ( & key_lines [ edit_line ] , 1 , & key_linepos , key , unicode ) ;
2004-08-23 00:15:46 +00:00
}
//============================================================================
qboolean chat_team ;
2013-11-21 23:02:28 +00:00
unsigned char * chat_buffer ;
int chat_bufferpos ;
2004-08-23 00:15:46 +00:00
2009-07-21 00:48:19 +00:00
void Key_Message ( int key , int unicode )
2004-08-23 00:15:46 +00:00
{
2013-11-21 23:02:28 +00:00
if ( ! chat_buffer )
{
chat_buffer = BZ_Malloc ( 1 ) ;
chat_buffer [ 0 ] = 0 ;
chat_bufferpos = 0 ;
}
2004-08-23 00:15:46 +00:00
2013-05-03 04:28:08 +00:00
if ( key = = K_ENTER | | key = = K_KP_ENTER )
2004-08-23 00:15:46 +00:00
{
2013-11-21 23:02:28 +00:00
if ( chat_buffer & & chat_buffer [ 0 ] )
2005-07-16 00:53:08 +00:00
{ //send it straight into the command.
2013-11-21 23:02:28 +00:00
char * line = chat_buffer ;
char deutf8 [ 8192 ] ;
if ( com_parseutf8 . ival < = 0 )
{
unsigned int unicode ;
int err ;
int len = 0 ;
while ( * line )
{
unicode = utf8_decode ( & err , line , & line ) ;
2014-01-13 02:42:25 +00:00
len + = unicode_encode ( deutf8 + len , unicode , sizeof ( deutf8 ) - 1 - len , true ) ;
2013-11-21 23:02:28 +00:00
}
deutf8 [ len ] = 0 ;
line = deutf8 ;
}
Cmd_TokenizeString ( va ( " %s %s " , chat_team ? " say_team " : " say " , line ) , true , false ) ;
2005-07-16 00:53:08 +00:00
CL_Say ( chat_team , " " ) ;
}
2004-08-23 00:15:46 +00:00
2013-10-08 14:28:11 +00:00
Key_Dest_Remove ( kdm_message ) ;
2013-11-21 23:02:28 +00:00
chat_bufferpos = 0 ;
2004-08-23 00:15:46 +00:00
chat_buffer [ 0 ] = 0 ;
return ;
}
if ( key = = K_ESCAPE )
{
2013-10-08 14:28:11 +00:00
Key_Dest_Remove ( kdm_message ) ;
2013-11-21 23:02:28 +00:00
chat_bufferpos = 0 ;
2004-08-23 00:15:46 +00:00
chat_buffer [ 0 ] = 0 ;
return ;
}
2013-11-21 23:02:28 +00:00
Key_EntryLine ( & chat_buffer , 0 , & chat_bufferpos , key , unicode ) ;
2004-08-23 00:15:46 +00:00
}
//============================================================================
2005-07-05 23:46:10 +00:00
char * Key_GetBinding ( int keynum )
{
if ( keynum > = 0 & & keynum < K_MAX )
return keybindings [ keynum ] [ 0 ] ;
return NULL ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = =
Key_StringToKeynum
Returns a key number to be used to index keybindings [ ] by looking at
the given string . Single ascii characters return themselves , while
the K_ * names are matched up .
= = = = = = = = = = = = = = = = = = =
*/
2014-03-30 08:55:06 +00:00
int Key_StringToKeynum ( const char * str , int * modifier )
2004-08-23 00:15:46 +00:00
{
keyname_t * kn ;
char * underscore ;
if ( ! strnicmp ( str , " std_ " , 4 ) )
* modifier = 0 ;
else
{
* modifier = 0 ;
while ( 1 )
{
underscore = strchr ( str , ' _ ' ) ;
if ( ! underscore | | ! underscore [ 1 ] )
break ; //nothing afterwards or no underscore.
if ( ! strnicmp ( str , " shift_ " , 6 ) )
* modifier | = 1 ;
else if ( ! strnicmp ( str , " alt_ " , 4 ) )
* modifier | = 2 ;
else if ( ! strnicmp ( str , " ctrl_ " , 5 ) )
* modifier | = 4 ;
else
break ;
str = underscore + 1 ; //next char.
}
if ( ! * modifier )
* modifier = ~ 0 ;
}
if ( ! str | | ! str [ 0 ] )
return - 1 ;
if ( ! str [ 1 ] ) //single char.
2009-07-05 18:45:53 +00:00
{
#if 0 //def _WIN32
return VkKeyScan ( str [ 0 ] ) ;
# else
2004-08-23 00:15:46 +00:00
return str [ 0 ] ;
2009-07-05 18:45:53 +00:00
# endif
}
2004-08-23 00:15:46 +00:00
2005-05-08 05:59:05 +00:00
if ( ! strncmp ( str , " K_ " , 2 ) )
str + = 2 ;
2004-08-23 00:15:46 +00:00
for ( kn = keynames ; kn - > name ; kn + + )
{
if ( ! Q_strcasecmp ( str , kn - > name ) )
return kn - > keynum ;
}
if ( atoi ( str ) ) //assume ascii code. (prepend with a 0 if needed)
2009-07-05 18:45:53 +00:00
{
2004-08-23 00:15:46 +00:00
return atoi ( str ) ;
2009-07-05 18:45:53 +00:00
}
2004-08-23 00:15:46 +00:00
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = = =
Key_KeynumToString
Returns a string ( either a single ascii char , or a K_ * name ) for the
given keynum .
FIXME : handle quote special ( general escape sequence ? )
= = = = = = = = = = = = = = = = = = =
*/
char * Key_KeynumToString ( int keynum )
{
keyname_t * kn ;
static char tinystr [ 2 ] ;
if ( keynum = = - 1 )
return " <KEY NOT FOUND> " ;
if ( keynum > 32 & & keynum < 127 )
{ // printable ascii
tinystr [ 0 ] = keynum ;
tinystr [ 1 ] = 0 ;
return tinystr ;
}
for ( kn = keynames ; kn - > name ; kn + + )
if ( keynum = = kn - > keynum )
return kn - > name ;
{
2008-01-28 13:27:30 +00:00
if ( keynum < 10 ) //don't let it be a single character
2004-08-23 00:15:46 +00:00
return va ( " 0%i " , keynum ) ;
return va ( " %i " , keynum ) ;
}
return " <UNKNOWN KEYNUM> " ;
}
/*
= = = = = = = = = = = = = = = = = = =
Key_SetBinding
= = = = = = = = = = = = = = = = = = =
*/
void Key_SetBinding ( int keynum , int modifier , char * binding , int level )
{
2006-06-02 17:42:36 +00:00
char * newc ;
2004-08-23 00:15:46 +00:00
int l ;
2007-10-08 12:56:17 +00:00
if ( modifier = = ~ 0 ) //all of the possibilities.
2004-08-23 00:15:46 +00:00
{
for ( l = 0 ; l < KEY_MODIFIERSTATES ; l + + )
Key_SetBinding ( keynum , l , binding , level ) ;
return ;
}
2013-03-12 22:40:16 +00:00
if ( keynum < 0 | | keynum > = K_MAX )
2004-08-23 00:15:46 +00:00
return ;
2013-03-12 22:40:16 +00:00
//just so the quit menu realises it needs to show something.
Cvar_ConfigChanged ( ) ;
2004-08-23 00:15:46 +00:00
// free old bindings
if ( keybindings [ keynum ] [ modifier ] )
{
Z_Free ( keybindings [ keynum ] [ modifier ] ) ;
keybindings [ keynum ] [ modifier ] = NULL ;
}
if ( ! binding )
{
keybindings [ keynum ] [ modifier ] = NULL ;
return ;
}
// allocate memory for new binding
l = Q_strlen ( binding ) ;
2006-06-02 17:42:36 +00:00
newc = Z_Malloc ( l + 1 ) ;
Q_strcpy ( newc , binding ) ;
newc [ l ] = 0 ;
keybindings [ keynum ] [ modifier ] = newc ;
2004-08-23 00:15:46 +00:00
bindcmdlevel [ keynum ] [ modifier ] = level ;
}
/*
= = = = = = = = = = = = = = = = = = =
Key_Unbind_f
= = = = = = = = = = = = = = = = = = =
*/
void Key_Unbind_f ( void )
{
int b , modifier ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_Printf ( " unbind <key> : remove commands from a key \n " ) ;
return ;
}
b = Key_StringToKeynum ( Cmd_Argv ( 1 ) , & modifier ) ;
if ( b = = - 1 )
{
2013-12-29 22:48:28 +00:00
if ( cl_warncmd . ival )
Con_Printf ( " \" %s \" isn't a valid key \n " , Cmd_Argv ( 1 ) ) ;
2004-08-23 00:15:46 +00:00
return ;
}
Key_SetBinding ( b , modifier , NULL , Cmd_ExecLevel ) ;
}
void Key_Unbindall_f ( void )
{
int i ;
2005-07-05 23:46:10 +00:00
for ( i = 0 ; i < K_MAX ; i + + )
2004-08-23 00:15:46 +00:00
if ( keybindings [ i ] )
Key_SetBinding ( i , ~ 0 , NULL , Cmd_ExecLevel ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
Key_Bind_f
= = = = = = = = = = = = = = = = = = =
*/
2004-09-20 23:25:38 +00:00
void Key_Bind_f ( void )
2004-08-23 00:15:46 +00:00
{
int i , c , b , modifier ;
char cmd [ 1024 ] ;
c = Cmd_Argc ( ) ;
2004-09-20 23:25:38 +00:00
if ( c < 2 )
2004-08-23 00:15:46 +00:00
{
Con_Printf ( " bind <key> [command] : attach a command to a key \n " ) ;
return ;
}
b = Key_StringToKeynum ( Cmd_Argv ( 1 ) , & modifier ) ;
if ( b = = - 1 )
{
2013-12-29 22:48:28 +00:00
if ( cl_warncmd . ival )
Con_Printf ( " \" %s \" isn't a valid key \n " , Cmd_Argv ( 1 ) ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( c = = 2 )
{
2014-05-16 01:34:58 +00:00
if ( modifier = = ~ 0 ) //modifier unspecified. default to no modifier
modifier = 0 ;
if ( keybindings [ b ] [ modifier ] )
Con_Printf ( " \" %s \" = \" %s \" \n " , Cmd_Argv ( 1 ) , keybindings [ b ] [ modifier ] ) ;
2004-08-23 00:15:46 +00:00
else
Con_Printf ( " \" %s \" is not bound \n " , Cmd_Argv ( 1 ) ) ;
return ;
}
2004-09-20 23:25:38 +00:00
if ( c > 3 )
{
2004-12-08 04:14:52 +00:00
Cmd_ShiftArgs ( 1 , Cmd_ExecLevel = = RESTRICT_LOCAL ) ;
2004-09-20 23:25:38 +00:00
Key_SetBinding ( b , modifier , Cmd_Args ( ) , Cmd_ExecLevel ) ;
return ;
}
2004-08-23 00:15:46 +00:00
// copy the rest of the command line
cmd [ 0 ] = 0 ; // start out with a null string
for ( i = 2 ; i < c ; i + + )
{
2007-08-30 02:31:47 +00:00
Q_strncatz ( cmd , Cmd_Argv ( i ) , sizeof ( cmd ) ) ;
2004-08-23 00:15:46 +00:00
if ( i ! = ( c - 1 ) )
2007-08-30 02:31:47 +00:00
Q_strncatz ( cmd , " " , sizeof ( cmd ) ) ;
2004-08-23 00:15:46 +00:00
}
Key_SetBinding ( b , modifier , cmd , Cmd_ExecLevel ) ;
}
void Key_BindLevel_f ( void )
{
int i , c , b , modifier ;
char cmd [ 1024 ] ;
c = Cmd_Argc ( ) ;
if ( c ! = 2 & & c ! = 3 )
{
Con_Printf ( " bindat <key> [<level> <command>] : attach a command to a key for a specific level of access \n " ) ;
return ;
}
b = Key_StringToKeynum ( Cmd_Argv ( 1 ) , & modifier ) ;
if ( b = = - 1 )
{
2013-12-29 22:48:28 +00:00
if ( cl_warncmd . ival )
Con_Printf ( " \" %s \" isn't a valid key \n " , Cmd_Argv ( 1 ) ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2014-03-30 08:55:06 +00:00
if ( modifier = = ~ 0 ) //modifier unspecified. default to no modifier
modifier = 0 ;
2004-08-23 00:15:46 +00:00
if ( c = = 2 )
{
2014-03-30 08:55:06 +00:00
if ( keybindings [ b ] [ modifier ] )
2004-08-23 00:15:46 +00:00
Con_Printf ( " \" %s \" (%i)= \" %s \" \n " , Cmd_Argv ( 1 ) , bindcmdlevel [ b ] [ modifier ] , keybindings [ b ] [ modifier ] ) ;
else
Con_Printf ( " \" %s \" is not bound \n " , Cmd_Argv ( 1 ) ) ;
return ;
}
2005-04-16 16:21:27 +00:00
if ( Cmd_IsInsecure ( ) )
2004-08-23 00:15:46 +00:00
{
Con_Printf ( " Server attempted usage of bindat \n " ) ;
return ;
}
// copy the rest of the command line
cmd [ 0 ] = 0 ; // start out with a null string
for ( i = 3 ; i < c ; i + + )
{
2007-08-30 02:31:47 +00:00
Q_strncatz ( cmd , Cmd_Argv ( i ) , sizeof ( cmd ) ) ;
2004-08-23 00:15:46 +00:00
if ( i ! = ( c - 1 ) )
2007-08-30 02:31:47 +00:00
Q_strncatz ( cmd , " " , sizeof ( cmd ) ) ;
2004-08-23 00:15:46 +00:00
}
Key_SetBinding ( b , modifier , cmd , atoi ( Cmd_Argv ( 2 ) ) ) ;
}
/*
= = = = = = = = = = = =
Key_WriteBindings
Writes lines containing " bind key value "
= = = = = = = = = = = =
*/
2005-12-21 03:07:33 +00:00
void Key_WriteBindings ( vfsfile_t * f )
2004-08-23 00:15:46 +00:00
{
2013-08-21 07:14:39 +00:00
const char * s ;
2004-08-23 00:15:46 +00:00
int i , m ;
char * binding , * base ;
char prefix [ 128 ] ;
2013-08-21 07:14:39 +00:00
char keybuf [ 256 ] ;
char commandbuf [ 2048 ] ;
2004-08-23 00:15:46 +00:00
2005-07-05 23:46:10 +00:00
for ( i = 0 ; i < K_MAX ; i + + ) //we rebind the key with all modifiers to get the standard bind, then change the specific ones.
2007-10-08 12:56:17 +00:00
{ //this does two things, it normally allows us to skip 7 of the 8 possibilities
2004-08-23 00:15:46 +00:00
base = keybindings [ i ] [ 0 ] ; //plus we can use the config with other clients.
if ( ! base )
base = " " ;
for ( m = 0 ; m < KEY_MODIFIERSTATES ; m + + )
{
binding = keybindings [ i ] [ m ] ;
if ( ! binding )
binding = " " ;
if ( strcmp ( binding , base ) | | ( m = = 0 & & keybindings [ i ] [ 0 ] ) | | bindcmdlevel [ i ] [ m ] ! = bindcmdlevel [ i ] [ 0 ] )
{
* prefix = ' \0 ' ;
if ( m & 4 )
strcat ( prefix , " CTRL_ " ) ;
if ( m & 2 )
strcat ( prefix , " ALT_ " ) ;
if ( m & 1 )
strcat ( prefix , " SHIFT_ " ) ;
2013-08-21 07:14:39 +00:00
s = va ( " %s%s " , prefix , Key_KeynumToString ( i ) ) ;
//quote it as required
if ( i = = ' ; ' | | i < = ' ' | | i = = ' \" ' )
s = COM_QuotedString ( s , keybuf , sizeof ( keybuf ) ) ;
2004-08-23 00:15:46 +00:00
if ( bindcmdlevel [ i ] [ m ] ! = bindcmdlevel [ i ] [ 0 ] )
2013-08-21 07:14:39 +00:00
s = va ( " bindlevel %s %i %s \n " , s , bindcmdlevel [ i ] [ m ] , COM_QuotedString ( binding , commandbuf , sizeof ( commandbuf ) ) ) ;
2004-08-23 00:15:46 +00:00
else
2013-08-21 07:14:39 +00:00
s = va ( " bind %s %s \n " , s , COM_QuotedString ( binding , commandbuf , sizeof ( commandbuf ) ) ) ;
2005-12-21 03:07:33 +00:00
VFS_WRITE ( f , s , strlen ( s ) ) ;
2004-08-23 00:15:46 +00:00
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = =
Key_Init
= = = = = = = = = = = = = = = = = = =
*/
void Key_Init ( void )
{
int i ;
2012-11-27 03:23:19 +00:00
for ( i = 0 ; i < = CON_EDIT_LINES_MASK ; i + + )
2004-08-23 00:15:46 +00:00
{
2013-04-13 08:15:18 +00:00
key_lines [ i ] = Z_Malloc ( 2 ) ;
2004-08-23 00:15:46 +00:00
key_lines [ i ] [ 0 ] = ' ] ' ;
}
key_linepos = 1 ;
2013-10-08 14:28:11 +00:00
key_dest_mask = kdm_game ;
key_dest_absolutemouse = kdm_console | kdm_editor ;
2004-08-23 00:15:46 +00:00
//
// init ascii characters in console mode
//
for ( i = 32 ; i < 128 ; i + + )
consolekeys [ i ] = true ;
consolekeys [ K_ENTER ] = true ;
2013-05-03 04:28:08 +00:00
consolekeys [ K_KP_ENTER ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_TAB ] = true ;
consolekeys [ K_LEFTARROW ] = true ;
consolekeys [ K_RIGHTARROW ] = true ;
consolekeys [ K_UPARROW ] = true ;
consolekeys [ K_DOWNARROW ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_LEFTARROW ] = true ;
consolekeys [ K_KP_RIGHTARROW ] = true ;
consolekeys [ K_KP_UPARROW ] = true ;
consolekeys [ K_KP_DOWNARROW ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_BACKSPACE ] = true ;
consolekeys [ K_DEL ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_DEL ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_HOME ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_HOME ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_END ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_END ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_PGUP ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_PGUP ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_PGDN ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_KP_PGDN ] = true ;
2013-05-11 14:02:55 +00:00
consolekeys [ K_LSHIFT ] = true ;
consolekeys [ K_RSHIFT ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ K_MWHEELUP ] = true ;
consolekeys [ K_MWHEELDOWN ] = true ;
2013-05-11 14:02:55 +00:00
consolekeys [ K_LCTRL ] = true ;
consolekeys [ K_RCTRL ] = true ;
2013-04-13 08:15:18 +00:00
consolekeys [ K_LALT ] = true ;
consolekeys [ K_RALT ] = true ;
2004-08-23 00:15:46 +00:00
consolekeys [ ' ` ' ] = false ;
consolekeys [ ' ~ ' ] = false ;
2006-02-02 01:13:52 +00:00
for ( i = K_MOUSE1 ; i < K_MOUSE10 ; i + + )
{
consolekeys [ i ] = true ;
}
consolekeys [ K_MWHEELUP ] = true ;
consolekeys [ K_MWHEELDOWN ] = true ;
2005-07-05 23:46:10 +00:00
for ( i = 0 ; i < K_MAX ; i + + )
2004-08-23 00:15:46 +00:00
keyshift [ i ] = i ;
for ( i = ' a ' ; i < = ' z ' ; i + + )
keyshift [ i ] = i - ' a ' + ' A ' ;
keyshift [ ' 1 ' ] = ' ! ' ;
keyshift [ ' 2 ' ] = ' @ ' ;
keyshift [ ' 3 ' ] = ' # ' ;
keyshift [ ' 4 ' ] = ' $ ' ;
keyshift [ ' 5 ' ] = ' % ' ;
keyshift [ ' 6 ' ] = ' ^ ' ;
keyshift [ ' 7 ' ] = ' & ' ;
keyshift [ ' 8 ' ] = ' * ' ;
keyshift [ ' 9 ' ] = ' ( ' ;
keyshift [ ' 0 ' ] = ' ) ' ;
keyshift [ ' - ' ] = ' _ ' ;
keyshift [ ' = ' ] = ' + ' ;
keyshift [ ' , ' ] = ' < ' ;
keyshift [ ' . ' ] = ' > ' ;
keyshift [ ' / ' ] = ' ? ' ;
keyshift [ ' ; ' ] = ' : ' ;
keyshift [ ' \' ' ] = ' " ' ;
keyshift [ ' [ ' ] = ' { ' ;
keyshift [ ' ] ' ] = ' } ' ;
keyshift [ ' ` ' ] = ' ~ ' ;
keyshift [ ' \\ ' ] = ' | ' ;
menubound [ K_ESCAPE ] = true ;
for ( i = 0 ; i < 12 ; i + + )
menubound [ K_F1 + i ] = true ;
//
// register our functions
//
Cmd_AddCommand ( " bind " , Key_Bind_f ) ;
Cmd_AddCommand ( " bindlevel " , Key_BindLevel_f ) ;
Cmd_AddCommand ( " unbind " , Key_Unbind_f ) ;
Cmd_AddCommand ( " unbindall " , Key_Unbindall_f ) ;
2006-02-11 02:09:43 +00:00
Cvar_Register ( & con_selectioncolour , " Console variables " ) ;
2008-11-09 22:29:28 +00:00
Cvar_Register ( & con_echochat , " Console variables " ) ;
2004-08-23 00:15:46 +00:00
}
2006-03-10 03:52:12 +00:00
qboolean Key_MouseShouldBeFree ( void )
{
//returns if the mouse should be a cursor or if it should go to the menu
//if true, the input code is expected to return mouse cursor positions rather than deltas
2009-10-06 23:37:05 +00:00
extern cvar_t cl_prydoncursor ;
2013-10-08 14:28:11 +00:00
if ( key_dest_absolutemouse & key_dest_mask )
2012-11-27 03:23:19 +00:00
return true ;
2012-10-14 09:00:49 +00:00
// if (!ActiveApp)
2009-07-25 11:05:06 +00:00
// return true;
2006-03-10 03:52:12 +00:00
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_menu ) )
2006-03-10 03:52:12 +00:00
{
2009-07-25 11:05:06 +00:00
if ( m_state = = m_complex | | m_state = = m_plugin /*|| m_state == m_menu_dat*/ )
2006-03-10 03:52:12 +00:00
return true ;
}
# ifdef VM_UI
if ( UI_MenuState ( ) )
2009-10-06 23:37:05 +00:00
return false ;
2006-03-10 03:52:12 +00:00
# endif
2012-10-08 04:36:10 +00:00
if ( Media_PlayingFullScreen ( ) )
return true ;
2009-10-06 23:37:05 +00:00
if ( cl_prydoncursor . ival )
return true ;
2006-03-10 03:52:12 +00:00
return false ;
}
2013-12-02 14:30:30 +00:00
int Sbar_TranslateHudClick ( void ) ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = =
Key_Event
Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt !
= = = = = = = = = = = = = = = = = = =
*/
2012-02-12 05:18:31 +00:00
void Key_Event ( int devid , int key , unsigned int unicode , qboolean down )
2004-08-23 00:15:46 +00:00
{
2014-03-30 08:55:06 +00:00
int bl , bkey ;
char * dc , * uc ;
2012-02-12 05:18:31 +00:00
char p [ 16 ] ;
2014-03-30 08:55:06 +00:00
int modifierstate ;
2014-04-24 01:53:01 +00:00
int conkey = consolekeys [ key ] | | ( ( unicode | | key = = ' ` ' ) & & ( key ! = ' ` ' | | key_linepos > 1 ) ) ; //if the input line is empty, allow ` to toggle the console, otherwise enter it as actual text.
2004-08-23 00:15:46 +00:00
2009-07-05 18:45:53 +00:00
// Con_Printf ("%i : %i : %i\n", key, unicode, down); //@@@
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
//bug: my keyboard doesn't fire release events if the other shift is already pressed.
//hack around that by just force-releasing eg left if right is pressed, but only on inital press to avoid potential infinite loops if the state got bad.
//ctrl+alt don't seem to have the problem.
//you can still see a difference in that
if ( key = = K_LSHIFT & & ! keydown [ K_LSHIFT ] & & keydown [ K_RSHIFT ] )
Key_Event ( devid , K_RSHIFT , 0 , false ) ;
if ( key = = K_RSHIFT & & ! keydown [ K_RSHIFT ] & & keydown [ K_LSHIFT ] )
Key_Event ( devid , K_LSHIFT , 0 , false ) ;
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
modifierstate = KeyModifier ( keydown [ K_LSHIFT ] | keydown [ K_RSHIFT ] , keydown [ K_LALT ] | keydown [ K_RALT ] , keydown [ K_LCTRL ] | keydown [ K_RCTRL ] ) ;
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
keydown [ key ] = down ;
2004-08-23 00:15:46 +00:00
if ( ! down )
key_repeats [ key ] = 0 ;
key_lastpress = key ;
key_count + + ;
if ( key_count < = 0 )
{
return ; // just catching keys for Con_NotifyBox
}
// update auto-repeat status
if ( down )
{
key_repeats [ key ] + + ;
// if (key >= 200 && !keybindings[key]) //is this too annoying?
// Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
}
2013-05-11 14:02:55 +00:00
if ( key = = K_LSHIFT | | key = = K_RSHIFT )
2009-07-05 18:45:53 +00:00
{
2013-05-11 14:02:55 +00:00
shift_down = keydown [ K_LSHIFT ] | keydown [ K_RSHIFT ] ;
2009-07-05 18:45:53 +00:00
}
2004-08-23 00:15:46 +00:00
2008-11-09 22:29:28 +00:00
if ( key = = K_ESCAPE )
if ( shift_down )
{
2014-08-27 08:41:31 +00:00
extern cvar_t con_stayhidden ;
2014-09-02 02:44:43 +00:00
if ( down & & con_stayhidden . ival < 2 )
2008-11-09 22:29:28 +00:00
{
2014-03-30 08:55:06 +00:00
if ( ! Key_Dest_Has ( kdm_console ) ) //don't toggle it when the console is already down. this allows typing blind to not care if its already active.
Con_ToggleConsole_Force ( ) ;
2008-11-09 22:29:28 +00:00
return ;
}
}
2005-05-13 10:42:48 +00:00
//yes, csqc is allowed to steal the escape key.
2013-10-08 14:28:11 +00:00
if ( key ! = ' ` ' & & ( ! down | | key ! = K_ESCAPE | | ( ! Key_Dest_Has ( ~ kdm_game ) & & ! shift_down ) ) )
if ( ! Key_Dest_Has ( ~ kdm_game ) & & ! Media_PlayingFullScreen ( ) )
2005-08-26 22:56:51 +00:00
{
2005-08-26 23:55:09 +00:00
# ifdef CSQC_DAT
2012-02-12 05:18:31 +00:00
if ( CSQC_KeyPress ( key , unicode , down , devid ) ) //give csqc a chance to handle it.
2005-05-13 10:42:48 +00:00
return ;
2005-08-26 23:55:09 +00:00
# endif
# ifdef VM_CG
2009-07-25 11:05:06 +00:00
if ( CG_KeyPress ( key , unicode , down ) )
2005-08-26 22:56:51 +00:00
return ;
2005-05-13 10:42:48 +00:00
# endif
2005-08-26 23:55:09 +00:00
}
2005-05-13 10:42:48 +00:00
2004-08-23 00:15:46 +00:00
//
// handle escape specialy, so the user can never unbind it
//
if ( key = = K_ESCAPE )
{
2005-09-09 23:40:55 +00:00
# ifdef VM_UI
2004-08-23 00:15:46 +00:00
# ifdef TEXTEDITOR
2014-05-10 13:42:13 +00:00
if ( ! Key_Dest_Has ( ~ kdm_game ) & & ! Key_Dest_Has ( kdm_console ) )
2004-08-23 00:15:46 +00:00
# endif
2005-05-13 10:42:48 +00:00
{
2012-04-24 07:59:11 +00:00
if ( down & & Media_PlayingFullScreen ( ) )
2010-03-14 14:35:56 +00:00
{
2013-05-03 04:28:08 +00:00
Media_StopFilm ( false ) ;
2010-03-14 14:35:56 +00:00
return ;
}
2009-07-25 11:05:06 +00:00
if ( UI_KeyPress ( key , unicode , down ) ) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu.
2005-05-08 05:59:05 +00:00
return ;
2005-05-13 10:42:48 +00:00
}
2005-09-09 23:40:55 +00:00
# endif
2005-05-08 05:59:05 +00:00
2004-08-23 00:15:46 +00:00
if ( ! down )
return ;
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_console ) )
2004-08-23 00:15:46 +00:00
{
2014-05-10 13:42:13 +00:00
Key_Dest_Remove ( kdm_console ) ;
if ( ! cls . state & & ! Key_Dest_Has ( ~ kdm_game ) )
2013-10-08 14:28:11 +00:00
M_ToggleMenu_f ( ) ;
}
2013-10-08 16:13:18 +00:00
# ifdef TEXTEDITOR
2013-10-08 14:28:11 +00:00
else if ( Key_Dest_Has ( kdm_editor ) )
2009-07-25 11:05:06 +00:00
Editor_Key ( key , unicode ) ;
2013-10-08 16:13:18 +00:00
# endif
2013-10-08 14:28:11 +00:00
else if ( Key_Dest_Has ( kdm_menu ) )
M_Keydown ( key , unicode ) ;
else if ( Key_Dest_Has ( kdm_message ) )
Key_Dest_Remove ( kdm_message ) ;
else
{
2006-03-06 01:41:09 +00:00
if ( Media_PlayingFullScreen ( ) )
2004-08-27 00:40:01 +00:00
{
2013-05-03 04:28:08 +00:00
Media_StopFilm ( true ) ;
2013-10-08 14:28:11 +00:00
if ( ! cls . state )
M_ToggleMenu_f ( ) ;
2004-08-27 00:40:01 +00:00
}
2013-04-13 08:15:18 +00:00
else
M_ToggleMenu_f ( ) ;
2004-08-23 00:15:46 +00:00
}
return ;
}
//
// key up events only generate commands if the game key binding is
// a button command (leading + sign). These will occur even in console mode,
// to keep the character from continuing an action started before a console
// switch. Button commands include the keynum as a parameter, so multiple
// downs can be matched with ups
//
if ( ! down )
{
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_console ) )
2004-08-23 00:15:46 +00:00
{
2013-08-21 07:14:39 +00:00
con_current - > mousecursor [ 0 ] = mousecursor_x ;
con_current - > mousecursor [ 1 ] = mousecursor_y ;
Key_ConsoleRelease ( con_current , key , unicode ) ;
2004-08-23 00:15:46 +00:00
}
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_menu ) )
M_Keyup ( key , unicode ) ;
2013-10-08 16:13:18 +00:00
# ifndef NOMEDIA
2013-10-08 14:28:11 +00:00
if ( Media_PlayingFullScreen ( ) )
Media_Send_KeyEvent ( NULL , key , unicode , down ? 0 : 1 ) ;
2013-10-08 16:13:18 +00:00
# endif
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
uc = releasecommand [ key ] [ devid % MAX_INDEVS ] ;
if ( uc ) //this wasn't down, so don't crash on bad commands.
2004-08-23 00:15:46 +00:00
{
2014-03-30 08:55:06 +00:00
releasecommand [ key ] [ devid % MAX_INDEVS ] = NULL ;
Cbuf_AddText ( uc , releasecommandlevel [ key ] [ devid % MAX_INDEVS ] ) ;
Z_Free ( uc ) ;
2004-08-23 00:15:46 +00:00
}
return ;
}
//
// during demo playback, most keys bring up the main menu
//
2014-08-16 05:33:50 +00:00
if ( cls . demoplayback & & cls . demoplayback ! = DPB_MVD & & cls . demoplayback ! = DPB_EZTV & & down & & conkey & & ! Key_Dest_Has ( ~ kdm_game ) )
{
switch ( key )
{ //these keys don't force the menu to appear while playing the demo reel
case K_LSHIFT :
case K_RSHIFT :
case K_LALT :
case K_RALT :
case K_LCTRL :
// case K_RCTRL:
break ;
default :
dc = keybindings [ key ] [ modifierstate ] ;
//toggleconsole or +showFOO keys should do their regular bind action
if ( ! dc | | ( strcmp ( dc , " toggleconsole " ) & & strncmp ( dc , " +show " , 5 ) ) )
{
M_ToggleMenu_f ( ) ;
return ;
}
}
2004-08-23 00:15:46 +00:00
}
//
// if not a consolekey, send to the interpreter no matter what mode is
//
2005-09-09 23:40:55 +00:00
# ifdef VM_UI
2005-08-26 22:56:51 +00:00
if ( key ! = ' ` ' & & key ! = ' ~ ' )
2013-10-08 14:28:11 +00:00
if ( ! Key_Dest_Has ( ~ kdm_game ) | | ! down )
2004-08-23 00:15:46 +00:00
{
2009-07-25 11:05:06 +00:00
if ( UI_KeyPress ( key , unicode , down ) & & down ) //UI is allowed to take these keydowns. Keyups are always maintained.
2004-08-23 00:15:46 +00:00
return ;
}
2005-09-09 23:40:55 +00:00
# endif
2004-08-23 00:15:46 +00:00
2013-10-08 14:28:11 +00:00
if ( conkey & & Key_Dest_Has ( kdm_console ) )
2004-08-23 00:15:46 +00:00
{
2013-10-08 14:28:11 +00:00
con_current - > mousecursor [ 0 ] = mousecursor_x ;
con_current - > mousecursor [ 1 ] = mousecursor_y ;
Key_Console ( con_current , unicode , key ) ;
return ;
}
2013-10-08 16:13:18 +00:00
# ifdef TEXTEDITOR
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_editor ) )
{
Editor_Key ( key , unicode ) ;
return ;
}
2013-10-08 16:13:18 +00:00
# endif
2013-10-08 14:28:11 +00:00
if ( Key_Dest_Has ( kdm_menu ) )
{
M_Keydown ( key , unicode ) ;
return ;
}
if ( Key_Dest_Has ( kdm_message ) )
{
Key_Message ( key , unicode ) ;
return ;
}
2013-10-08 16:13:18 +00:00
# ifndef NOMEDIA
2013-10-08 14:28:11 +00:00
if ( Media_PlayingFullScreen ( ) )
{
Media_Send_KeyEvent ( NULL , key , unicode , down ? 0 : 1 ) ;
return ;
}
2013-10-08 16:13:18 +00:00
# endif
2011-07-19 12:34:49 +00:00
2013-10-08 14:28:11 +00:00
//anything else is a key binding.
2012-02-12 05:18:31 +00:00
2013-10-08 14:28:11 +00:00
/*don't auto-repeat binds as it breaks too many scripts*/
if ( key_repeats [ key ] > 1 )
return ;
2012-02-12 05:18:31 +00:00
2014-07-12 06:56:17 +00:00
//first player is normally assumed anyway.
2013-10-08 14:28:11 +00:00
if ( devid )
Q_snprintfz ( p , sizeof ( p ) , " p %i " , devid + 1 ) ;
else
* p = 0 ;
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
dc = keybindings [ key ] [ modifierstate ] ;
bl = bindcmdlevel [ key ] [ modifierstate ] ;
2004-08-23 00:15:46 +00:00
2014-03-30 08:55:06 +00:00
//simulate singular shift+alt+ctrl for binds (no left/right). really though, this code should translate to csqc/menu keycodes and back to resolve the weirdness instead.
if ( key = = K_RALT & & ( ! dc | | ! * dc ) )
2013-12-02 14:30:30 +00:00
{
2014-03-30 08:55:06 +00:00
bkey = K_LALT ;
dc = keybindings [ bkey ] [ modifierstate ] ;
bl = bindcmdlevel [ bkey ] [ modifierstate ] ;
2013-12-02 14:30:30 +00:00
}
2014-03-30 08:55:06 +00:00
else if ( key = = K_RCTRL & & ( ! dc | | ! * dc ) )
{
bkey = K_LCTRL ;
dc = keybindings [ bkey ] [ modifierstate ] ;
bl = bindcmdlevel [ bkey ] [ modifierstate ] ;
}
else if ( key = = K_RSHIFT & & ( ! dc | | ! * dc ) )
{
bkey = K_LSHIFT ;
dc = keybindings [ bkey ] [ modifierstate ] ;
bl = bindcmdlevel [ bkey ] [ modifierstate ] ;
}
else
bkey = key ;
2013-12-02 14:30:30 +00:00
2014-03-30 08:55:06 +00:00
if ( key = = K_MOUSE1 & & IN_MouseDevIsTouch ( devid ) )
2004-08-23 00:15:46 +00:00
{
2014-03-30 08:55:06 +00:00
dc = SCR_ShowPics_ClickCommand ( mousecursor_x , mousecursor_y ) ;
if ( dc )
bl = RESTRICT_INSECURE ;
2013-10-08 14:28:11 +00:00
else
2004-08-23 00:15:46 +00:00
{
2014-03-30 08:55:06 +00:00
int bkey = Sbar_TranslateHudClick ( ) ;
if ( bkey )
{
dc = keybindings [ bkey ] [ modifierstate ] ;
bl = bindcmdlevel [ bkey ] [ modifierstate ] ;
}
}
if ( ! dc ) //no buttons to click,
{
bkey = IN_TranslateMButtonPress ( devid ) ;
if ( bkey )
{
dc = keybindings [ bkey ] [ modifierstate ] ;
bl = bindcmdlevel [ bkey ] [ modifierstate ] ;
}
else
return ;
2004-08-23 00:15:46 +00:00
}
}
2014-03-30 08:55:06 +00:00
if ( ! dc )
dc = " " ;
if ( dc [ 0 ] = = ' + ' )
{
uc = va ( " -%s%s %i \n " , p , dc + 1 , bkey ) ;
dc = va ( " +%s%s %i \n " , p , dc + 1 , bkey ) ;
}
else
{
uc = NULL ;
dc = va ( " %s%s \n " , p , dc ) ;
}
//don't mess up if we ran out of devices, just silently release the one that it conflicted with (and only if its in conflict).
if ( releasecommand [ key ] [ devid % MAX_INDEVS ] & & ( ! uc | | strcmp ( uc , releasecommand [ key ] [ devid % MAX_INDEVS ] ) ) )
{
Cbuf_AddText ( releasecommand [ key ] [ devid % MAX_INDEVS ] , releasecommandlevel [ key ] [ devid % MAX_INDEVS ] ) ;
Z_Free ( releasecommand [ key ] [ devid % MAX_INDEVS ] ) ;
releasecommand [ key ] [ devid % MAX_INDEVS ] = NULL ;
}
Cbuf_AddText ( dc , bl ) ;
if ( uc )
releasecommand [ key ] [ devid % MAX_INDEVS ] = Z_StrDup ( uc ) ;
releasecommandlevel [ key ] [ devid % MAX_INDEVS ] = bl ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
Key_ClearStates
= = = = = = = = = = = = = = = = = = =
*/
void Key_ClearStates ( void )
{
int i ;
2005-07-05 23:46:10 +00:00
for ( i = 0 ; i < K_MAX ; i + + )
2004-08-23 00:15:46 +00:00
{
keydown [ i ] = false ;
key_repeats [ i ] = false ;
}
}