KeyInput.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. typedef struct {
  23. char *name;
  24. int keynum;
  25. char *strId; // localized string id
  26. } keyname_t;
  27. // keys that can be set without a special name
  28. static const char unnamedkeys[] = "*,-=./[\\]1234567890abcdefghijklmnopqrstuvwxyz";
  29. #if MACOS_X
  30. const char* OSX_GetLocalizedString( const char* );
  31. #endif
  32. // names not in this list can either be lowercase ascii, or '0xnn' hex sequences
  33. keyname_t keynames[] =
  34. {
  35. {"TAB", K_TAB, "#str_07018"},
  36. {"ENTER", K_ENTER, "#str_07019"},
  37. {"ESCAPE", K_ESCAPE, "#str_07020"},
  38. {"SPACE", K_SPACE, "#str_07021"},
  39. {"BACKSPACE", K_BACKSPACE, "#str_07022"},
  40. {"UPARROW", K_UPARROW, "#str_07023"},
  41. {"DOWNARROW", K_DOWNARROW, "#str_07024"},
  42. {"LEFTARROW", K_LEFTARROW, "#str_07025"},
  43. {"RIGHTARROW", K_RIGHTARROW, "#str_07026"},
  44. {"ALT", K_ALT, "#str_07027"},
  45. {"RIGHTALT", K_RIGHT_ALT, "#str_07027"},
  46. {"CTRL", K_CTRL, "#str_07028"},
  47. {"SHIFT", K_SHIFT, "#str_07029"},
  48. {"LWIN", K_LWIN, "#str_07030"},
  49. {"RWIN", K_RWIN, "#str_07031"},
  50. {"MENU", K_MENU, "#str_07032"},
  51. {"COMMAND", K_COMMAND, "#str_07033"},
  52. {"CAPSLOCK", K_CAPSLOCK, "#str_07034"},
  53. {"SCROLL", K_SCROLL, "#str_07035"},
  54. {"PRINTSCREEN", K_PRINT_SCR, "#str_07179"},
  55. {"F1", K_F1, "#str_07036"},
  56. {"F2", K_F2, "#str_07037"},
  57. {"F3", K_F3, "#str_07038"},
  58. {"F4", K_F4, "#str_07039"},
  59. {"F5", K_F5, "#str_07040"},
  60. {"F6", K_F6, "#str_07041"},
  61. {"F7", K_F7, "#str_07042"},
  62. {"F8", K_F8, "#str_07043"},
  63. {"F9", K_F9, "#str_07044"},
  64. {"F10", K_F10, "#str_07045"},
  65. {"F11", K_F11, "#str_07046"},
  66. {"F12", K_F12, "#str_07047"},
  67. {"INS", K_INS, "#str_07048"},
  68. {"DEL", K_DEL, "#str_07049"},
  69. {"PGDN", K_PGDN, "#str_07050"},
  70. {"PGUP", K_PGUP, "#str_07051"},
  71. {"HOME", K_HOME, "#str_07052"},
  72. {"END", K_END, "#str_07053"},
  73. {"MOUSE1", K_MOUSE1, "#str_07054"},
  74. {"MOUSE2", K_MOUSE2, "#str_07055"},
  75. {"MOUSE3", K_MOUSE3, "#str_07056"},
  76. {"MOUSE4", K_MOUSE4, "#str_07057"},
  77. {"MOUSE5", K_MOUSE5, "#str_07058"},
  78. {"MOUSE6", K_MOUSE6, "#str_07059"},
  79. {"MOUSE7", K_MOUSE7, "#str_07060"},
  80. {"MOUSE8", K_MOUSE8, "#str_07061"},
  81. {"MWHEELUP", K_MWHEELUP, "#str_07131"},
  82. {"MWHEELDOWN", K_MWHEELDOWN, "#str_07132"},
  83. {"JOY1", K_JOY1, "#str_07062"},
  84. {"JOY2", K_JOY2, "#str_07063"},
  85. {"JOY3", K_JOY3, "#str_07064"},
  86. {"JOY4", K_JOY4, "#str_07065"},
  87. {"JOY5", K_JOY5, "#str_07066"},
  88. {"JOY6", K_JOY6, "#str_07067"},
  89. {"JOY7", K_JOY7, "#str_07068"},
  90. {"JOY8", K_JOY8, "#str_07069"},
  91. {"JOY9", K_JOY9, "#str_07070"},
  92. {"JOY10", K_JOY10, "#str_07071"},
  93. {"JOY11", K_JOY11, "#str_07072"},
  94. {"JOY12", K_JOY12, "#str_07073"},
  95. {"JOY13", K_JOY13, "#str_07074"},
  96. {"JOY14", K_JOY14, "#str_07075"},
  97. {"JOY15", K_JOY15, "#str_07076"},
  98. {"JOY16", K_JOY16, "#str_07077"},
  99. {"JOY17", K_JOY17, "#str_07078"},
  100. {"JOY18", K_JOY18, "#str_07079"},
  101. {"JOY19", K_JOY19, "#str_07080"},
  102. {"JOY20", K_JOY20, "#str_07081"},
  103. {"JOY21", K_JOY21, "#str_07082"},
  104. {"JOY22", K_JOY22, "#str_07083"},
  105. {"JOY23", K_JOY23, "#str_07084"},
  106. {"JOY24", K_JOY24, "#str_07085"},
  107. {"JOY25", K_JOY25, "#str_07086"},
  108. {"JOY26", K_JOY26, "#str_07087"},
  109. {"JOY27", K_JOY27, "#str_07088"},
  110. {"JOY28", K_JOY28, "#str_07089"},
  111. {"JOY29", K_JOY29, "#str_07090"},
  112. {"JOY30", K_JOY30, "#str_07091"},
  113. {"JOY31", K_JOY31, "#str_07092"},
  114. {"JOY32", K_JOY32, "#str_07093"},
  115. {"AUX1", K_AUX1, "#str_07094"},
  116. {"AUX2", K_AUX2, "#str_07095"},
  117. {"AUX3", K_AUX3, "#str_07096"},
  118. {"AUX4", K_AUX4, "#str_07097"},
  119. {"AUX5", K_AUX5, "#str_07098"},
  120. {"AUX6", K_AUX6, "#str_07099"},
  121. {"AUX7", K_AUX7, "#str_07100"},
  122. {"AUX8", K_AUX8, "#str_07101"},
  123. {"AUX9", K_AUX9, "#str_07102"},
  124. {"AUX10", K_AUX10, "#str_07103"},
  125. {"AUX11", K_AUX11, "#str_07104"},
  126. {"AUX12", K_AUX12, "#str_07105"},
  127. {"AUX13", K_AUX13, "#str_07106"},
  128. {"AUX14", K_AUX14, "#str_07107"},
  129. {"AUX15", K_AUX15, "#str_07108"},
  130. {"AUX16", K_AUX16, "#str_07109"},
  131. {"KP_HOME", K_KP_HOME, "#str_07110"},
  132. {"KP_UPARROW", K_KP_UPARROW, "#str_07111"},
  133. {"KP_PGUP", K_KP_PGUP, "#str_07112"},
  134. {"KP_LEFTARROW", K_KP_LEFTARROW, "#str_07113"},
  135. {"KP_5", K_KP_5, "#str_07114"},
  136. {"KP_RIGHTARROW", K_KP_RIGHTARROW, "#str_07115"},
  137. {"KP_END", K_KP_END, "#str_07116"},
  138. {"KP_DOWNARROW", K_KP_DOWNARROW, "#str_07117"},
  139. {"KP_PGDN", K_KP_PGDN, "#str_07118"},
  140. {"KP_ENTER", K_KP_ENTER, "#str_07119"},
  141. {"KP_INS", K_KP_INS, "#str_07120"},
  142. {"KP_DEL", K_KP_DEL, "#str_07121"},
  143. {"KP_SLASH", K_KP_SLASH, "#str_07122"},
  144. {"KP_MINUS", K_KP_MINUS, "#str_07123"},
  145. {"KP_PLUS", K_KP_PLUS, "#str_07124"},
  146. {"KP_NUMLOCK", K_KP_NUMLOCK, "#str_07125"},
  147. {"KP_STAR", K_KP_STAR, "#str_07126"},
  148. {"KP_EQUALS", K_KP_EQUALS, "#str_07127"},
  149. {"PAUSE", K_PAUSE, "#str_07128"},
  150. {"SEMICOLON", ';', "#str_07129"}, // because a raw semicolon separates commands
  151. {"APOSTROPHE", '\'', "#str_07130"}, // because a raw apostrophe messes with parsing
  152. {NULL, 0, NULL}
  153. };
  154. static const int MAX_KEYS = 256;
  155. class idKey {
  156. public:
  157. idKey( void ) { down = false; repeats = 0; usercmdAction = 0; }
  158. bool down;
  159. int repeats; // if > 1, it is autorepeating
  160. idStr binding;
  161. int usercmdAction; // for testing by the asyncronous usercmd generation
  162. };
  163. bool key_overstrikeMode = false;
  164. idKey * keys = NULL;
  165. #define ID_DOOM_LEGACY
  166. #ifdef ID_DOOM_LEGACY
  167. char * cheatCodes[] = {
  168. "iddqd", // Invincibility
  169. "idkfa", // All weapons, keys, ammo, and 200% armor
  170. "idfa", // Reset ammunition
  171. "idspispopd", // Walk through walls
  172. "idclip", // Walk through walls
  173. "idchoppers", // Chainsaw
  174. /*
  175. "idbeholds", // Berserker strength
  176. "idbeholdv", // Temporary invincibility
  177. "idbeholdi", // Temporary invisibility
  178. "idbeholda", // Full automap
  179. "idbeholdr", // Anti-radiation suit
  180. "idbeholdl", // Light amplification visor
  181. "idclev", // Level select
  182. "iddt", // Toggle full map; full map and objects; normal map
  183. "idmypos", // Display coordinates and heading
  184. "idmus", // Change music to indicated level
  185. "fhhall", // Kill all enemies in level
  186. "fhshh", // Invisible to enemies until attack
  187. */
  188. NULL
  189. };
  190. char lastKeys[32];
  191. int lastKeyIndex;
  192. #endif
  193. /*
  194. ===================
  195. idKeyInput::ArgCompletion_KeyName
  196. ===================
  197. */
  198. void idKeyInput::ArgCompletion_KeyName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
  199. keyname_t *kn;
  200. int i;
  201. for( i = 0; i < sizeof( unnamedkeys ) - 1; i++ ) {
  202. callback( va( "%s %c", args.Argv( 0 ), unnamedkeys[ i ] ) );
  203. }
  204. for ( kn = keynames; kn->name; kn++ ) {
  205. callback( va( "%s %s", args.Argv( 0 ), kn->name ) );
  206. }
  207. }
  208. /*
  209. ===================
  210. idKeyInput::GetOverstrikeMode
  211. ===================
  212. */
  213. bool idKeyInput::GetOverstrikeMode( void ) {
  214. return key_overstrikeMode;
  215. }
  216. /*
  217. ===================
  218. idKeyInput::SetOverstrikeMode
  219. ===================
  220. */
  221. void idKeyInput::SetOverstrikeMode( bool state ) {
  222. key_overstrikeMode = state;
  223. }
  224. /*
  225. ===================
  226. idKeyInput::IsDown
  227. ===================
  228. */
  229. bool idKeyInput::IsDown( int keynum ) {
  230. if ( keynum == -1 ) {
  231. return false;
  232. }
  233. return keys[keynum].down;
  234. }
  235. /*
  236. ===================
  237. idKeyInput::StringToKeyNum
  238. Returns a key number to be used to index keys[] by looking at
  239. the given string. Single ascii characters return themselves, while
  240. the K_* names are matched up.
  241. 0x11 will be interpreted as raw hex, which will allow new controlers
  242. to be configured even if they don't have defined names.
  243. ===================
  244. */
  245. int idKeyInput::StringToKeyNum( const char *str ) {
  246. keyname_t *kn;
  247. if ( !str || !str[0] ) {
  248. return -1;
  249. }
  250. if ( !str[1] ) {
  251. return (unsigned char)(str[0]);
  252. }
  253. // check for hex code
  254. if ( str[0] == '0' && str[1] == 'x' && strlen( str ) == 4 ) {
  255. int n1, n2;
  256. n1 = str[2];
  257. if ( n1 >= '0' && n1 <= '9' ) {
  258. n1 -= '0';
  259. } else if ( n1 >= 'a' && n1 <= 'f' ) {
  260. n1 = n1 - 'a' + 10;
  261. } else {
  262. n1 = 0;
  263. }
  264. n2 = str[3];
  265. if ( n2 >= '0' && n2 <= '9' ) {
  266. n2 -= '0';
  267. } else if ( n2 >= 'a' && n2 <= 'f' ) {
  268. n2 = n2 - 'a' + 10;
  269. } else {
  270. n2 = 0;
  271. }
  272. return n1 * 16 + n2;
  273. }
  274. // scan for a text match
  275. for ( kn = keynames; kn->name; kn++ ) {
  276. if ( !idStr::Icmp( str, kn->name ) ) {
  277. return kn->keynum;
  278. }
  279. }
  280. return -1;
  281. }
  282. /*
  283. ===================
  284. idKeyInput::KeyNumToString
  285. Returns a string (either a single ascii char, a K_* name, or a 0x11 hex string) for the
  286. given keynum.
  287. ===================
  288. */
  289. const char *idKeyInput::KeyNumToString( int keynum, bool localized ) {
  290. keyname_t *kn;
  291. static char tinystr[5];
  292. int i, j;
  293. if ( keynum == -1 ) {
  294. return "<KEY NOT FOUND>";
  295. }
  296. if ( keynum < 0 || keynum > 255 ) {
  297. return "<OUT OF RANGE>";
  298. }
  299. // check for printable ascii (don't use quote)
  300. if ( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != '\'' ) {
  301. tinystr[0] = Sys_MapCharForKey( keynum );
  302. tinystr[1] = 0;
  303. return tinystr;
  304. }
  305. // check for a key string
  306. for ( kn = keynames; kn->name; kn++ ) {
  307. if ( keynum == kn->keynum ) {
  308. if ( !localized || kn->strId[0] != '#' ) {
  309. return kn->name;
  310. } else {
  311. #if MACOS_X
  312. switch ( kn->keynum ) {
  313. case K_ENTER:
  314. case K_BACKSPACE:
  315. case K_ALT:
  316. case K_INS:
  317. case K_PRINT_SCR:
  318. return OSX_GetLocalizedString( kn->name );
  319. break;
  320. default :
  321. return common->GetLanguageDict()->GetString( kn->strId ); break;
  322. }
  323. #else
  324. return common->GetLanguageDict()->GetString( kn->strId );
  325. #endif
  326. }
  327. }
  328. }
  329. // check for European high-ASCII characters
  330. if ( localized && keynum >= 161 && keynum <= 255 ) {
  331. tinystr[0] = keynum;
  332. tinystr[1] = 0;
  333. return tinystr;
  334. }
  335. // make a hex string
  336. i = keynum >> 4;
  337. j = keynum & 15;
  338. tinystr[0] = '0';
  339. tinystr[1] = 'x';
  340. tinystr[2] = i > 9 ? i - 10 + 'a' : i + '0';
  341. tinystr[3] = j > 9 ? j - 10 + 'a' : j + '0';
  342. tinystr[4] = 0;
  343. return tinystr;
  344. }
  345. /*
  346. ===================
  347. idKeyInput::SetBinding
  348. ===================
  349. */
  350. void idKeyInput::SetBinding( int keynum, const char *binding ) {
  351. if ( keynum == -1 ) {
  352. return;
  353. }
  354. // Clear out all button states so we aren't stuck forever thinking this key is held down
  355. usercmdGen->Clear();
  356. // allocate memory for new binding
  357. keys[keynum].binding = binding;
  358. // find the action for the async command generation
  359. keys[keynum].usercmdAction = usercmdGen->CommandStringUsercmdData( binding );
  360. // consider this like modifying an archived cvar, so the
  361. // file write will be triggered at the next oportunity
  362. cvarSystem->SetModifiedFlags( CVAR_ARCHIVE );
  363. }
  364. /*
  365. ===================
  366. idKeyInput::GetBinding
  367. ===================
  368. */
  369. const char *idKeyInput::GetBinding( int keynum ) {
  370. if ( keynum == -1 ) {
  371. return "";
  372. }
  373. return keys[ keynum ].binding;
  374. }
  375. /*
  376. ===================
  377. idKeyInput::GetUsercmdAction
  378. ===================
  379. */
  380. int idKeyInput::GetUsercmdAction( int keynum ) {
  381. return keys[ keynum ].usercmdAction;
  382. }
  383. /*
  384. ===================
  385. Key_Unbind_f
  386. ===================
  387. */
  388. void Key_Unbind_f( const idCmdArgs &args ) {
  389. int b;
  390. if ( args.Argc() != 2 ) {
  391. common->Printf( "unbind <key> : remove commands from a key\n" );
  392. return;
  393. }
  394. b = idKeyInput::StringToKeyNum( args.Argv(1) );
  395. if ( b == -1 ) {
  396. // If it wasn't a key, it could be a command
  397. if ( !idKeyInput::UnbindBinding( args.Argv(1) ) ) {
  398. common->Printf( "\"%s\" isn't a valid key\n", args.Argv(1) );
  399. }
  400. } else {
  401. idKeyInput::SetBinding( b, "" );
  402. }
  403. }
  404. /*
  405. ===================
  406. Key_Unbindall_f
  407. ===================
  408. */
  409. void Key_Unbindall_f( const idCmdArgs &args ) {
  410. int i;
  411. for ( i = 0; i < MAX_KEYS; i++ ) {
  412. idKeyInput::SetBinding( i, "" );
  413. }
  414. }
  415. /*
  416. ===================
  417. Key_Bind_f
  418. ===================
  419. */
  420. void Key_Bind_f( const idCmdArgs &args ) {
  421. int i, c, b;
  422. char cmd[MAX_STRING_CHARS];
  423. c = args.Argc();
  424. if ( c < 2 ) {
  425. common->Printf( "bind <key> [command] : attach a command to a key\n" );
  426. return;
  427. }
  428. b = idKeyInput::StringToKeyNum( args.Argv(1) );
  429. if ( b == -1 ) {
  430. common->Printf( "\"%s\" isn't a valid key\n", args.Argv(1) );
  431. return;
  432. }
  433. if ( c == 2 ) {
  434. if ( keys[b].binding.Length() ) {
  435. common->Printf( "\"%s\" = \"%s\"\n", args.Argv(1), keys[b].binding.c_str() );
  436. }
  437. else {
  438. common->Printf( "\"%s\" is not bound\n", args.Argv(1) );
  439. }
  440. return;
  441. }
  442. // copy the rest of the command line
  443. cmd[0] = 0; // start out with a null string
  444. for ( i = 2; i < c; i++ ) {
  445. strcat( cmd, args.Argv( i ) );
  446. if ( i != (c-1) ) {
  447. strcat( cmd, " " );
  448. }
  449. }
  450. idKeyInput::SetBinding( b, cmd );
  451. }
  452. /*
  453. ============
  454. Key_BindUnBindTwo_f
  455. binds keynum to bindcommand and unbinds if there are already two binds on the key
  456. ============
  457. */
  458. void Key_BindUnBindTwo_f( const idCmdArgs &args ) {
  459. int c = args.Argc();
  460. if ( c < 3 ) {
  461. common->Printf( "bindunbindtwo <keynum> [command]\n" );
  462. return;
  463. }
  464. int key = atoi( args.Argv( 1 ) );
  465. idStr bind = args.Argv( 2 );
  466. if ( idKeyInput::NumBinds( bind ) >= 2 && !idKeyInput::KeyIsBoundTo( key, bind ) ) {
  467. idKeyInput::UnbindBinding( bind );
  468. }
  469. idKeyInput::SetBinding( key, bind );
  470. }
  471. /*
  472. ============
  473. idKeyInput::WriteBindings
  474. Writes lines containing "bind key value"
  475. ============
  476. */
  477. void idKeyInput::WriteBindings( idFile *f ) {
  478. int i;
  479. f->Printf( "unbindall\n" );
  480. for ( i = 0; i < MAX_KEYS; i++ ) {
  481. if ( keys[i].binding.Length() ) {
  482. const char *name = KeyNumToString( i, false );
  483. // handle the escape character nicely
  484. if ( !strcmp( name, "\\" ) ) {
  485. f->Printf( "bind \"\\\" \"%s\"\n", keys[i].binding.c_str() );
  486. } else {
  487. f->Printf( "bind \"%s\" \"%s\"\n", KeyNumToString( i, false ), keys[i].binding.c_str() );
  488. }
  489. }
  490. }
  491. }
  492. /*
  493. ============
  494. Key_ListBinds_f
  495. ============
  496. */
  497. void Key_ListBinds_f( const idCmdArgs &args ) {
  498. int i;
  499. for ( i = 0; i < MAX_KEYS; i++ ) {
  500. if ( keys[i].binding.Length() ) {
  501. common->Printf( "%s \"%s\"\n", idKeyInput::KeyNumToString( i, false ), keys[i].binding.c_str() );
  502. }
  503. }
  504. }
  505. /*
  506. ============
  507. idKeyInput::KeysFromBinding
  508. returns the localized name of the key for the binding
  509. ============
  510. */
  511. const char *idKeyInput::KeysFromBinding( const char *bind ) {
  512. int i;
  513. static char keyName[MAX_STRING_CHARS];
  514. keyName[0] = '\0';
  515. if ( bind && *bind ) {
  516. for ( i = 0; i < MAX_KEYS; i++ ) {
  517. if ( keys[i].binding.Icmp( bind ) == 0 ) {
  518. if ( keyName[0] != '\0' ) {
  519. idStr::Append( keyName, sizeof( keyName ), common->GetLanguageDict()->GetString( "#str_07183" ) );
  520. }
  521. idStr::Append( keyName, sizeof( keyName ), KeyNumToString( i, true ) );
  522. }
  523. }
  524. }
  525. if ( keyName[0] == '\0' ) {
  526. idStr::Copynz( keyName, common->GetLanguageDict()->GetString( "#str_07133" ), sizeof( keyName ) );
  527. }
  528. idStr::ToLower( keyName );
  529. return keyName;
  530. }
  531. /*
  532. ============
  533. idKeyInput::BindingFromKey
  534. returns the binding for the localized name of the key
  535. ============
  536. */
  537. const char *idKeyInput::BindingFromKey( const char *key ) {
  538. const int keyNum = idKeyInput::StringToKeyNum( key );
  539. if ( keyNum<0 || keyNum >= MAX_KEYS ) {
  540. return NULL;
  541. }
  542. return keys[keyNum].binding.c_str();
  543. }
  544. /*
  545. ============
  546. idKeyInput::UnbindBinding
  547. ============
  548. */
  549. bool idKeyInput::UnbindBinding( const char *binding ) {
  550. bool unbound = false;
  551. int i;
  552. if ( binding && *binding ) {
  553. for ( i = 0; i < MAX_KEYS; i++ ) {
  554. if ( keys[i].binding.Icmp( binding ) == 0 ) {
  555. SetBinding( i, "" );
  556. unbound = true;
  557. }
  558. }
  559. }
  560. return unbound;
  561. }
  562. /*
  563. ============
  564. idKeyInput::NumBinds
  565. ============
  566. */
  567. int idKeyInput::NumBinds( const char *binding ) {
  568. int i, count = 0;
  569. if ( binding && *binding ) {
  570. for ( i = 0; i < MAX_KEYS; i++ ) {
  571. if ( keys[i].binding.Icmp( binding ) == 0 ) {
  572. count++;
  573. }
  574. }
  575. }
  576. return count;
  577. }
  578. /*
  579. ============
  580. idKeyInput::KeyIsBountTo
  581. ============
  582. */
  583. bool idKeyInput::KeyIsBoundTo( int keynum, const char *binding ) {
  584. if ( keynum >= 0 && keynum < MAX_KEYS ) {
  585. return ( keys[keynum].binding.Icmp( binding ) == 0 );
  586. }
  587. return false;
  588. }
  589. /*
  590. ===================
  591. idKeyInput::PreliminaryKeyEvent
  592. Tracks global key up/down state
  593. Called by the system for both key up and key down events
  594. ===================
  595. */
  596. void idKeyInput::PreliminaryKeyEvent( int keynum, bool down ) {
  597. keys[keynum].down = down;
  598. #ifdef ID_DOOM_LEGACY
  599. if ( down ) {
  600. lastKeys[ 0 + ( lastKeyIndex & 15 )] = keynum;
  601. lastKeys[16 + ( lastKeyIndex & 15 )] = keynum;
  602. lastKeyIndex = ( lastKeyIndex + 1 ) & 15;
  603. for ( int i = 0; cheatCodes[i] != NULL; i++ ) {
  604. int l = strlen( cheatCodes[i] );
  605. assert( l <= 16 );
  606. if ( idStr::Icmpn( lastKeys + 16 + ( lastKeyIndex & 15 ) - l, cheatCodes[i], l ) == 0 ) {
  607. common->Printf( "your memory serves you well!\n" );
  608. break;
  609. }
  610. }
  611. }
  612. #endif
  613. }
  614. /*
  615. =================
  616. idKeyInput::ExecKeyBinding
  617. =================
  618. */
  619. bool idKeyInput::ExecKeyBinding( int keynum ) {
  620. // commands that are used by the async thread
  621. // don't add text
  622. if ( keys[keynum].usercmdAction ) {
  623. return false;
  624. }
  625. // send the bound action
  626. if ( keys[keynum].binding.Length() ) {
  627. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, keys[keynum].binding.c_str() );
  628. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
  629. }
  630. return true;
  631. }
  632. /*
  633. ===================
  634. idKeyInput::ClearStates
  635. ===================
  636. */
  637. void idKeyInput::ClearStates( void ) {
  638. int i;
  639. for ( i = 0; i < MAX_KEYS; i++ ) {
  640. if ( keys[i].down ) {
  641. PreliminaryKeyEvent( i, false );
  642. }
  643. keys[i].down = false;
  644. }
  645. // clear the usercommand states
  646. usercmdGen->Clear();
  647. }
  648. /*
  649. ===================
  650. idKeyInput::Init
  651. ===================
  652. */
  653. void idKeyInput::Init( void ) {
  654. keys = new idKey[MAX_KEYS];
  655. // register our functions
  656. cmdSystem->AddCommand( "bind", Key_Bind_f, CMD_FL_SYSTEM, "binds a command to a key", idKeyInput::ArgCompletion_KeyName );
  657. cmdSystem->AddCommand( "bindunbindtwo", Key_BindUnBindTwo_f, CMD_FL_SYSTEM, "binds a key but unbinds it first if there are more than two binds" );
  658. cmdSystem->AddCommand( "unbind", Key_Unbind_f, CMD_FL_SYSTEM, "unbinds any command from a key", idKeyInput::ArgCompletion_KeyName );
  659. cmdSystem->AddCommand( "unbindall", Key_Unbindall_f, CMD_FL_SYSTEM, "unbinds any commands from all keys" );
  660. cmdSystem->AddCommand( "listBinds", Key_ListBinds_f, CMD_FL_SYSTEM, "lists key bindings" );
  661. }
  662. /*
  663. ===================
  664. idKeyInput::Shutdown
  665. ===================
  666. */
  667. void idKeyInput::Shutdown( void ) {
  668. delete [] keys;
  669. keys = NULL;
  670. }