Files
Wolf3D-iOS/wolf3d/newCode/env/console.c

823 lines
16 KiB
C

/*
Copyright (C) 2004-2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
Copyright (C) 1997-2001 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.
*/
/*
* console.c: Console drawing and management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
*
* Acknowledgement:
* This code was derived from Quake II, and was originally
* written by Id Software, Inc.
*
*/
#include "../wolfiphone.h"
extern viddef_t viddef;
extern int consoleActive;
console_t con;
float scr_conlines;
float scr_con_current;
cvar_t *con_notifytime;
cvar_t *scr_conspeed;
#define MAXCMDLINE 256
char key_lines[ 32 ][ MAXCMDLINE ];
int edit_line;
int key_linepos;
colour3_t colourconLGray = { 220, 220, 220 };
colour3_t colourconLLGray = { 192, 192, 192 };
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void DrawString( int x, int y, char *s )
{
Font_put_line( FONT0, x, y, s );
}
/*
-----------------------------------------------------------------------------
Function: Key_ClearTyping -Clear any keys that where typed.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
void Key_ClearTyping( void )
{
key_lines[ edit_line ][ 1 ] = 0; // clear any typing
key_linepos = 1;
}
/*
-----------------------------------------------------------------------------
Function: Con_ToggleConsole_f -Get ready to enter console.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_ToggleConsole_f( void )
{
Key_ClearTyping();
Con_ClearNotify();
}
/*
-----------------------------------------------------------------------------
Function: Con_Clear_f -Clear console text buffer.
Parameters: Nothing.
Returns: Nothing.
Notes:
Zero sets con.text memory block.
-----------------------------------------------------------------------------
*/
PRIVATE void Con_Clear_f( void )
{
memset( con.text, ' ', CON_TEXTSIZE );
}
/*
-----------------------------------------------------------------------------
Function: Con_Dump_f -Save the console contents out to a file.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Con_Dump_f( void )
{
int length, x;
char *line;
FILE *f;
char buffer[1024];
char name[MAX_OSPATH];
if( Cmd_Argc() != 2 )
{
Com_Printf( "usage: conDump <filename>\n" );
return;
}
my_snprintf( name, sizeof( name ), "%s/%s.txt", FS_Gamedir(), Cmd_Argv( 1 ) );
Com_Printf( "Dumped console text to %s.\n", name );
FS_CreatePath( name );
f = fopen( name, "w" );
if( ! f )
{
Com_Printf( "ERROR: couldn't open.\n" );
return;
}
// skip empty lines
for( length = con.current - con.totallines + 1; length <= con.current; ++length )
{
line = con.text + (length % con.totallines) * con.linewidth;
for( x = 0; x < con.linewidth; ++x )
{
if( line[ x ] != ' ' )
{
break;
}
}
if( x != con.linewidth )
{
break;
}
}
// write the remaining lines
buffer[ con.linewidth ] = '\0';
for( ; length <= con.current ; ++length )
{
line = con.text + (length % con.totallines) * con.linewidth;
my_strlcpy( buffer, line, con.linewidth );
for( x = con.linewidth - 1; x >= 0; --x )
{
if( buffer[ x ] == ' ' )
{
buffer[ x ] = '\0'; // NUL-terminate string
}
else
{
break;
}
}
for( x = 0; buffer[ x ]; ++x )
{
buffer[ x ] &= 0x7f;
}
fprintf( f, "%s\n", buffer );
}
fclose( f );
}
/*
-----------------------------------------------------------------------------
Function: Con_ClearNotify -Clear console con.times.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_ClearNotify( void )
{
int i;
for( i = 0; i < NUM_CON_TIMES; ++i )
{
con.times[ i ] = 0;
}
}
/*
-----------------------------------------------------------------------------
Function: Con_CheckResize -If the line width has changed, reformat the buffer.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_CheckResize( void )
{
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
char tbuf[ CON_TEXTSIZE ];
width = (viddef.width >> 3) - 2;
if( width == con.linewidth )
{
return;
}
if( width < 1 ) // video hasn't been initialized yet
{
width = 38;
con.linewidth = width;
con.totallines = CON_TEXTSIZE / con.linewidth;
memset( con.text, ' ', CON_TEXTSIZE );
}
else
{
oldwidth = con.linewidth;
con.linewidth = width;
oldtotallines = con.totallines;
con.totallines = CON_TEXTSIZE / con.linewidth;
numlines = oldtotallines;
if( con.totallines < numlines )
{
numlines = con.totallines;
}
numchars = oldwidth;
if( con.linewidth < numchars )
{
numchars = con.linewidth;
}
memcpy( tbuf, con.text, CON_TEXTSIZE );
memset( con.text, ' ', CON_TEXTSIZE );
for( i = 0; i < numlines; ++i )
{
for( j = 0; j < numchars; ++j )
{
con.text[(con.totallines - 1 - i) * con.linewidth + j] =
tbuf[((con.current - i + oldtotallines) %
oldtotallines) * oldwidth + j];
}
}
Con_ClearNotify();
}
con.current = con.totallines - 1;
con.display = con.current;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_Init( void )
{
con.linewidth = -1;
Con_CheckResize();
Com_Printf( "Console Initialized\n" );
//
// register our commands
//
con_notifytime = Cvar_Get( "con_notifytime", "90", CVAR_INIT );
scr_conspeed = Cvar_Get( "scr_conspeed", "90", CVAR_INIT );
Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f );
Cmd_AddCommand( "clear", Con_Clear_f );
Cmd_AddCommand( "conDump", Con_Dump_f );
con.initialized = true;
}
/*
-----------------------------------------------------------------------------
Function: Con_Linefeed -Fill rest of line with spaces.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Con_Linefeed( void )
{
con.x = 0;
if( con.display == con.current )
{
con.display++;
}
con.current++;
memset( &con.text[ (con.current % con.totallines) * con.linewidth ]
, ' ', con.linewidth );
}
/*
-----------------------------------------------------------------------------
Function: Con_Print -Print formatted message to the console.
Parameters: txt -[in] Text message to print
Returns: Nothing.
Notes:
Handles cursor positioning, line wrapping, etc
All console printing must go through this in order to be logged to disk
If no console is visible, the text will appear at the top of the game window
-----------------------------------------------------------------------------
*/
PUBLIC void Con_Print( char *txt )
{
int y;
int c, wordlength;
static int cr;
int mask;
#ifdef IPHONE
printf( "%s", txt );
#endif
if( ! con.initialized )
{
return;
}
if( txt[ 0 ] == 1 || txt[ 0 ] == 2 )
{
mask = 128; // go to colored text
txt++;
}
else
{
mask = 0;
}
while( (c = *txt) )
{
// count word length
for( wordlength = 0 ; wordlength < con.linewidth ; ++wordlength )
{
if( txt[ wordlength ] <= ' ')
{
break;
}
}
// word wrap
if( wordlength != con.linewidth && (con.x + wordlength > con.linewidth) )
{
con.x = 0;
}
txt++;
if( cr )
{
con.current--;
cr = false;
}
if( ! con.x )
{
Con_Linefeed();
// mark time for transparent overlay
if( con.current >= 0 )
{
con.times[ con.current % NUM_CON_TIMES ] = iphoneFrameNum;
}
}
switch( c )
{
case '\n':
con.x = 0;
break;
case '\r':
con.x = 0;
cr = 1;
break;
default: // display character and advance
y = con.current % con.totallines;
con.text[ y * con.linewidth + con.x] = c | mask | con.ormask;
con.x++;
if( con.x >= con.linewidth )
{
con.x = 0;
}
break;
}
}
}
/*
-----------------------------------------------------------------------------
Function: Con_CenteredPrint -Print message that is centered on screen.
Parameters: text -[in] Message string.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_CenteredPrint( const char *text )
{
int length;
char buffer[ 1024 ];
length = strlen( text );
length = ( con.linewidth - length ) >> 1;
if( length < 0 )
{
length = 0;
}
memset( buffer, ' ', length );
my_strlcpy( buffer + length, text, sizeof( buffer ) - length );
my_strlcat( buffer, "\n", sizeof( buffer ) );
Con_Print( buffer );
}
/*
==============================================================================
DRAWING
==============================================================================
*/
/*
-----------------------------------------------------------------------------
Function: Con_DrawInput -The input line scrolls horizontally if typing
goes beyond the right edge.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Con_DrawInput( void )
{
int y;
int i;
char *text;
char buf[256];
W16 heightfont, charwidth;
static char ccursor[ 2 ] = { ' ', '_' };
heightfont = Font_GetSize( FONT0 ) + 4;
#ifdef IPHONE
{
const char * GetCurrentCommandLine();
extern int consoleActive;
if ( consoleActive == 0 ) {
return;
}
strcpy( buf, GetCurrentCommandLine() );
key_linepos = strlen( buf );
buf[key_linepos+1] = 0;
text = buf;
}
#else
if( ClientStatic.key_dest != key_console )
{
return; // don't draw anything (always draw if not active)
}
text = key_lines[ edit_line ];
#endif
// add the cursor frame
text[ key_linepos ] = ccursor[ 0 + ((int)( iphoneFrameNum >> 3 ) & 1 ) ];
// fill out remainder with spaces
for( i = key_linepos + 1 ; i < con.linewidth ; ++i )
{
text[ i ] = ' ';
}
// prestep if horizontally scrolling
if( key_linepos >= con.linewidth )
{
text += 1 + key_linepos - con.linewidth;
}
// draw it
y = con.vislines - heightfont;
charwidth = 8;
for( i = 0 ; i < con.linewidth ; ++i )
{
charwidth += Font_put_character( FONT0, charwidth, con.vislines - 22, text[ i ] );
}
// remove cursor
key_lines[ edit_line ][ key_linepos ] = 0;
}
/*
-----------------------------------------------------------------------------
Function: Con_DrawNotify -Draws the last few lines of output transparently
over the game top.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_DrawNotify( void )
{
int x, v;
int charwidth;
char *text;
int i;
int time;
// char *s;
// int skip;
W16 size;
Font_SetSize( FONT1, 1 );
size = Font_GetSize( FONT1 );
Font_SetColour( FONT1, colourWhite );
v = 0;
for( i = con.current - NUM_CON_TIMES+1 ; i <= con.current ; ++i )
{
if( i < 0 )
{
continue;
}
time = FloatToInt( con.times[ i % NUM_CON_TIMES ] );
if( time == 0 )
{
continue;
}
time = iphoneFrameNum- time;
if( time > con_notifytime->value )
{
continue;
}
text = con.text + (i % con.totallines) * con.linewidth;
charwidth = 0;
for( x = 0 ; x < con.linewidth ; ++x )
{
charwidth += Font_put_character( FONT1, charwidth, v, text[ x ] );
}
v += size;
}
Font_SetSize( FONT1, 2 );
}
/*
-----------------------------------------------------------------------------
Function: Con_DrawConsole -Draws the console.
Parameters: frac -[in] Fraction of the screen the console will take up.
Range is 0.0 to 1.0
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Con_DrawConsole( float frac )
{
int i, x, y;
int rows;
char *text;
int row;
W32 lines;
char version[ 64 ];
// int w, h;
int heightfont, charwidth;
lines = FloatToInt( viddef.height * frac );
if( lines < 1 )
{
return;
}
Font_SetSize( FONT0, 1 );
Font_SetColour( FONT0, colourconLLGray );
heightfont = Font_GetSize( FONT0 );
if( lines > viddef.height )
{
lines = viddef.height;
}
//
// Draw the background
//
R_Draw_Fill( 0, -viddef.height + lines, viddef.width, viddef.height, colourBlack );
R_Draw_Fill( 0, lines-2, viddef.width, 2, colourconLGray );
// SCR_AddDirtyPoint( 0, 0 );
// SCR_AddDirtyPoint( viddef.width-1, lines-1 );
my_snprintf( version, sizeof( version ), "v%s", APP_VERSION );
Font_SetColour( FONT0, colourGreen );
Font_put_lineR2L( FONT0, viddef.width-20, lines - 2 - heightfont, version );
Font_SetColour( FONT0, colourconLLGray );
//
// Draw the text
//
con.vislines = lines;
#if 0
rows = (lines - 8) >> 3; // rows of text to draw
y = lines - 24;
#else
rows = (lines - 22) >> 3; // rows of text to draw
y = lines - 30;
#endif
// draw from the bottom up
if( con.display != con.current )
{
// draw arrows to show the buffer is backscrolled
for( x = 0; x < con.linewidth; x += 4 )
{
Font_put_character( FONT0, (x+1) << 3, y, '^' );
}
y -= heightfont;
rows--;
}
row = con.display;
for( i = 0 ; i < rows ; ++i, y -= heightfont, --row )
{
if( row < 0 )
{
break;
}
if( con.current - row >= con.totallines )
{
break; // past scrollback wrap point
}
text = con.text + (row % con.totallines) * con.linewidth;
charwidth = 0;
for( x = 0; x < con.linewidth; ++x )
{
charwidth += Font_put_character( FONT0, charwidth, y, text[ x ] );
}
}
// draw the input prompt, user text, and cursor if desired
Con_DrawInput();
Font_SetSize( FONT0, 2 );
}
/*
-----------------------------------------------------------------------------
Function: Client_Screen_RunConsole -Figure out how the console should be
drawn.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Client_Screen_RunConsole( void )
{
if( scr_conlines < scr_con_current )
{
scr_con_current -= scr_conspeed->value * iphoneFrameNum;
if( scr_conlines > scr_con_current )
{
scr_con_current = scr_conlines;
}
}
else if( scr_conlines > scr_con_current )
{
scr_con_current += scr_conspeed->value * iphoneFrameNum;
if( scr_conlines < scr_con_current )
{
scr_con_current = scr_conlines;
}
}
}
/*
-----------------------------------------------------------------------------
Function: Client_Screen_DrawConsole -Draw the console on the screen.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Client_Screen_DrawConsole( void )
{
Con_CheckResize();
if( scr_con_current )
{
Con_DrawConsole( scr_con_current );
}
else
{
Con_DrawNotify();
}
}