console.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /*
  2. Copyright (C) 2004-2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
  3. Copyright (C) 1997-2001 Id Software, Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. /*
  17. * console.c: Console drawing and management.
  18. *
  19. * Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
  20. *
  21. * Acknowledgement:
  22. * This code was derived from Quake II, and was originally
  23. * written by Id Software, Inc.
  24. *
  25. */
  26. #include "../wolfiphone.h"
  27. extern viddef_t viddef;
  28. extern int consoleActive;
  29. console_t con;
  30. float scr_conlines;
  31. float scr_con_current;
  32. cvar_t *con_notifytime;
  33. cvar_t *scr_conspeed;
  34. #define MAXCMDLINE 256
  35. char key_lines[ 32 ][ MAXCMDLINE ];
  36. int edit_line;
  37. int key_linepos;
  38. colour3_t colourconLGray = { 220, 220, 220 };
  39. colour3_t colourconLLGray = { 192, 192, 192 };
  40. /*
  41. -----------------------------------------------------------------------------
  42. Function:
  43. Parameters:
  44. Returns: Nothing.
  45. Notes:
  46. -----------------------------------------------------------------------------
  47. */
  48. PRIVATE void DrawString( int x, int y, char *s )
  49. {
  50. Font_put_line( FONT0, x, y, s );
  51. }
  52. /*
  53. -----------------------------------------------------------------------------
  54. Function: Key_ClearTyping -Clear any keys that where typed.
  55. Parameters: Nothing.
  56. Returns: Nothing.
  57. Notes:
  58. -----------------------------------------------------------------------------
  59. */
  60. void Key_ClearTyping( void )
  61. {
  62. key_lines[ edit_line ][ 1 ] = 0; // clear any typing
  63. key_linepos = 1;
  64. }
  65. /*
  66. -----------------------------------------------------------------------------
  67. Function: Con_ToggleConsole_f -Get ready to enter console.
  68. Parameters: Nothing.
  69. Returns: Nothing.
  70. Notes:
  71. -----------------------------------------------------------------------------
  72. */
  73. PUBLIC void Con_ToggleConsole_f( void )
  74. {
  75. Key_ClearTyping();
  76. Con_ClearNotify();
  77. }
  78. /*
  79. -----------------------------------------------------------------------------
  80. Function: Con_Clear_f -Clear console text buffer.
  81. Parameters: Nothing.
  82. Returns: Nothing.
  83. Notes:
  84. Zero sets con.text memory block.
  85. -----------------------------------------------------------------------------
  86. */
  87. PRIVATE void Con_Clear_f( void )
  88. {
  89. memset( con.text, ' ', CON_TEXTSIZE );
  90. }
  91. /*
  92. -----------------------------------------------------------------------------
  93. Function: Con_Dump_f -Save the console contents out to a file.
  94. Parameters: Nothing.
  95. Returns: Nothing.
  96. Notes:
  97. -----------------------------------------------------------------------------
  98. */
  99. PRIVATE void Con_Dump_f( void )
  100. {
  101. int length, x;
  102. char *line;
  103. FILE *f;
  104. char buffer[1024];
  105. char name[MAX_OSPATH];
  106. if( Cmd_Argc() != 2 )
  107. {
  108. Com_Printf( "usage: conDump <filename>\n" );
  109. return;
  110. }
  111. my_snprintf( name, sizeof( name ), "%s/%s.txt", FS_Gamedir(), Cmd_Argv( 1 ) );
  112. Com_Printf( "Dumped console text to %s.\n", name );
  113. FS_CreatePath( name );
  114. f = fopen( name, "w" );
  115. if( ! f )
  116. {
  117. Com_Printf( "ERROR: couldn't open.\n" );
  118. return;
  119. }
  120. // skip empty lines
  121. for( length = con.current - con.totallines + 1; length <= con.current; ++length )
  122. {
  123. line = con.text + (length % con.totallines) * con.linewidth;
  124. for( x = 0; x < con.linewidth; ++x )
  125. {
  126. if( line[ x ] != ' ' )
  127. {
  128. break;
  129. }
  130. }
  131. if( x != con.linewidth )
  132. {
  133. break;
  134. }
  135. }
  136. // write the remaining lines
  137. buffer[ con.linewidth ] = '\0';
  138. for( ; length <= con.current ; ++length )
  139. {
  140. line = con.text + (length % con.totallines) * con.linewidth;
  141. my_strlcpy( buffer, line, con.linewidth );
  142. for( x = con.linewidth - 1; x >= 0; --x )
  143. {
  144. if( buffer[ x ] == ' ' )
  145. {
  146. buffer[ x ] = '\0'; // NUL-terminate string
  147. }
  148. else
  149. {
  150. break;
  151. }
  152. }
  153. for( x = 0; buffer[ x ]; ++x )
  154. {
  155. buffer[ x ] &= 0x7f;
  156. }
  157. fprintf( f, "%s\n", buffer );
  158. }
  159. fclose( f );
  160. }
  161. /*
  162. -----------------------------------------------------------------------------
  163. Function: Con_ClearNotify -Clear console con.times.
  164. Parameters: Nothing.
  165. Returns: Nothing.
  166. Notes:
  167. -----------------------------------------------------------------------------
  168. */
  169. PUBLIC void Con_ClearNotify( void )
  170. {
  171. int i;
  172. for( i = 0; i < NUM_CON_TIMES; ++i )
  173. {
  174. con.times[ i ] = 0;
  175. }
  176. }
  177. /*
  178. -----------------------------------------------------------------------------
  179. Function: Con_CheckResize -If the line width has changed, reformat the buffer.
  180. Parameters: Nothing.
  181. Returns: Nothing.
  182. Notes:
  183. -----------------------------------------------------------------------------
  184. */
  185. PUBLIC void Con_CheckResize( void )
  186. {
  187. int i, j, width, oldwidth, oldtotallines, numlines, numchars;
  188. char tbuf[ CON_TEXTSIZE ];
  189. width = (viddef.width >> 3) - 2;
  190. if( width == con.linewidth )
  191. {
  192. return;
  193. }
  194. if( width < 1 ) // video hasn't been initialized yet
  195. {
  196. width = 38;
  197. con.linewidth = width;
  198. con.totallines = CON_TEXTSIZE / con.linewidth;
  199. memset( con.text, ' ', CON_TEXTSIZE );
  200. }
  201. else
  202. {
  203. oldwidth = con.linewidth;
  204. con.linewidth = width;
  205. oldtotallines = con.totallines;
  206. con.totallines = CON_TEXTSIZE / con.linewidth;
  207. numlines = oldtotallines;
  208. if( con.totallines < numlines )
  209. {
  210. numlines = con.totallines;
  211. }
  212. numchars = oldwidth;
  213. if( con.linewidth < numchars )
  214. {
  215. numchars = con.linewidth;
  216. }
  217. memcpy( tbuf, con.text, CON_TEXTSIZE );
  218. memset( con.text, ' ', CON_TEXTSIZE );
  219. for( i = 0; i < numlines; ++i )
  220. {
  221. for( j = 0; j < numchars; ++j )
  222. {
  223. con.text[(con.totallines - 1 - i) * con.linewidth + j] =
  224. tbuf[((con.current - i + oldtotallines) %
  225. oldtotallines) * oldwidth + j];
  226. }
  227. }
  228. Con_ClearNotify();
  229. }
  230. con.current = con.totallines - 1;
  231. con.display = con.current;
  232. }
  233. /*
  234. -----------------------------------------------------------------------------
  235. Function:
  236. Parameters: Nothing.
  237. Returns: Nothing.
  238. Notes:
  239. -----------------------------------------------------------------------------
  240. */
  241. PUBLIC void Con_Init( void )
  242. {
  243. con.linewidth = -1;
  244. Con_CheckResize();
  245. Com_Printf( "Console Initialized\n" );
  246. //
  247. // register our commands
  248. //
  249. con_notifytime = Cvar_Get( "con_notifytime", "90", CVAR_INIT );
  250. scr_conspeed = Cvar_Get( "scr_conspeed", "90", CVAR_INIT );
  251. Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f );
  252. Cmd_AddCommand( "clear", Con_Clear_f );
  253. Cmd_AddCommand( "conDump", Con_Dump_f );
  254. con.initialized = true;
  255. }
  256. /*
  257. -----------------------------------------------------------------------------
  258. Function: Con_Linefeed -Fill rest of line with spaces.
  259. Parameters: Nothing.
  260. Returns: Nothing.
  261. Notes:
  262. -----------------------------------------------------------------------------
  263. */
  264. PRIVATE void Con_Linefeed( void )
  265. {
  266. con.x = 0;
  267. if( con.display == con.current )
  268. {
  269. con.display++;
  270. }
  271. con.current++;
  272. memset( &con.text[ (con.current % con.totallines) * con.linewidth ]
  273. , ' ', con.linewidth );
  274. }
  275. /*
  276. -----------------------------------------------------------------------------
  277. Function: Con_Print -Print formatted message to the console.
  278. Parameters: txt -[in] Text message to print
  279. Returns: Nothing.
  280. Notes:
  281. Handles cursor positioning, line wrapping, etc
  282. All console printing must go through this in order to be logged to disk
  283. If no console is visible, the text will appear at the top of the game window
  284. -----------------------------------------------------------------------------
  285. */
  286. PUBLIC void Con_Print( char *txt )
  287. {
  288. int y;
  289. int c, wordlength;
  290. static int cr;
  291. int mask;
  292. #ifdef IPHONE
  293. printf( "%s", txt );
  294. #endif
  295. if( ! con.initialized )
  296. {
  297. return;
  298. }
  299. if( txt[ 0 ] == 1 || txt[ 0 ] == 2 )
  300. {
  301. mask = 128; // go to colored text
  302. txt++;
  303. }
  304. else
  305. {
  306. mask = 0;
  307. }
  308. while( (c = *txt) )
  309. {
  310. // count word length
  311. for( wordlength = 0 ; wordlength < con.linewidth ; ++wordlength )
  312. {
  313. if( txt[ wordlength ] <= ' ')
  314. {
  315. break;
  316. }
  317. }
  318. // word wrap
  319. if( wordlength != con.linewidth && (con.x + wordlength > con.linewidth) )
  320. {
  321. con.x = 0;
  322. }
  323. txt++;
  324. if( cr )
  325. {
  326. con.current--;
  327. cr = false;
  328. }
  329. if( ! con.x )
  330. {
  331. Con_Linefeed();
  332. // mark time for transparent overlay
  333. if( con.current >= 0 )
  334. {
  335. con.times[ con.current % NUM_CON_TIMES ] = iphoneFrameNum;
  336. }
  337. }
  338. switch( c )
  339. {
  340. case '\n':
  341. con.x = 0;
  342. break;
  343. case '\r':
  344. con.x = 0;
  345. cr = 1;
  346. break;
  347. default: // display character and advance
  348. y = con.current % con.totallines;
  349. con.text[ y * con.linewidth + con.x] = c | mask | con.ormask;
  350. con.x++;
  351. if( con.x >= con.linewidth )
  352. {
  353. con.x = 0;
  354. }
  355. break;
  356. }
  357. }
  358. }
  359. /*
  360. -----------------------------------------------------------------------------
  361. Function: Con_CenteredPrint -Print message that is centered on screen.
  362. Parameters: text -[in] Message string.
  363. Returns: Nothing.
  364. Notes:
  365. -----------------------------------------------------------------------------
  366. */
  367. PUBLIC void Con_CenteredPrint( const char *text )
  368. {
  369. int length;
  370. char buffer[ 1024 ];
  371. length = strlen( text );
  372. length = ( con.linewidth - length ) >> 1;
  373. if( length < 0 )
  374. {
  375. length = 0;
  376. }
  377. memset( buffer, ' ', length );
  378. my_strlcpy( buffer + length, text, sizeof( buffer ) - length );
  379. my_strlcat( buffer, "\n", sizeof( buffer ) );
  380. Con_Print( buffer );
  381. }
  382. /*
  383. ==============================================================================
  384. DRAWING
  385. ==============================================================================
  386. */
  387. /*
  388. -----------------------------------------------------------------------------
  389. Function: Con_DrawInput -The input line scrolls horizontally if typing
  390. goes beyond the right edge.
  391. Parameters: Nothing.
  392. Returns: Nothing.
  393. Notes:
  394. -----------------------------------------------------------------------------
  395. */
  396. PRIVATE void Con_DrawInput( void )
  397. {
  398. int y;
  399. int i;
  400. char *text;
  401. char buf[256];
  402. W16 heightfont, charwidth;
  403. static char ccursor[ 2 ] = { ' ', '_' };
  404. heightfont = Font_GetSize( FONT0 ) + 4;
  405. #ifdef IPHONE
  406. {
  407. const char * GetCurrentCommandLine();
  408. extern int consoleActive;
  409. if ( consoleActive == 0 ) {
  410. return;
  411. }
  412. strcpy( buf, GetCurrentCommandLine() );
  413. key_linepos = strlen( buf );
  414. buf[key_linepos+1] = 0;
  415. text = buf;
  416. }
  417. #else
  418. if( ClientStatic.key_dest != key_console )
  419. {
  420. return; // don't draw anything (always draw if not active)
  421. }
  422. text = key_lines[ edit_line ];
  423. #endif
  424. // add the cursor frame
  425. text[ key_linepos ] = ccursor[ 0 + ((int)( iphoneFrameNum >> 3 ) & 1 ) ];
  426. // fill out remainder with spaces
  427. for( i = key_linepos + 1 ; i < con.linewidth ; ++i )
  428. {
  429. text[ i ] = ' ';
  430. }
  431. // prestep if horizontally scrolling
  432. if( key_linepos >= con.linewidth )
  433. {
  434. text += 1 + key_linepos - con.linewidth;
  435. }
  436. // draw it
  437. y = con.vislines - heightfont;
  438. charwidth = 8;
  439. for( i = 0 ; i < con.linewidth ; ++i )
  440. {
  441. charwidth += Font_put_character( FONT0, charwidth, con.vislines - 22, text[ i ] );
  442. }
  443. // remove cursor
  444. key_lines[ edit_line ][ key_linepos ] = 0;
  445. }
  446. /*
  447. -----------------------------------------------------------------------------
  448. Function: Con_DrawNotify -Draws the last few lines of output transparently
  449. over the game top.
  450. Parameters: Nothing.
  451. Returns: Nothing.
  452. Notes:
  453. -----------------------------------------------------------------------------
  454. */
  455. PUBLIC void Con_DrawNotify( void )
  456. {
  457. int x, v;
  458. int charwidth;
  459. char *text;
  460. int i;
  461. int time;
  462. // char *s;
  463. // int skip;
  464. W16 size;
  465. Font_SetSize( FONT1, 1 );
  466. size = Font_GetSize( FONT1 );
  467. Font_SetColour( FONT1, colourWhite );
  468. v = 0;
  469. for( i = con.current - NUM_CON_TIMES+1 ; i <= con.current ; ++i )
  470. {
  471. if( i < 0 )
  472. {
  473. continue;
  474. }
  475. time = FloatToInt( con.times[ i % NUM_CON_TIMES ] );
  476. if( time == 0 )
  477. {
  478. continue;
  479. }
  480. time = iphoneFrameNum- time;
  481. if( time > con_notifytime->value )
  482. {
  483. continue;
  484. }
  485. text = con.text + (i % con.totallines) * con.linewidth;
  486. charwidth = 0;
  487. for( x = 0 ; x < con.linewidth ; ++x )
  488. {
  489. charwidth += Font_put_character( FONT1, charwidth, v, text[ x ] );
  490. }
  491. v += size;
  492. }
  493. Font_SetSize( FONT1, 2 );
  494. }
  495. /*
  496. -----------------------------------------------------------------------------
  497. Function: Con_DrawConsole -Draws the console.
  498. Parameters: frac -[in] Fraction of the screen the console will take up.
  499. Range is 0.0 to 1.0
  500. Returns: Nothing.
  501. Notes:
  502. -----------------------------------------------------------------------------
  503. */
  504. PUBLIC void Con_DrawConsole( float frac )
  505. {
  506. int i, x, y;
  507. int rows;
  508. char *text;
  509. int row;
  510. W32 lines;
  511. char version[ 64 ];
  512. // int w, h;
  513. int heightfont, charwidth;
  514. lines = FloatToInt( viddef.height * frac );
  515. if( lines < 1 )
  516. {
  517. return;
  518. }
  519. Font_SetSize( FONT0, 1 );
  520. Font_SetColour( FONT0, colourconLLGray );
  521. heightfont = Font_GetSize( FONT0 );
  522. if( lines > viddef.height )
  523. {
  524. lines = viddef.height;
  525. }
  526. //
  527. // Draw the background
  528. //
  529. R_Draw_Fill( 0, -viddef.height + lines, viddef.width, viddef.height, colourBlack );
  530. R_Draw_Fill( 0, lines-2, viddef.width, 2, colourconLGray );
  531. // SCR_AddDirtyPoint( 0, 0 );
  532. // SCR_AddDirtyPoint( viddef.width-1, lines-1 );
  533. my_snprintf( version, sizeof( version ), "v%s", APP_VERSION );
  534. Font_SetColour( FONT0, colourGreen );
  535. Font_put_lineR2L( FONT0, viddef.width-20, lines - 2 - heightfont, version );
  536. Font_SetColour( FONT0, colourconLLGray );
  537. //
  538. // Draw the text
  539. //
  540. con.vislines = lines;
  541. #if 0
  542. rows = (lines - 8) >> 3; // rows of text to draw
  543. y = lines - 24;
  544. #else
  545. rows = (lines - 22) >> 3; // rows of text to draw
  546. y = lines - 30;
  547. #endif
  548. // draw from the bottom up
  549. if( con.display != con.current )
  550. {
  551. // draw arrows to show the buffer is backscrolled
  552. for( x = 0; x < con.linewidth; x += 4 )
  553. {
  554. Font_put_character( FONT0, (x+1) << 3, y, '^' );
  555. }
  556. y -= heightfont;
  557. rows--;
  558. }
  559. row = con.display;
  560. for( i = 0 ; i < rows ; ++i, y -= heightfont, --row )
  561. {
  562. if( row < 0 )
  563. {
  564. break;
  565. }
  566. if( con.current - row >= con.totallines )
  567. {
  568. break; // past scrollback wrap point
  569. }
  570. text = con.text + (row % con.totallines) * con.linewidth;
  571. charwidth = 0;
  572. for( x = 0; x < con.linewidth; ++x )
  573. {
  574. charwidth += Font_put_character( FONT0, charwidth, y, text[ x ] );
  575. }
  576. }
  577. // draw the input prompt, user text, and cursor if desired
  578. Con_DrawInput();
  579. Font_SetSize( FONT0, 2 );
  580. }
  581. /*
  582. -----------------------------------------------------------------------------
  583. Function: Client_Screen_RunConsole -Figure out how the console should be
  584. drawn.
  585. Parameters: Nothing.
  586. Returns: Nothing.
  587. Notes:
  588. -----------------------------------------------------------------------------
  589. */
  590. PUBLIC void Client_Screen_RunConsole( void )
  591. {
  592. if( scr_conlines < scr_con_current )
  593. {
  594. scr_con_current -= scr_conspeed->value * iphoneFrameNum;
  595. if( scr_conlines > scr_con_current )
  596. {
  597. scr_con_current = scr_conlines;
  598. }
  599. }
  600. else if( scr_conlines > scr_con_current )
  601. {
  602. scr_con_current += scr_conspeed->value * iphoneFrameNum;
  603. if( scr_conlines < scr_con_current )
  604. {
  605. scr_con_current = scr_conlines;
  606. }
  607. }
  608. }
  609. /*
  610. -----------------------------------------------------------------------------
  611. Function: Client_Screen_DrawConsole -Draw the console on the screen.
  612. Parameters: Nothing.
  613. Returns: Nothing.
  614. Notes:
  615. -----------------------------------------------------------------------------
  616. */
  617. PUBLIC void Client_Screen_DrawConsole( void )
  618. {
  619. Con_CheckResize();
  620. if( scr_con_current )
  621. {
  622. Con_DrawConsole( scr_con_current );
  623. }
  624. else
  625. {
  626. Con_DrawNotify();
  627. }
  628. }