* Merge unified-sdl to trunk
* Bump Q3_VERSION to 1.35
This commit is contained in:
parent
39abffeb3b
commit
672cfbf16f
188 changed files with 5071 additions and 41739 deletions
36
code/sys/sys_loadlib.h
Normal file
36
code/sys/sys_loadlib.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifdef DEDICATED
|
||||
# include <dlfcn.h>
|
||||
# define Sys_LoadLibrary(f) dlopen(f,RTLD_NOW)
|
||||
# define Sys_UnloadLibrary(h) dlclose(h)
|
||||
# define Sys_LoadFunction(h,fn) dlsym(h,fn)
|
||||
# define Sys_LibraryError() dlerror()
|
||||
#else
|
||||
# include "SDL.h"
|
||||
# include "SDL_loadso.h"
|
||||
# define Sys_LoadLibrary(f) SDL_LoadObject(f)
|
||||
# define Sys_UnloadLibrary(h) SDL_UnloadObject(h)
|
||||
# define Sys_LoadFunction(h,fn) SDL_LoadFunction(h,fn)
|
||||
# define Sys_LibraryError() SDL_GetError()
|
||||
#endif
|
40
code/sys/sys_local.h
Normal file
40
code/sys/sys_local.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
// Input subsystem
|
||||
void IN_Init (void);
|
||||
void IN_Frame (void);
|
||||
void IN_Shutdown (void);
|
||||
|
||||
// TTY console
|
||||
void TTY_Hide( void );
|
||||
void TTY_Show( void );
|
||||
void TTY_Shutdown( void );
|
||||
void TTY_Init( void );
|
||||
char *TTY_ConsoleInput(void);
|
||||
|
||||
#ifdef MACOS_X
|
||||
char *Sys_StripAppBundle( char *pwd );
|
||||
#endif
|
646
code/sys/sys_main.c
Normal file
646
code/sys/sys_main.c
Normal file
|
@ -0,0 +1,646 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef DEDICATED
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
|
||||
#include "sys_local.h"
|
||||
#include "sys_loadlib.h"
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
static char binaryPath[ MAX_OSPATH ] = { 0 };
|
||||
static char installPath[ MAX_OSPATH ] = { 0 };
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_SetBinaryPath
|
||||
=================
|
||||
*/
|
||||
void Sys_SetBinaryPath(const char *path)
|
||||
{
|
||||
Q_strncpyz(binaryPath, path, sizeof(binaryPath));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_BinaryPath
|
||||
=================
|
||||
*/
|
||||
char *Sys_BinaryPath(void)
|
||||
{
|
||||
return binaryPath;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_SetDefaultInstallPath
|
||||
=================
|
||||
*/
|
||||
void Sys_SetDefaultInstallPath(const char *path)
|
||||
{
|
||||
Q_strncpyz(installPath, path, sizeof(installPath));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_DefaultInstallPath
|
||||
=================
|
||||
*/
|
||||
char *Sys_DefaultInstallPath(void)
|
||||
{
|
||||
if (*installPath)
|
||||
return installPath;
|
||||
else
|
||||
return Sys_Cwd();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_In_Restart_f
|
||||
|
||||
Restart the input subsystem
|
||||
=================
|
||||
*/
|
||||
void Sys_In_Restart_f( void )
|
||||
{
|
||||
IN_Shutdown();
|
||||
IN_Init();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ConsoleInputInit
|
||||
|
||||
Start the console input subsystem
|
||||
=================
|
||||
*/
|
||||
void Sys_ConsoleInputInit( void )
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
TTY_Init( );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ConsoleInputShutdown
|
||||
|
||||
Shutdown the console input subsystem
|
||||
=================
|
||||
*/
|
||||
void Sys_ConsoleInputShutdown( void )
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
TTY_Shutdown( );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ConsoleInput
|
||||
|
||||
Handle new console input
|
||||
=================
|
||||
*/
|
||||
char *Sys_ConsoleInput(void)
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
return TTY_ConsoleInput( );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Exit
|
||||
|
||||
Single exit point (regular exit or in case of error)
|
||||
=================
|
||||
*/
|
||||
void Sys_Exit( int ex )
|
||||
{
|
||||
Sys_ConsoleInputShutdown();
|
||||
|
||||
#ifndef DEDICATED
|
||||
SDL_Quit( );
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
// _exit is called instead of exit since there are rumours of
|
||||
// GL libraries installing atexit calls that we don't want to call
|
||||
// FIXME: get some testing done with plain exit
|
||||
_exit(ex);
|
||||
#else
|
||||
// Cause a backtrace on error exits
|
||||
assert( ex == 0 );
|
||||
exit(ex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Quit
|
||||
=================
|
||||
*/
|
||||
void Sys_Quit (void)
|
||||
{
|
||||
CL_Shutdown ();
|
||||
Sys_Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_GetProcessorFeatures
|
||||
=================
|
||||
*/
|
||||
cpuFeatures_t Sys_GetProcessorFeatures( void )
|
||||
{
|
||||
cpuFeatures_t features = 0;
|
||||
|
||||
#ifndef DEDICATED
|
||||
if( SDL_HasRDTSC( ) ) features |= CF_RDTSC;
|
||||
if( SDL_HasMMX( ) ) features |= CF_MMX;
|
||||
if( SDL_HasMMXExt( ) ) features |= CF_MMX_EXT;
|
||||
if( SDL_Has3DNow( ) ) features |= CF_3DNOW;
|
||||
if( SDL_Has3DNowExt( ) ) features |= CF_3DNOW_EXT;
|
||||
if( SDL_HasSSE( ) ) features |= CF_SSE;
|
||||
if( SDL_HasSSE2( ) ) features |= CF_SSE2;
|
||||
if( SDL_HasAltiVec( ) ) features |= CF_ALTIVEC;
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Init
|
||||
=================
|
||||
*/
|
||||
void Sys_Init(void)
|
||||
{
|
||||
Cmd_AddCommand( "in_restart", Sys_In_Restart_f );
|
||||
Cvar_Set( "arch", OS_STRING " " ARCH_STRING );
|
||||
Cvar_Set( "username", Sys_GetCurrentUser( ) );
|
||||
}
|
||||
|
||||
static struct Q3ToAnsiColorTable_s
|
||||
{
|
||||
char Q3color;
|
||||
char *ANSIcolor;
|
||||
} TTY_colorTable[ ] =
|
||||
{
|
||||
{ COLOR_BLACK, "30" },
|
||||
{ COLOR_RED, "31" },
|
||||
{ COLOR_GREEN, "32" },
|
||||
{ COLOR_YELLOW, "33" },
|
||||
{ COLOR_BLUE, "34" },
|
||||
{ COLOR_CYAN, "36" },
|
||||
{ COLOR_MAGENTA, "35" },
|
||||
{ COLOR_WHITE, "0" }
|
||||
};
|
||||
|
||||
static int TTY_colorTableSize =
|
||||
sizeof( TTY_colorTable ) / sizeof( TTY_colorTable[ 0 ] );
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ANSIColorify
|
||||
|
||||
Transform Q3 colour codes to ANSI escape sequences
|
||||
=================
|
||||
*/
|
||||
static void Sys_ANSIColorify( const char *msg, char *buffer, int bufferSize )
|
||||
{
|
||||
int msgLength, pos;
|
||||
int i, j;
|
||||
char *escapeCode;
|
||||
char tempBuffer[ 7 ];
|
||||
|
||||
if( !msg || !buffer )
|
||||
return;
|
||||
|
||||
msgLength = strlen( msg );
|
||||
pos = 0;
|
||||
i = 0;
|
||||
buffer[ 0 ] = '\0';
|
||||
|
||||
while( i < msgLength )
|
||||
{
|
||||
if( msg[ i ] == '\n' )
|
||||
{
|
||||
Com_sprintf( tempBuffer, 7, "%c[0m\n", 0x1B );
|
||||
strncat( buffer, tempBuffer, bufferSize );
|
||||
i++;
|
||||
}
|
||||
else if( msg[ i ] == Q_COLOR_ESCAPE )
|
||||
{
|
||||
i++;
|
||||
|
||||
if( i < msgLength )
|
||||
{
|
||||
escapeCode = NULL;
|
||||
for( j = 0; j < TTY_colorTableSize; j++ )
|
||||
{
|
||||
if( msg[ i ] == TTY_colorTable[ j ].Q3color )
|
||||
{
|
||||
escapeCode = TTY_colorTable[ j ].ANSIcolor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( escapeCode )
|
||||
{
|
||||
Com_sprintf( tempBuffer, 7, "%c[%sm", 0x1B, escapeCode );
|
||||
strncat( buffer, tempBuffer, bufferSize );
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_sprintf( tempBuffer, 7, "%c", msg[ i++ ] );
|
||||
strncat( buffer, tempBuffer, bufferSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Print
|
||||
=================
|
||||
*/
|
||||
void Sys_Print( const char *msg )
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
TTY_Hide();
|
||||
#endif
|
||||
|
||||
if( com_ansiColor && com_ansiColor->integer )
|
||||
{
|
||||
char ansiColorString[ MAXPRINTMSG ];
|
||||
Sys_ANSIColorify( msg, ansiColorString, MAXPRINTMSG );
|
||||
fputs( ansiColorString, stderr );
|
||||
}
|
||||
else
|
||||
fputs(msg, stderr);
|
||||
|
||||
#ifdef DEDICATED
|
||||
TTY_Show();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Error
|
||||
=================
|
||||
*/
|
||||
void Sys_Error( const char *error, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
#ifdef DEDICATED
|
||||
TTY_Hide();
|
||||
#endif
|
||||
|
||||
CL_Shutdown ();
|
||||
|
||||
va_start (argptr,error);
|
||||
Q_vsnprintf (string, sizeof(string), error, argptr);
|
||||
va_end (argptr);
|
||||
fprintf(stderr, "Sys_Error: %s\n", string);
|
||||
|
||||
Sys_Exit( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Warn
|
||||
=================
|
||||
*/
|
||||
void Sys_Warn( char *warning, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
va_start (argptr,warning);
|
||||
Q_vsnprintf (string, sizeof(string), warning, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
#ifdef DEDICATED
|
||||
TTY_Hide();
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Warning: %s", string);
|
||||
|
||||
#ifdef DEDICATED
|
||||
TTY_Show();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Sys_FileTime
|
||||
|
||||
returns -1 if not present
|
||||
============
|
||||
*/
|
||||
int Sys_FileTime( char *path )
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (stat (path,&buf) == -1)
|
||||
return -1;
|
||||
|
||||
return buf.st_mtime;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_UnloadDll
|
||||
=================
|
||||
*/
|
||||
void Sys_UnloadDll( void *dllHandle )
|
||||
{
|
||||
if( !dllHandle )
|
||||
{
|
||||
Com_Printf("Sys_UnloadDll(NULL)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Sys_UnloadLibrary(dllHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_TryLibraryLoad
|
||||
=================
|
||||
*/
|
||||
static void* Sys_TryLibraryLoad(const char* base, const char* gamedir, const char* fname, char* fqpath )
|
||||
{
|
||||
void* libHandle;
|
||||
char* fn;
|
||||
|
||||
*fqpath = 0;
|
||||
|
||||
fn = FS_BuildOSPath( base, gamedir, fname );
|
||||
Com_Printf( "Sys_LoadDll(%s)... \n", fn );
|
||||
|
||||
libHandle = Sys_LoadLibrary(fn);
|
||||
|
||||
if(!libHandle) {
|
||||
Com_Printf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", fn, Sys_LibraryError() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn );
|
||||
Q_strncpyz ( fqpath , fn , MAX_QPATH ) ;
|
||||
|
||||
return libHandle;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_LoadDll
|
||||
|
||||
Used to load a development dll instead of a virtual machine
|
||||
#1 look down current path
|
||||
#2 look in fs_homepath
|
||||
#3 look in fs_basepath
|
||||
=================
|
||||
*/
|
||||
void *Sys_LoadDll( const char *name, char *fqpath ,
|
||||
intptr_t (**entryPoint)(int, ...),
|
||||
intptr_t (*systemcalls)(intptr_t, ...) )
|
||||
{
|
||||
void *libHandle;
|
||||
void (*dllEntry)( intptr_t (*syscallptr)(intptr_t, ...) );
|
||||
char curpath[MAX_OSPATH];
|
||||
char fname[MAX_OSPATH];
|
||||
char *basepath;
|
||||
char *homepath;
|
||||
char *pwdpath;
|
||||
char *gamedir;
|
||||
|
||||
assert( name );
|
||||
|
||||
getcwd(curpath, sizeof(curpath));
|
||||
snprintf (fname, sizeof(fname), "%s" ARCH_STRING DLL_EXT, name);
|
||||
|
||||
// TODO: use fs_searchpaths from files.c
|
||||
pwdpath = Sys_Cwd();
|
||||
basepath = Cvar_VariableString( "fs_basepath" );
|
||||
homepath = Cvar_VariableString( "fs_homepath" );
|
||||
gamedir = Cvar_VariableString( "fs_game" );
|
||||
|
||||
libHandle = Sys_TryLibraryLoad(pwdpath, gamedir, fname, fqpath);
|
||||
|
||||
if(!libHandle && homepath)
|
||||
libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname, fqpath);
|
||||
|
||||
if(!libHandle && basepath)
|
||||
libHandle = Sys_TryLibraryLoad(basepath, gamedir, fname, fqpath);
|
||||
|
||||
if(!libHandle) {
|
||||
Com_Printf ( "Sys_LoadDll(%s) failed to load library\n", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dllEntry = Sys_LoadFunction( libHandle, "dllEntry" );
|
||||
*entryPoint = Sys_LoadFunction( libHandle, "vmMain" );
|
||||
|
||||
if ( !*entryPoint || !dllEntry )
|
||||
{
|
||||
Com_Printf ( "Sys_LoadDll(%s) failed to find vmMain function:\n\"%s\" !\n", name, Sys_LibraryError( ) );
|
||||
Sys_UnloadLibrary(libHandle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Com_Printf ( "Sys_LoadDll(%s) found vmMain function at %p\n", name, *entryPoint );
|
||||
dllEntry( systemcalls );
|
||||
|
||||
return libHandle;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Idle
|
||||
=================
|
||||
*/
|
||||
static void Sys_Idle( void )
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
int appState = SDL_GetAppState( );
|
||||
int sleep = 0;
|
||||
|
||||
// If we have no input focus at all, sleep a bit
|
||||
if( !( appState & ( SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS ) ) )
|
||||
{
|
||||
Cvar_SetValue( "com_unfocused", 1 );
|
||||
sleep += 16;
|
||||
}
|
||||
else
|
||||
Cvar_SetValue( "com_unfocused", 0 );
|
||||
|
||||
// If we're minimised, sleep a bit more
|
||||
if( !( appState & SDL_APPACTIVE ) )
|
||||
{
|
||||
Cvar_SetValue( "com_minimized", 1 );
|
||||
sleep += 32;
|
||||
}
|
||||
else
|
||||
Cvar_SetValue( "com_minimized", 0 );
|
||||
|
||||
if( !com_dedicated->integer && sleep )
|
||||
SDL_Delay( sleep );
|
||||
#else
|
||||
// Dedicated server idles via NET_Sleep
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ParseArgs
|
||||
=================
|
||||
*/
|
||||
void Sys_ParseArgs( int argc, char **argv )
|
||||
{
|
||||
if( argc == 2 )
|
||||
{
|
||||
if( !strcmp( argv[1], "--version" ) ||
|
||||
!strcmp( argv[1], "-v" ) )
|
||||
{
|
||||
const char* date = __DATE__;
|
||||
#ifdef DEDICATED
|
||||
fprintf( stdout, Q3_VERSION " dedicated server (%s)\n", date );
|
||||
#else
|
||||
fprintf( stdout, Q3_VERSION " client (%s)\n", date );
|
||||
#endif
|
||||
Sys_Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DEFAULT_BASEDIR
|
||||
# ifdef MACOS_X
|
||||
# define DEFAULT_BASEDIR Sys_StripAppBundle(Sys_BinaryPath())
|
||||
# else
|
||||
# define DEFAULT_BASEDIR Sys_BinaryPath()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_SigHandler
|
||||
=================
|
||||
*/
|
||||
static void Sys_SigHandler( int signal )
|
||||
{
|
||||
static qboolean signalcaught = qfalse;
|
||||
|
||||
if( signalcaught )
|
||||
{
|
||||
fprintf( stderr, "DOUBLE SIGNAL FAULT: Received signal %d, exiting...\n",
|
||||
signal );
|
||||
}
|
||||
else
|
||||
{
|
||||
signalcaught = qtrue;
|
||||
fprintf( stderr, "Received signal %d, exiting...\n", signal );
|
||||
#ifndef DEDICATED
|
||||
CL_Shutdown();
|
||||
#endif
|
||||
SV_Shutdown( "Signal caught" );
|
||||
}
|
||||
|
||||
Sys_Exit( 0 ); // Exit with 0 to avoid recursive signals
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
main
|
||||
=================
|
||||
*/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int i;
|
||||
char commandLine[ MAX_STRING_CHARS ] = { 0 };
|
||||
|
||||
Sys_ParseArgs( argc, argv );
|
||||
Sys_SetBinaryPath( Sys_Dirname( argv[ 0 ] ) );
|
||||
Sys_SetDefaultInstallPath( DEFAULT_BASEDIR );
|
||||
|
||||
// Concatenate the command line for passing to Com_Init
|
||||
for( i = 1; i < argc; i++ )
|
||||
{
|
||||
Q_strcat( commandLine, sizeof( commandLine ), argv[ i ] );
|
||||
Q_strcat( commandLine, sizeof( commandLine ), " " );
|
||||
}
|
||||
|
||||
Com_Init( commandLine );
|
||||
NET_Init();
|
||||
|
||||
Sys_ConsoleInputInit();
|
||||
|
||||
#ifndef _WIN32
|
||||
// Windows doesn't have these signals
|
||||
signal( SIGHUP, Sys_SigHandler );
|
||||
signal( SIGQUIT, Sys_SigHandler );
|
||||
signal( SIGTRAP, Sys_SigHandler );
|
||||
signal( SIGIOT, Sys_SigHandler );
|
||||
signal( SIGBUS, Sys_SigHandler );
|
||||
#endif
|
||||
|
||||
signal( SIGILL, Sys_SigHandler );
|
||||
signal( SIGFPE, Sys_SigHandler );
|
||||
signal( SIGSEGV, Sys_SigHandler );
|
||||
signal( SIGTERM, Sys_SigHandler );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
Sys_Idle( );
|
||||
IN_Frame( );
|
||||
Com_Frame( );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
450
code/sys/sys_unix.c
Normal file
450
code/sys/sys_unix.c
Normal file
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <pwd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
// Used to determine where to store user-specific files
|
||||
static char homePath[ MAX_OSPATH ] = { 0 };
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_DefaultHomePath
|
||||
==================
|
||||
*/
|
||||
char *Sys_DefaultHomePath(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if( !*homePath )
|
||||
{
|
||||
if( ( p = getenv( "HOME" ) ) != NULL )
|
||||
{
|
||||
Q_strncpyz( homePath, p, sizeof( homePath ) );
|
||||
#ifdef MACOS_X
|
||||
Q_strcat( homePath, sizeof( homePath ), "/Library/Application Support/Quake3" );
|
||||
#else
|
||||
Q_strcat( homePath, sizeof( homePath ), "/.q3a" );
|
||||
#endif
|
||||
if( mkdir( homePath, 0777 ) )
|
||||
{
|
||||
if( errno != EEXIST )
|
||||
{
|
||||
Sys_Error( "Unable to create directory \"%s\", error is %s(%d)\n",
|
||||
homePath, strerror( errno ), errno );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return homePath;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
/* base time in seconds, that's our origin
|
||||
timeval:tv_sec is an int:
|
||||
assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038
|
||||
using unsigned long data type to work right with Sys_XTimeToSysTime */
|
||||
unsigned long sys_timeBase = 0;
|
||||
/* current time in ms, using sys_timeBase as origin
|
||||
NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
|
||||
0x7fffffff ms - ~24 days
|
||||
although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
|
||||
(which would affect the wrap period) */
|
||||
int curtime;
|
||||
int Sys_Milliseconds (void)
|
||||
{
|
||||
struct timeval tp;
|
||||
|
||||
gettimeofday(&tp, NULL);
|
||||
|
||||
if (!sys_timeBase)
|
||||
{
|
||||
sys_timeBase = tp.tv_sec;
|
||||
return tp.tv_usec/1000;
|
||||
}
|
||||
|
||||
curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
|
||||
|
||||
return curtime;
|
||||
}
|
||||
|
||||
#if !id386
|
||||
/*
|
||||
==================
|
||||
fastftol
|
||||
==================
|
||||
*/
|
||||
long fastftol( float f )
|
||||
{
|
||||
return (long)f;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_SnapVector
|
||||
==================
|
||||
*/
|
||||
void Sys_SnapVector( float *v )
|
||||
{
|
||||
v[0] = rint(v[0]);
|
||||
v[1] = rint(v[1]);
|
||||
v[2] = rint(v[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_RandomBytes
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_RandomBytes( byte *string, int len )
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen( "/dev/urandom", "r" );
|
||||
if( !fp )
|
||||
return qfalse;
|
||||
|
||||
if( !fread( string, sizeof( byte ), len, fp ) )
|
||||
{
|
||||
fclose( fp );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetCurrentUser
|
||||
==================
|
||||
*/
|
||||
char *Sys_GetCurrentUser( void )
|
||||
{
|
||||
struct passwd *p;
|
||||
|
||||
if ( (p = getpwuid( getuid() )) == NULL ) {
|
||||
return "player";
|
||||
}
|
||||
return p->pw_name;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetClipboardData
|
||||
==================
|
||||
*/
|
||||
char *Sys_GetClipboardData(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MEM_THRESHOLD 96*1024*1024
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_LowPhysicalMemory
|
||||
|
||||
TODO
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_LowPhysicalMemory( void )
|
||||
{
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_Basename
|
||||
==================
|
||||
*/
|
||||
const char *Sys_Basename( char *path )
|
||||
{
|
||||
return basename( path );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_Dirname
|
||||
==================
|
||||
*/
|
||||
const char *Sys_Dirname( char *path )
|
||||
{
|
||||
return dirname( path );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_Mkdir
|
||||
==================
|
||||
*/
|
||||
void Sys_Mkdir( const char *path )
|
||||
{
|
||||
mkdir( path, 0777 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_Cwd
|
||||
==================
|
||||
*/
|
||||
char *Sys_Cwd( void )
|
||||
{
|
||||
static char cwd[MAX_OSPATH];
|
||||
|
||||
getcwd( cwd, sizeof( cwd ) - 1 );
|
||||
cwd[MAX_OSPATH-1] = 0;
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
DIRECTORY SCANNING
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
|
||||
#define MAX_FOUND_FILES 0x1000
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_ListFilteredFiles
|
||||
==================
|
||||
*/
|
||||
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles )
|
||||
{
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
DIR *fdir;
|
||||
struct dirent *d;
|
||||
struct stat st;
|
||||
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
|
||||
}
|
||||
else {
|
||||
Com_sprintf( search, sizeof(search), "%s", basedir );
|
||||
}
|
||||
|
||||
if ((fdir = opendir(search)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
|
||||
if (stat(filename, &st) == -1)
|
||||
continue;
|
||||
|
||||
if (st.st_mode & S_IFDIR) {
|
||||
if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
|
||||
}
|
||||
else {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
|
||||
}
|
||||
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
|
||||
}
|
||||
}
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
|
||||
if (!Com_FilterPath( filter, filename, qfalse ))
|
||||
continue;
|
||||
list[ *numfiles ] = CopyString( filename );
|
||||
(*numfiles)++;
|
||||
}
|
||||
|
||||
closedir(fdir);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_ListFiles
|
||||
==================
|
||||
*/
|
||||
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *fdir;
|
||||
qboolean dironly = wantsubs;
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES];
|
||||
int i;
|
||||
struct stat st;
|
||||
|
||||
int extLen;
|
||||
|
||||
if (filter) {
|
||||
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
|
||||
|
||||
list[ nfiles ] = NULL;
|
||||
*numfiles = nfiles;
|
||||
|
||||
if (!nfiles)
|
||||
return NULL;
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
if ( !extension)
|
||||
extension = "";
|
||||
|
||||
if ( extension[0] == '/' && extension[1] == 0 ) {
|
||||
extension = "";
|
||||
dironly = qtrue;
|
||||
}
|
||||
|
||||
extLen = strlen( extension );
|
||||
|
||||
// search
|
||||
nfiles = 0;
|
||||
|
||||
if ((fdir = opendir(directory)) == NULL) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
|
||||
if (stat(search, &st) == -1)
|
||||
continue;
|
||||
if ((dironly && !(st.st_mode & S_IFDIR)) ||
|
||||
(!dironly && (st.st_mode & S_IFDIR)))
|
||||
continue;
|
||||
|
||||
if (*extension) {
|
||||
if ( strlen( d->d_name ) < strlen( extension ) ||
|
||||
Q_stricmp(
|
||||
d->d_name + strlen( d->d_name ) - strlen( extension ),
|
||||
extension ) ) {
|
||||
continue; // didn't match
|
||||
}
|
||||
}
|
||||
|
||||
if ( nfiles == MAX_FOUND_FILES - 1 )
|
||||
break;
|
||||
list[ nfiles ] = CopyString( d->d_name );
|
||||
nfiles++;
|
||||
}
|
||||
|
||||
list[ nfiles ] = NULL;
|
||||
|
||||
closedir(fdir);
|
||||
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
|
||||
if ( !nfiles ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_FreeFileList
|
||||
==================
|
||||
*/
|
||||
void Sys_FreeFileList( char **list )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !list ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0 ; list[i] ; i++ ) {
|
||||
Z_Free( list[i] );
|
||||
}
|
||||
|
||||
Z_Free( list );
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
=================
|
||||
Sys_StripAppBundle
|
||||
|
||||
Discovers if passed dir is suffixed with the directory structure of a Mac OS X
|
||||
.app bundle. If it is, the .app directory structure is stripped off the end and
|
||||
the result is returned. If not, dir is returned untouched.
|
||||
=================
|
||||
*/
|
||||
char *Sys_StripAppBundle( char *dir )
|
||||
{
|
||||
static char cwd[MAX_OSPATH];
|
||||
|
||||
Q_strncpyz(cwd, dir, sizeof(cwd));
|
||||
if(strcmp(Sys_Basename(cwd), "MacOS"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
if(strcmp(Sys_Basename(cwd), "Contents"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
if(!strstr(Sys_Basename(cwd), ".app"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
return cwd;
|
||||
}
|
||||
#endif // MACOS_X
|
510
code/sys/sys_win32.c
Normal file
510
code/sys/sys_win32.c
Normal file
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "sys_local.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <lmerr.h>
|
||||
#include <lmcons.h>
|
||||
#include <lmwksta.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#include <wincrypt.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
// Used to determine where to store user-specific files
|
||||
static char homePath[ MAX_OSPATH ] = { 0 };
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_DefaultHomePath
|
||||
================
|
||||
*/
|
||||
char *Sys_DefaultHomePath( void )
|
||||
{
|
||||
TCHAR szPath[MAX_PATH];
|
||||
FARPROC qSHGetFolderPath;
|
||||
HMODULE shfolder = LoadLibrary("shfolder.dll");
|
||||
|
||||
if( !*homePath )
|
||||
{
|
||||
if(shfolder == NULL)
|
||||
{
|
||||
Com_Printf("Unable to load SHFolder.dll\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qSHGetFolderPath = GetProcAddress(shfolder, "SHGetFolderPathA");
|
||||
if(qSHGetFolderPath == NULL)
|
||||
{
|
||||
Com_Printf("Unable to find SHGetFolderPath in SHFolder.dll\n");
|
||||
FreeLibrary(shfolder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !SUCCEEDED( qSHGetFolderPath( NULL, CSIDL_APPDATA,
|
||||
NULL, 0, szPath ) ) )
|
||||
{
|
||||
Com_Printf("Unable to detect CSIDL_APPDATA\n");
|
||||
FreeLibrary(shfolder);
|
||||
return NULL;
|
||||
}
|
||||
Q_strncpyz( homePath, szPath, sizeof( homePath ) );
|
||||
Q_strcat( homePath, sizeof( homePath ), "\\Quake3" );
|
||||
FreeLibrary(shfolder);
|
||||
if( !CreateDirectory( homePath, NULL ) )
|
||||
{
|
||||
if( GetLastError() != ERROR_ALREADY_EXISTS )
|
||||
{
|
||||
Com_Printf("Unable to create directory \"%s\"\n", homePath );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return homePath;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
int sys_timeBase;
|
||||
int Sys_Milliseconds (void)
|
||||
{
|
||||
int sys_curtime;
|
||||
static qboolean initialized = qfalse;
|
||||
|
||||
if (!initialized) {
|
||||
sys_timeBase = timeGetTime();
|
||||
initialized = qtrue;
|
||||
}
|
||||
sys_curtime = timeGetTime() - sys_timeBase;
|
||||
|
||||
return sys_curtime;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__ //see snapvectora.s
|
||||
/*
|
||||
================
|
||||
Sys_SnapVector
|
||||
================
|
||||
*/
|
||||
void Sys_SnapVector( float *v )
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
v++;
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
v++;
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_RandomBytes
|
||||
================
|
||||
*/
|
||||
qboolean Sys_RandomBytes( byte *string, int len )
|
||||
{
|
||||
HCRYPTPROV prov;
|
||||
|
||||
if( !CryptAcquireContext( &prov, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) ) {
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if( !CryptGenRandom( prov, len, (BYTE *)string ) ) {
|
||||
CryptReleaseContext( prov, 0 );
|
||||
return qfalse;
|
||||
}
|
||||
CryptReleaseContext( prov, 0 );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetCurrentUser
|
||||
================
|
||||
*/
|
||||
char *Sys_GetCurrentUser( void )
|
||||
{
|
||||
static char s_userName[1024];
|
||||
unsigned long size = sizeof( s_userName );
|
||||
|
||||
if( !GetUserName( s_userName, &size ) )
|
||||
strcpy( s_userName, "player" );
|
||||
|
||||
if( !s_userName[0] )
|
||||
{
|
||||
strcpy( s_userName, "player" );
|
||||
}
|
||||
|
||||
return s_userName;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetClipboardData
|
||||
================
|
||||
*/
|
||||
char *Sys_GetClipboardData( void )
|
||||
{
|
||||
char *data = NULL;
|
||||
char *cliptext;
|
||||
|
||||
if ( OpenClipboard( NULL ) != 0 ) {
|
||||
HANDLE hClipboardData;
|
||||
|
||||
if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 ) {
|
||||
if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) {
|
||||
data = Z_Malloc( GlobalSize( hClipboardData ) + 1 );
|
||||
Q_strncpyz( data, cliptext, GlobalSize( hClipboardData ) );
|
||||
GlobalUnlock( hClipboardData );
|
||||
|
||||
strtok( data, "\n\r\b" );
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
#define MEM_THRESHOLD 96*1024*1024
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_LowPhysicalMemory
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_LowPhysicalMemory( void )
|
||||
{
|
||||
MEMORYSTATUS stat;
|
||||
GlobalMemoryStatus (&stat);
|
||||
return (stat.dwTotalPhys <= MEM_THRESHOLD) ? qtrue : qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_Basename
|
||||
==============
|
||||
*/
|
||||
const char *Sys_Basename( char *path )
|
||||
{
|
||||
static char base[ MAX_OSPATH ] = { 0 };
|
||||
int length;
|
||||
|
||||
length = strlen( path ) - 1;
|
||||
|
||||
// Skip trailing slashes
|
||||
while( length > 0 && path[ length ] == '\\' )
|
||||
length--;
|
||||
|
||||
while( length > 0 && path[ length - 1 ] != '\\' )
|
||||
length--;
|
||||
|
||||
Q_strncpyz( base, &path[ length ], sizeof( base ) );
|
||||
|
||||
length = strlen( base ) - 1;
|
||||
|
||||
// Strip trailing slashes
|
||||
while( length > 0 && base[ length ] == '\\' )
|
||||
base[ length-- ] = '\0';
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_Dirname
|
||||
==============
|
||||
*/
|
||||
const char *Sys_Dirname( char *path )
|
||||
{
|
||||
static char dir[ MAX_OSPATH ] = { 0 };
|
||||
int length;
|
||||
|
||||
Q_strncpyz( dir, path, sizeof( dir ) );
|
||||
length = strlen( dir ) - 1;
|
||||
|
||||
while( length > 0 && dir[ length ] != '\\' )
|
||||
length--;
|
||||
|
||||
dir[ length ] = '\0';
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_Mkdir
|
||||
==============
|
||||
*/
|
||||
void Sys_Mkdir( const char *path )
|
||||
{
|
||||
_mkdir (path);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_Cwd
|
||||
==============
|
||||
*/
|
||||
char *Sys_Cwd( void ) {
|
||||
static char cwd[MAX_OSPATH];
|
||||
|
||||
_getcwd( cwd, sizeof( cwd ) - 1 );
|
||||
cwd[MAX_OSPATH-1] = 0;
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
DIRECTORY SCANNING
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
|
||||
#define MAX_FOUND_FILES 0x1000
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_ListFilteredFiles
|
||||
==============
|
||||
*/
|
||||
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles )
|
||||
{
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
int findhandle;
|
||||
struct _finddata_t findinfo;
|
||||
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( search, sizeof(search), "%s\\%s\\*", basedir, subdirs );
|
||||
}
|
||||
else {
|
||||
Com_sprintf( search, sizeof(search), "%s\\*", basedir );
|
||||
}
|
||||
|
||||
findhandle = _findfirst (search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (findinfo.attrib & _A_SUBDIR) {
|
||||
if (Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..")) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s\\%s", subdirs, findinfo.name);
|
||||
}
|
||||
else {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", findinfo.name);
|
||||
}
|
||||
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
|
||||
}
|
||||
}
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
Com_sprintf( filename, sizeof(filename), "%s\\%s", subdirs, findinfo.name );
|
||||
if (!Com_FilterPath( filter, filename, qfalse ))
|
||||
continue;
|
||||
list[ *numfiles ] = CopyString( filename );
|
||||
(*numfiles)++;
|
||||
} while ( _findnext (findhandle, &findinfo) != -1 );
|
||||
|
||||
_findclose (findhandle);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
strgtr
|
||||
==============
|
||||
*/
|
||||
static qboolean strgtr(const char *s0, const char *s1)
|
||||
{
|
||||
int l0, l1, i;
|
||||
|
||||
l0 = strlen(s0);
|
||||
l1 = strlen(s1);
|
||||
|
||||
if (l1<l0) {
|
||||
l0 = l1;
|
||||
}
|
||||
|
||||
for(i=0;i<l0;i++) {
|
||||
if (s1[i] > s0[i]) {
|
||||
return qtrue;
|
||||
}
|
||||
if (s1[i] < s0[i]) {
|
||||
return qfalse;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_ListFiles
|
||||
==============
|
||||
*/
|
||||
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
|
||||
{
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES];
|
||||
struct _finddata_t findinfo;
|
||||
int findhandle;
|
||||
int flag;
|
||||
int i;
|
||||
|
||||
if (filter) {
|
||||
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
|
||||
|
||||
list[ nfiles ] = 0;
|
||||
*numfiles = nfiles;
|
||||
|
||||
if (!nfiles)
|
||||
return NULL;
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
if ( !extension) {
|
||||
extension = "";
|
||||
}
|
||||
|
||||
// passing a slash as extension will find directories
|
||||
if ( extension[0] == '/' && extension[1] == 0 ) {
|
||||
extension = "";
|
||||
flag = 0;
|
||||
} else {
|
||||
flag = _A_SUBDIR;
|
||||
}
|
||||
|
||||
Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension );
|
||||
|
||||
// search
|
||||
nfiles = 0;
|
||||
|
||||
findhandle = _findfirst (search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) {
|
||||
if ( nfiles == MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
list[ nfiles ] = CopyString( findinfo.name );
|
||||
nfiles++;
|
||||
}
|
||||
} while ( _findnext (findhandle, &findinfo) != -1 );
|
||||
|
||||
list[ nfiles ] = 0;
|
||||
|
||||
_findclose (findhandle);
|
||||
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
|
||||
if ( !nfiles ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
do {
|
||||
flag = 0;
|
||||
for(i=1; i<nfiles; i++) {
|
||||
if (strgtr(listCopy[i-1], listCopy[i])) {
|
||||
char *temp = listCopy[i];
|
||||
listCopy[i] = listCopy[i-1];
|
||||
listCopy[i-1] = temp;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
} while(flag);
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_FreeFileList
|
||||
==============
|
||||
*/
|
||||
void Sys_FreeFileList( char **list )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !list ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0 ; list[i] ; i++ ) {
|
||||
Z_Free( list[i] );
|
||||
}
|
||||
|
||||
Z_Free( list );
|
||||
}
|
440
code/sys/tty_console.c
Normal file
440
code/sys/tty_console.c
Normal file
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
tty console routines
|
||||
|
||||
NOTE: if the user is editing a line when something gets printed to the early
|
||||
console then it won't look good so we provide TTY_Hide and TTY_Show to be
|
||||
called before and after a stdout or stderr output
|
||||
=============================================================
|
||||
*/
|
||||
|
||||
// general flag to tell about tty console mode
|
||||
static qboolean ttycon_on = qfalse;
|
||||
static int ttycon_hide = 0;
|
||||
|
||||
// some key codes that the terminal may be using, initialised on start up
|
||||
static int TTY_erase;
|
||||
static int TTY_eof;
|
||||
|
||||
static struct termios TTY_tc;
|
||||
|
||||
static field_t TTY_con;
|
||||
|
||||
// This is somewhat of aduplicate of the graphical console history
|
||||
// but it's safer more modular to have our own here
|
||||
#define TTY_HISTORY 32
|
||||
static field_t ttyEditLines[ TTY_HISTORY ];
|
||||
static int hist_current = -1, hist_count = 0;
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_FlushIn
|
||||
|
||||
Flush stdin, I suspect some terminals are sending a LOT of shit
|
||||
FIXME relevant?
|
||||
==================
|
||||
*/
|
||||
static void TTY_FlushIn( void )
|
||||
{
|
||||
char key;
|
||||
while (read(0, &key, 1)!=-1);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_Back
|
||||
|
||||
Output a backspace
|
||||
|
||||
NOTE: it seems on some terminals just sending '\b' is not enough so instead we
|
||||
send "\b \b"
|
||||
(FIXME there may be a way to find out if '\b' alone would work though)
|
||||
==================
|
||||
*/
|
||||
static void TTY_Back( void )
|
||||
{
|
||||
char key;
|
||||
key = '\b';
|
||||
write(1, &key, 1);
|
||||
key = ' ';
|
||||
write(1, &key, 1);
|
||||
key = '\b';
|
||||
write(1, &key, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_Hide
|
||||
|
||||
Clear the display of the line currently edited
|
||||
bring cursor back to beginning of line
|
||||
==================
|
||||
*/
|
||||
void TTY_Hide( void )
|
||||
{
|
||||
if( ttycon_on )
|
||||
{
|
||||
int i;
|
||||
if (ttycon_hide)
|
||||
{
|
||||
ttycon_hide++;
|
||||
return;
|
||||
}
|
||||
if (TTY_con.cursor>0)
|
||||
{
|
||||
for (i=0; i<TTY_con.cursor; i++)
|
||||
{
|
||||
TTY_Back();
|
||||
}
|
||||
}
|
||||
TTY_Back(); // Delete "]"
|
||||
ttycon_hide++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_Show
|
||||
|
||||
Show the current line
|
||||
FIXME need to position the cursor if needed?
|
||||
==================
|
||||
*/
|
||||
void TTY_Show( void )
|
||||
{
|
||||
if( ttycon_on )
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(ttycon_hide>0);
|
||||
ttycon_hide--;
|
||||
if (ttycon_hide == 0)
|
||||
{
|
||||
write( 1, "]", 1 );
|
||||
if (TTY_con.cursor)
|
||||
{
|
||||
for (i=0; i<TTY_con.cursor; i++)
|
||||
{
|
||||
write(1, TTY_con.buffer+i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_Shutdown
|
||||
|
||||
Never exit without calling this, or your terminal will be left in a pretty bad state
|
||||
==================
|
||||
*/
|
||||
void TTY_Shutdown( void )
|
||||
{
|
||||
if (ttycon_on)
|
||||
{
|
||||
TTY_Back(); // Delete "]"
|
||||
tcsetattr (0, TCSADRAIN, &TTY_tc);
|
||||
|
||||
// Restore blocking to stdin reads
|
||||
fcntl( 0, F_SETFL, fcntl( 0, F_GETFL, 0 ) & ~O_NDELAY );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Hist_Add
|
||||
==================
|
||||
*/
|
||||
void Hist_Add(field_t *field)
|
||||
{
|
||||
int i;
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
// make some room
|
||||
for (i=TTY_HISTORY-1; i>0; i--)
|
||||
{
|
||||
ttyEditLines[i] = ttyEditLines[i-1];
|
||||
}
|
||||
ttyEditLines[0] = *field;
|
||||
if (hist_count<TTY_HISTORY)
|
||||
{
|
||||
hist_count++;
|
||||
}
|
||||
hist_current = -1; // re-init
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Hist_Prev
|
||||
==================
|
||||
*/
|
||||
field_t *Hist_Prev( void )
|
||||
{
|
||||
int hist_prev;
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
hist_prev = hist_current + 1;
|
||||
if (hist_prev >= hist_count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
hist_current++;
|
||||
return &(ttyEditLines[hist_current]);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Hist_Next
|
||||
==================
|
||||
*/
|
||||
field_t *Hist_Next( void )
|
||||
{
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
if (hist_current >= 0)
|
||||
{
|
||||
hist_current--;
|
||||
}
|
||||
if (hist_current == -1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &(ttyEditLines[hist_current]);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_Init
|
||||
|
||||
Initialize the console input (tty mode if possible)
|
||||
==================
|
||||
*/
|
||||
void TTY_Init( void )
|
||||
{
|
||||
struct termios tc;
|
||||
|
||||
// If the process is backgrounded (running non interactively)
|
||||
// then SIGTTIN or SIGTOU is emitted, if not caught, turns into a SIGSTP
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
|
||||
// Make stdin reads non-blocking
|
||||
fcntl( 0, F_SETFL, fcntl( 0, F_GETFL, 0 ) | O_NDELAY );
|
||||
|
||||
if (isatty(STDIN_FILENO)!=1)
|
||||
{
|
||||
Com_Printf( "stdin is not a tty, tty console mode disabled\n");
|
||||
ttycon_on = qfalse;
|
||||
return;
|
||||
}
|
||||
|
||||
Field_Clear(&TTY_con);
|
||||
tcgetattr (0, &TTY_tc);
|
||||
TTY_erase = TTY_tc.c_cc[VERASE];
|
||||
TTY_eof = TTY_tc.c_cc[VEOF];
|
||||
tc = TTY_tc;
|
||||
|
||||
/*
|
||||
ECHO: don't echo input characters
|
||||
ICANON: enable canonical mode. This enables the special
|
||||
characters EOF, EOL, EOL2, ERASE, KILL, REPRINT,
|
||||
STATUS, and WERASE, and buffers by lines.
|
||||
ISIG: when any of the characters INTR, QUIT, SUSP, or
|
||||
DSUSP are received, generate the corresponding sig
|
||||
nal
|
||||
*/
|
||||
tc.c_lflag &= ~(ECHO | ICANON);
|
||||
|
||||
/*
|
||||
ISTRIP strip off bit 8
|
||||
INPCK enable input parity checking
|
||||
*/
|
||||
tc.c_iflag &= ~(ISTRIP | INPCK);
|
||||
tc.c_cc[VMIN] = 1;
|
||||
tc.c_cc[VTIME] = 0;
|
||||
tcsetattr (0, TCSADRAIN, &tc);
|
||||
ttycon_on = qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
TTY_ConsoleInput
|
||||
==================
|
||||
*/
|
||||
char *TTY_ConsoleInput( void )
|
||||
{
|
||||
// we use this when sending back commands
|
||||
static char text[256];
|
||||
int avail;
|
||||
char key;
|
||||
field_t *history;
|
||||
|
||||
if( ttycon_on )
|
||||
{
|
||||
avail = read(0, &key, 1);
|
||||
if (avail != -1)
|
||||
{
|
||||
// we have something
|
||||
// backspace?
|
||||
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
|
||||
if ((key == TTY_erase) || (key == 127) || (key == 8))
|
||||
{
|
||||
if (TTY_con.cursor > 0)
|
||||
{
|
||||
TTY_con.cursor--;
|
||||
TTY_con.buffer[TTY_con.cursor] = '\0';
|
||||
TTY_Back();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
// check if this is a control char
|
||||
if ((key) && (key) < ' ')
|
||||
{
|
||||
if (key == '\n')
|
||||
{
|
||||
// push it in history
|
||||
Hist_Add(&TTY_con);
|
||||
strcpy(text, TTY_con.buffer);
|
||||
Field_Clear(&TTY_con);
|
||||
key = '\n';
|
||||
write(1, &key, 1);
|
||||
write( 1, "]", 1 );
|
||||
return text;
|
||||
}
|
||||
if (key == '\t')
|
||||
{
|
||||
TTY_Hide();
|
||||
Field_AutoComplete( &TTY_con );
|
||||
TTY_Show();
|
||||
return NULL;
|
||||
}
|
||||
avail = read(0, &key, 1);
|
||||
if (avail != -1)
|
||||
{
|
||||
// VT 100 keys
|
||||
if (key == '[' || key == 'O')
|
||||
{
|
||||
avail = read(0, &key, 1);
|
||||
if (avail != -1)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 'A':
|
||||
history = Hist_Prev();
|
||||
if (history)
|
||||
{
|
||||
TTY_Hide();
|
||||
TTY_con = *history;
|
||||
TTY_Show();
|
||||
}
|
||||
TTY_FlushIn();
|
||||
return NULL;
|
||||
break;
|
||||
case 'B':
|
||||
history = Hist_Next();
|
||||
TTY_Hide();
|
||||
if (history)
|
||||
{
|
||||
TTY_con = *history;
|
||||
} else
|
||||
{
|
||||
Field_Clear(&TTY_con);
|
||||
}
|
||||
TTY_Show();
|
||||
TTY_FlushIn();
|
||||
return NULL;
|
||||
break;
|
||||
case 'C':
|
||||
return NULL;
|
||||
case 'D':
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase);
|
||||
TTY_FlushIn();
|
||||
return NULL;
|
||||
}
|
||||
// push regular character
|
||||
TTY_con.buffer[TTY_con.cursor] = key;
|
||||
TTY_con.cursor++;
|
||||
// print the current line (this is differential)
|
||||
write(1, &key, 1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
fd_set fdset;
|
||||
struct timeval timeout;
|
||||
static qboolean stdin_active;
|
||||
|
||||
if (!com_dedicated || !com_dedicated->value)
|
||||
return NULL;
|
||||
|
||||
if (!stdin_active)
|
||||
return NULL;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(0, &fdset); // stdin
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = read (0, text, sizeof(text));
|
||||
if (len == 0)
|
||||
{ // eof!
|
||||
stdin_active = qfalse;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
text[len-1] = 0; // rip off the /n and terminate
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
44
code/sys/win_resource.h
Normal file
44
code/sys/win_resource.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by winquake.rc
|
||||
//
|
||||
#define IDS_STRING1 1
|
||||
#define IDI_ICON1 1
|
||||
#define IDB_BITMAP1 1
|
||||
#define IDB_BITMAP2 128
|
||||
#define IDC_CURSOR1 129
|
||||
#define IDC_CURSOR2 130
|
||||
#define IDC_CURSOR3 131
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 132
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1005
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
75
code/sys/win_resource.rc
Normal file
75
code/sys/win_resource.rc
Normal file
|
@ -0,0 +1,75 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "win_resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#ifndef __MINGW32__
|
||||
#include "winres.h"
|
||||
#else
|
||||
#include <winresrc.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "misc/quake3.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_STRING1 "Quake3"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue