Console.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "StdAfx.h"
  13. #include "LCDDrawing.h"
  14. extern CGame *_pGame;
  15. // console variables
  16. static const FLOAT tmConsoleFade = 0.0f; // how many seconds it takes console to fade in/out
  17. static FLOAT fConsoleFadeValue = 0.0f; // faded value of console (0..1)
  18. static CTimerValue tvConsoleLast;
  19. static CTString strConsole;
  20. static CTString strInputHistory = "\n";
  21. static CTString strEditingLine;
  22. static CTString strExpandStart;
  23. static CTString strLastExpanded;
  24. static CTString strCurrentLine;
  25. static BOOL bLastExpandedFound;
  26. static INDEX iSymbolOffset;
  27. static INDEX iHistoryLine=0;
  28. static INDEX iCursorPos=0;
  29. static INDEX ctConsoleLinesOnScreen;
  30. static INDEX con_iFirstLine = 1;
  31. extern FLOAT con_fHeightFactor;
  32. extern FLOAT con_tmLastLines;
  33. // find a line with given number in a multi-line string counting from end of string
  34. BOOL GetLineCountBackward(const char *pchrStringStart, const char *pchrStringEnd,
  35. INDEX iBackwardLine, CTString &strResult)
  36. {
  37. // start at the end of string
  38. const char *pchrCurrent = pchrStringEnd;
  39. INDEX ctLinesDone=0;
  40. // while line of given number is not found
  41. while(ctLinesDone!=iBackwardLine) {
  42. // go one character back
  43. pchrCurrent--;
  44. // if got before start of string
  45. if (pchrCurrent < pchrStringStart) {
  46. // line is not found
  47. return FALSE;
  48. }
  49. // if at line break
  50. if(*pchrCurrent == '\n') {
  51. // count lines
  52. ctLinesDone++;
  53. }
  54. }
  55. // check that pointer is not outside range
  56. ASSERT(pchrCurrent>=pchrStringStart && pchrCurrent<pchrStringEnd);
  57. // if exactly on line break, skip it
  58. if (*pchrCurrent=='\n') {
  59. pchrCurrent++;
  60. }
  61. // find end of that line
  62. const char *pchrLineEnd=strchr(pchrCurrent, '\r');
  63. if (pchrLineEnd==NULL) {
  64. pchrLineEnd = pchrStringEnd;
  65. }
  66. // copy the found line
  67. char achrLine[ 1024];
  68. strncpy( achrLine, pchrCurrent, pchrLineEnd-pchrCurrent);
  69. achrLine[ pchrLineEnd-pchrCurrent]=0;
  70. strResult = achrLine;
  71. return TRUE;
  72. }
  73. void CGame::ConsoleRender(CDrawPort *pdp)
  74. {
  75. if( _pGame->gm_csConsoleState==CS_OFF) {
  76. con_iFirstLine = 1;
  77. tvConsoleLast = _pTimer->GetHighPrecisionTimer();
  78. return;
  79. }
  80. // get console height
  81. con_fHeightFactor = Clamp( con_fHeightFactor, 0.1f, 1.0f);
  82. FLOAT fHeightFactor = con_fHeightFactor;
  83. if( !gm_bGameOn) fHeightFactor = 0.9f;
  84. // calculate up-down speed to be independent of refresh speed
  85. CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
  86. CTimerValue tvDelta = tvNow - tvConsoleLast;
  87. tvConsoleLast = tvNow;
  88. FLOAT fFadeSpeed = (FLOAT)(tvDelta.GetSeconds() / tmConsoleFade);
  89. // if console is dropping down
  90. if( _pGame->gm_csConsoleState==CS_TURNINGON) {
  91. // move it down
  92. fConsoleFadeValue += fFadeSpeed;
  93. // if finished moving
  94. if( fConsoleFadeValue>1.0f) {
  95. // stop
  96. fConsoleFadeValue = 1.0f;
  97. _pGame->gm_csConsoleState = CS_ON;
  98. }
  99. }
  100. // if console is pulling up
  101. if( _pGame->gm_csConsoleState==CS_TURNINGOFF) {
  102. // move it up
  103. fConsoleFadeValue -= fFadeSpeed;
  104. // if finished moving
  105. if( fConsoleFadeValue<0.0f) {
  106. // stop
  107. fConsoleFadeValue = 0.0f;
  108. _pGame->gm_csConsoleState = CS_OFF;
  109. // if not in network
  110. if (!_pNetwork->IsNetworkEnabled()) {
  111. // don't show last lines on screen after exiting console
  112. CON_DiscardLastLineTimes();
  113. }
  114. return;
  115. }
  116. }
  117. if (_pGame->gm_csConsoleState==CS_TALK) {
  118. fHeightFactor = 0.1f;
  119. fConsoleFadeValue = 1.0f;
  120. }
  121. // calculate size of console box so that it covers upper half of the screen
  122. FLOAT fHeight = ClampUp( fHeightFactor*fConsoleFadeValue*2, fHeightFactor);
  123. CDrawPort dpConsole( pdp, 0.0f, 0.0f, 1.0f, fHeight);
  124. // lock drawport
  125. if( !dpConsole.Lock()) return;
  126. LCDPrepare(fConsoleFadeValue);
  127. LCDSetDrawport(&dpConsole);
  128. dpConsole.Fill(LCDFadedColor(C_BLACK|225));
  129. PIX pixSizeI = dpConsole.GetWidth();
  130. PIX pixSizeJ = dpConsole.GetHeight();
  131. COLOR colLight = LCDFadedColor(C_WHITE|255);
  132. COLOR colDark = LCDFadedColor(SE_COL_BLUE_LIGHT|255);
  133. INDEX iBackwardLine = con_iFirstLine;
  134. if( iBackwardLine>1) Swap( colLight, colDark);
  135. PIX pixLineSpacing = _pfdConsoleFont->fd_pixCharHeight + _pfdConsoleFont->fd_pixLineSpacing;
  136. LCDRenderCloudsForComp();
  137. //LCDRenderGrid();
  138. LCDRenderClouds2();
  139. dpConsole.DrawLine( 0, pixSizeJ-1, pixSizeI, pixSizeJ-1, LCDFadedColor(SE_COL_BLUE_NEUTRAL|255));
  140. const COLOR colFill = (colDark & ~CT_AMASK) | 0x2F;
  141. dpConsole.Fill( 0, pixSizeJ-pixLineSpacing*1.6f, pixSizeI, pixLineSpacing*1.6f, colFill);
  142. // setup font
  143. PIX pixTextX = (PIX)(dpConsole.GetWidth()*0.01f);
  144. PIX pixYLine = dpConsole.GetHeight()-14;
  145. dpConsole.SetFont( _pfdConsoleFont);
  146. // print editing line of text
  147. dpConsole.SetTextMode(-1);
  148. CTString strPrompt;
  149. if (_pGame->gm_csConsoleState == CS_TALK) {
  150. strPrompt = TRANS("say: ");
  151. } else {
  152. strPrompt = "=> ";
  153. }
  154. CTString strLineOnScreen = strPrompt + strEditingLine;
  155. dpConsole.PutText( strLineOnScreen, pixTextX, pixYLine, colLight);
  156. dpConsole.SetTextMode(+1);
  157. // add blinking cursor
  158. if( ((ULONG)(_pTimer->GetRealTimeTick()*2)) & 1) {
  159. CTString strCursor="_";
  160. FLOAT fTextScalingX = dpConsole.dp_fTextScaling * dpConsole.dp_fTextAspect;
  161. PIX pixCellSize = _pfdConsoleFont->fd_pixCharWidth * fTextScalingX + dpConsole.dp_pixTextCharSpacing;
  162. PIX pixCursorX = pixTextX + (iCursorPos+strlen(strPrompt))*pixCellSize;
  163. dpConsole.PutText( strCursor, pixCursorX, pixYLine+2, colDark);
  164. }
  165. // render previous outputs
  166. con_iFirstLine = ClampDn( con_iFirstLine, 1L);
  167. pixYLine -= (PIX)(pixLineSpacing * 1.333f);
  168. ctConsoleLinesOnScreen = pixYLine/pixLineSpacing;
  169. while( pixYLine >= 0) {
  170. CTString strLineOnScreen = CON_GetLastLine(iBackwardLine);
  171. dpConsole.PutText( strLineOnScreen, pixTextX, pixYLine, colDark);
  172. iBackwardLine++;
  173. pixYLine -= pixLineSpacing;
  174. }
  175. // all done
  176. dpConsole.Unlock();
  177. }
  178. // print last few lines from console to top of screen
  179. void CGame::ConsolePrintLastLines(CDrawPort *pdp)
  180. {
  181. // get number of lines to print
  182. con_tmLastLines = Clamp( con_tmLastLines, 1.0f, 10.0f);
  183. INDEX ctLines = CON_NumberOfLinesAfter( _pTimer->GetRealTimeTick() - con_tmLastLines);
  184. // if no lines left to print, just skip it
  185. if( ctLines==0) return;
  186. // setup font
  187. _pfdConsoleFont->SetFixedWidth();
  188. pdp->SetFont( _pfdConsoleFont);
  189. PIX pixCharHeight = _pfdConsoleFont->GetHeight() -1;
  190. // put some filter underneath for easier reading
  191. pdp->Fill( 0, 0, pdp->GetWidth(), pixCharHeight*ctLines, C_BLACK|128);
  192. // for each line
  193. for( INDEX iLine=0; iLine<ctLines; iLine++) {
  194. CTString strLine = CON_GetLastLine(iLine+1);
  195. pdp->PutText( strLine, 0, pixCharHeight*(ctLines-iLine-1), SE_COL_BLUE_LIGHT|255);
  196. }
  197. }
  198. static void Key_Backspace( BOOL bShift, BOOL bRight)
  199. {
  200. // do nothing if string is empty
  201. INDEX ctChars = strlen(strEditingLine);
  202. if( ctChars==0) return;
  203. if( bRight && iCursorPos<ctChars) { // DELETE key
  204. if( bShift) { // delete to end of line
  205. strEditingLine.TrimRight(iCursorPos);
  206. } else { // delete only one char
  207. strEditingLine.DeleteChar(iCursorPos);
  208. }
  209. }
  210. if( !bRight && iCursorPos>0) { // BACKSPACE key
  211. if( bShift) { // delete to start of line
  212. strEditingLine.TrimLeft(ctChars-iCursorPos);
  213. iCursorPos=0;
  214. } else { // delete only one char
  215. strEditingLine.DeleteChar(iCursorPos-1);
  216. iCursorPos--;
  217. }
  218. }
  219. }
  220. static void Key_ArrowUp(void)
  221. {
  222. CTString strSlash = "/";
  223. CTString strHistoryLine;
  224. if( iHistoryLine==0) strCurrentLine = strEditingLine;
  225. INDEX iCurrentHistoryLine = iHistoryLine;
  226. do {
  227. // determine previous line in history
  228. iCurrentHistoryLine++;
  229. const char *pchrHistoryStart = (const char*)strInputHistory;
  230. const char *pchrHistoryEnd = pchrHistoryStart +strlen( strInputHistory) -1;
  231. // we reach top of history, if line doesn't exist in history
  232. if( !GetLineCountBackward( pchrHistoryStart, pchrHistoryEnd, iCurrentHistoryLine, strHistoryLine)) return;
  233. } while( strCurrentLine!="" &&
  234. strnicmp( strHistoryLine, strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)))!=0 &&
  235. strnicmp( strHistoryLine, strSlash+strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)+1))!=0);
  236. // set new editing line
  237. iHistoryLine = iCurrentHistoryLine;
  238. strEditingLine = strHistoryLine;
  239. iCursorPos = strlen(strEditingLine);
  240. }
  241. static void Key_ArrowDown(void)
  242. {
  243. CTString strSlash = "/";
  244. CTString strHistoryLine;
  245. if( iHistoryLine==0) strCurrentLine = strEditingLine;
  246. INDEX iCurrentHistoryLine = iHistoryLine;
  247. while( iCurrentHistoryLine>1) {
  248. iCurrentHistoryLine--;
  249. const char *pchrHistoryStart = (const char *) strInputHistory;
  250. const char *pchrHistoryEnd = pchrHistoryStart +strlen(strInputHistory) -1;
  251. // line must exist in history
  252. BOOL bExists = GetLineCountBackward( pchrHistoryStart, pchrHistoryEnd, iCurrentHistoryLine, strHistoryLine);
  253. ASSERT( bExists);
  254. // set new editing line
  255. if( strCurrentLine=="" ||
  256. strnicmp( strHistoryLine, strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine))) ==0 ||
  257. strnicmp( strHistoryLine, strSlash+strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)+1))==0) {
  258. iHistoryLine = iCurrentHistoryLine;
  259. strEditingLine = strHistoryLine;
  260. iCursorPos = strlen(strEditingLine);
  261. return;
  262. }
  263. }
  264. }
  265. void DoCheat(const CTString &strCommand, const CTString &strVar)
  266. {
  267. _pShell->SetINDEX(strVar, !_pShell->GetINDEX(strVar));
  268. BOOL bNew = _pShell->GetINDEX(strVar);
  269. CPrintF("%s: %s\n", strCommand, bNew?"ON":"OFF");
  270. }
  271. static void Key_Return(void)
  272. {
  273. // ignore keydown return (keyup will be handled) - because of key bind to return
  274. //if( _pGame->gm_csConsoleState==CS_TALK) return;
  275. // clear editing line from whitespaces
  276. strEditingLine.TrimSpacesLeft();
  277. strEditingLine.TrimSpacesRight();
  278. // reset display position
  279. con_iFirstLine = 1;
  280. // ignore empty lines
  281. if( strEditingLine=="" || strEditingLine=="/") {
  282. strEditingLine = "";
  283. iCursorPos = 0;
  284. return;
  285. }
  286. // add to history
  287. strInputHistory += strEditingLine +"\r\n";
  288. iHistoryLine = 0;
  289. // check for cheats
  290. #define CHEAT_PREFIX "please"
  291. if (strEditingLine.HasPrefix(CHEAT_PREFIX) || strEditingLine.HasPrefix("/" CHEAT_PREFIX)) {
  292. strEditingLine.RemovePrefix(CHEAT_PREFIX);
  293. strEditingLine.RemovePrefix("/ " CHEAT_PREFIX );
  294. strEditingLine.TrimSpacesLeft();
  295. if (strEditingLine=="god") {
  296. DoCheat(strEditingLine, "cht_bGod");
  297. } else if (strEditingLine=="giveall") {
  298. DoCheat(strEditingLine, "cht_bGiveAll");
  299. } else if (strEditingLine=="killall") {
  300. DoCheat(strEditingLine, "cht_bKillAll");
  301. } else if (strEditingLine=="open") {
  302. DoCheat(strEditingLine, "cht_bOpen");
  303. } else if (strEditingLine=="tellall") {
  304. DoCheat(strEditingLine, "cht_bAllMessages");
  305. } else if (strEditingLine=="fly") {
  306. DoCheat(strEditingLine, "cht_bFly");
  307. } else if (strEditingLine=="ghost") {
  308. DoCheat(strEditingLine, "cht_bGhost");
  309. } else if (strEditingLine=="invisible") {
  310. DoCheat(strEditingLine, "cht_bInvisible");
  311. } else if (strEditingLine=="refresh") {
  312. DoCheat(strEditingLine, "cht_bRefresh");
  313. } else {
  314. CPrintF("sorry?\n");
  315. }
  316. // parse editing line
  317. } else if( strEditingLine[0]=='/') {
  318. // add to output and execute
  319. CPrintF( "-> %s\n", strEditingLine);
  320. strEditingLine+=";";
  321. _pShell->Execute(strEditingLine+1);
  322. }
  323. else if( !_pGame->gm_bGameOn) {
  324. // add to output and execute
  325. CPrintF( "-> %s\n", strEditingLine);
  326. strEditingLine+=";";
  327. _pShell->Execute(strEditingLine);
  328. }
  329. else {
  330. // just send chat
  331. _pNetwork->SendChat(-1, -1, strEditingLine);
  332. }
  333. // reset editing line
  334. strEditingLine = "";
  335. iCursorPos = 0;
  336. }
  337. // find first character that is not part of a symbol, backwards
  338. char *strrnonsym(const char *strString)
  339. {
  340. const char *pch = strString+strlen(strString)-1;
  341. while( pch>=strString) {
  342. char ch = *pch;
  343. if( !isalnum(ch) && ch!='_') return (char*)pch;
  344. pch--;
  345. }
  346. return NULL;
  347. }
  348. static void Key_Tab( BOOL bShift)
  349. {
  350. // clear editing line from whitespaces
  351. strEditingLine.TrimSpacesLeft();
  352. strEditingLine.TrimSpacesRight();
  353. // eventualy prepend the command like with '/'
  354. if (strEditingLine[0]!='/') strEditingLine = CTString("/")+strEditingLine;
  355. // find symbol letter typed so far
  356. CTString strSymbol;
  357. CTString strLastThatCanBeExpanded;
  358. if( strLastExpanded == "") {
  359. strExpandStart = strEditingLine;
  360. iSymbolOffset = 0;
  361. char *pcLastSymbol = strrnonsym( strEditingLine);
  362. // remember symbol text and offset inside editing line
  363. if( pcLastSymbol!=NULL) {
  364. strExpandStart = pcLastSymbol+1;
  365. iSymbolOffset = (INDEX)(pcLastSymbol+1 - (const char*)strEditingLine);
  366. }
  367. // printout all symbols that matches (if not only one, and not TAB only)
  368. INDEX ctSymbolsFound=0;
  369. BOOL bFirstFound = FALSE;
  370. CTString strLastMatched;
  371. {FOREACHINDYNAMICARRAY( _pShell->sh_assSymbols, CShellSymbol, itss) {
  372. // TAB only pressd?
  373. if( strExpandStart=="") break;
  374. // get completion name if current symbol is for user
  375. if( !(itss->ss_ulFlags&SSF_USER)) continue;
  376. strSymbol = itss->GetCompletionString();
  377. // if this symbol can be expanded
  378. if( strnicmp( strSymbol, strExpandStart, Min(strlen(strSymbol),strlen(strExpandStart))) == 0) {
  379. // can we print last found symbol ?
  380. if( strLastMatched!="") {
  381. if( !bFirstFound) CPrintF( " -\n");
  382. CPrintF( " %s\n", strLastMatched);
  383. bFirstFound = TRUE;
  384. }
  385. strLastMatched = strSymbol;
  386. ctSymbolsFound++;
  387. }
  388. }}
  389. // print last symbol
  390. if( ctSymbolsFound>1) CPrintF( " %s\n", strLastMatched);
  391. }
  392. // for each of symbols in the shell
  393. bLastExpandedFound = FALSE;
  394. BOOL bTabSymbolFound = FALSE;
  395. {FOREACHINDYNAMICARRAY( _pShell->sh_assSymbols, CShellSymbol, itss)
  396. {
  397. // skip if it is not visible to user
  398. if( !(itss->ss_ulFlags&SSF_USER)) continue;
  399. // get completion name for that symbol
  400. strSymbol = itss->GetCompletionString();
  401. // if this symbol can be expanded
  402. if( strnicmp( strSymbol, strExpandStart, Min(strlen(strSymbol),strlen(strExpandStart))) == 0)
  403. {
  404. // at least one symbol is found, so tab will work
  405. bTabSymbolFound = TRUE;
  406. // if this is first time we are doing this
  407. if( strLastExpanded == "") {
  408. // remember symbol as last expanded and set it as current
  409. strLastExpanded = strSymbol;
  410. break;
  411. }
  412. // if last expanded was already found, set this symbol as result and remember it as last expanded
  413. if( bLastExpandedFound) {
  414. strLastExpanded = strSymbol;
  415. break;
  416. }
  417. // if last expanded was not found yet, check if this one is last expanded
  418. if( stricmp( strLastExpanded, strSymbol) == 0) {
  419. // if looping backward (Shift+Tab)
  420. if( bShift) {
  421. // if we can loop backwards
  422. if( strLastThatCanBeExpanded != "") {
  423. strLastExpanded = strLastThatCanBeExpanded;
  424. break;
  425. // act like no symbols are found
  426. } else {
  427. bTabSymbolFound = FALSE;
  428. break;
  429. }
  430. }
  431. // if so, mark it
  432. bLastExpandedFound = TRUE;
  433. }
  434. // remember current as last that can be expanded (for loopbing back)
  435. strLastThatCanBeExpanded = strSymbol;
  436. }
  437. }}
  438. // if symbol was found
  439. if( bTabSymbolFound) {
  440. // set it in current editing line
  441. *((char*)(const char*)strEditingLine +iSymbolOffset) = '\0';
  442. strEditingLine += strLastExpanded;
  443. }
  444. iCursorPos = strlen(strEditingLine);
  445. }
  446. static void Key_PgUp( BOOL bShift)
  447. {
  448. if( bShift) con_iFirstLine += ctConsoleLinesOnScreen;
  449. else con_iFirstLine++;
  450. }
  451. static void Key_PgDn( BOOL bShift)
  452. {
  453. if( bShift) con_iFirstLine -= ctConsoleLinesOnScreen;
  454. else con_iFirstLine--;
  455. con_iFirstLine = ClampDn( con_iFirstLine, 1L);
  456. }
  457. void CGame::ConsoleKeyDown( MSG msg)
  458. {
  459. // if console is off
  460. if (_pGame->gm_csConsoleState==CS_OFF || _pGame->gm_csConsoleState==CS_TURNINGOFF) {
  461. // do nothing
  462. return;
  463. }
  464. BOOL bShift = GetKeyState(VK_SHIFT) & 0x8000;
  465. switch( msg.wParam) {
  466. case VK_RETURN: Key_Return(); break;
  467. case VK_UP: Key_ArrowUp(); break;
  468. case VK_DOWN: Key_ArrowDown(); break;
  469. case VK_TAB: Key_Tab(bShift); break;
  470. case VK_PRIOR: Key_PgUp(bShift); break;
  471. case VK_NEXT: Key_PgDn(bShift); break;
  472. case VK_BACK: Key_Backspace(bShift, FALSE); break;
  473. case VK_DELETE: Key_Backspace(bShift, TRUE); break;
  474. case VK_LEFT: if( iCursorPos > 0) iCursorPos--; break;
  475. case VK_RIGHT: if( iCursorPos < strlen(strEditingLine)) iCursorPos++; break;
  476. case VK_HOME: iCursorPos = 0; break;
  477. case VK_END: iCursorPos = strlen(strEditingLine); break;
  478. }
  479. }
  480. void CGame::ConsoleChar( MSG msg)
  481. {
  482. // if console is off, do nothing
  483. if (_pGame->gm_csConsoleState==CS_OFF) return;
  484. // for all keys except tab and shift, discard last found tab browsing symbol
  485. char chrKey = msg.wParam;
  486. if( msg.wParam!=VK_TAB && msg.wParam!=VK_SHIFT) strLastExpanded = "";
  487. // if key with letter pressed
  488. if( isprint(chrKey) && chrKey!='`') {
  489. // insert it to editing line
  490. strEditingLine.InsertChar( iCursorPos, chrKey);
  491. iCursorPos++;
  492. // reset history line
  493. iHistoryLine = 0;
  494. }
  495. }