2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 // Nurail: Swiped from quake3/common
27 #include <sys/types.h>
35 #if defined ( __linux__ ) || defined ( __APPLE__ )
43 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
44 #define HERETIC2_BASEDIRNAME "h"
45 #define PATHSEPERATOR '/'
47 // qboolean verbose = false;
50 void *safe_malloc( size_t size ){
55 Error( "safe_malloc failed on allocation of %i bytes", size );
62 void *safe_malloc_info( size_t size, char* info ){
67 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
75 // set these before calling CheckParm
83 char archivedir[1024];
90 Mimic unix command line expansion
93 #define MAX_EX_ARGC 1024
95 char *ex_argv[MAX_EX_ARGC];
98 void ExpandWildcards( int *argc, char ***argv ){
99 struct _finddata_t fileinfo;
107 for ( i = 0 ; i < *argc ; i++ )
111 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
112 ex_argv[ex_argc++] = path;
116 handle = _findfirst( path, &fileinfo );
117 if ( handle == -1 ) {
121 ExtractFilePath( path, filebase );
125 sprintf( filename, "%s%s", filebase, fileinfo.name );
126 ex_argv[ex_argc++] = copystring( filename );
127 } while ( _findnext( handle, &fileinfo ) != -1 );
129 _findclose( handle );
136 void ExpandWildcards( int *argc, char ***argv ){
142 qdir will hold the path up to the quake directory, including the slash
147 gamedir will hold qdir + the game directory (id1, id2, etc)
155 void SetQdirFromPath( const char *path ){
160 char basedirname[256];
162 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
164 strcat( temp, path );
168 // search for "quake2" in path
170 if ( !strcmp( game, "heretic2" ) ) {
171 strncpy( basedirname, HERETIC2_BASEDIRNAME, 256 );
174 strncpy( basedirname, BASEDIRNAME, 256 );
177 len = strlen( basedirname );
178 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
182 if ( !Q_strncasecmp( c, basedirname, len ) ) {
184 //strncpy (qdir, path, c+len+2-path);
185 // the +2 assumes a 2 or 3 following quake which is not the
186 // case with a retail install
187 // so we need to add up how much to the next separator
190 while ( *sep && *sep != '/' && *sep != '\\' )
195 strncpy( qdir, path, c + len + count - path );
196 Sys_FPrintf( SYS_VRB, "qdir: %s\n", qdir );
197 for ( i = 0; i < strlen( qdir ); i++ )
199 if ( qdir[i] == '\\' ) {
207 if ( *c == '/' || *c == '\\' ) {
208 strncpy( gamedir, path, c + 1 - path );
210 for ( i = 0; i < strlen( gamedir ); i++ )
212 if ( gamedir[i] == '\\' ) {
217 Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir );
219 if ( !writedir[0] ) {
220 strcpy( writedir, gamedir );
222 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
223 writedir[strlen( writedir )] = '/';
224 writedir[strlen( writedir ) + 1] = 0;
231 Error( "No gamedir in %s", path );
235 Error( "SetQdirFromPath: no '%s' in %s", basedirname, path );
238 char *ExpandArg( const char *path ){
239 static char full[1024];
241 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
243 strcat( full, path );
246 strcpy( full, path );
251 char *ExpandPath( const char *path ){
252 static char full[1024];
254 Error( "ExpandPath called without qdir set" );
256 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
257 strcpy( full, path );
260 sprintf( full, "%s%s", qdir, path );
264 char *ExpandGamePath( const char *path ){
265 static char full[1024];
267 Error( "ExpandGamePath called without qdir set" );
269 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
270 strcpy( full, path );
273 sprintf( full, "%s%s", gamedir, path );
277 char *ExpandPathAndArchive( const char *path ){
279 char archivename[1024];
281 expanded = ExpandPath( path );
284 sprintf( archivename, "%s/%s", archivedir, path );
285 QCopyFile( expanded, archivename );
291 char *copystring( const char *s ){
293 b = safe_malloc( strlen( s ) + 1 );
305 double I_FloatTime( void ){
312 // more precise, less portable
317 gettimeofday( &tp, &tzp );
321 return tp.tv_usec / 1000000.0;
324 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
328 void Q_getwd( char *out ){
335 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
339 while ( out[i] != 0 )
341 if ( out[i] == '\\' ) {
349 void Q_mkdir( const char *path ){
351 if ( _mkdir( path ) != -1 ) {
355 if ( mkdir( path, 0777 ) != -1 ) {
359 if ( errno != EEXIST ) {
360 Error( "mkdir %s: %s",path, strerror( errno ) );
368 returns -1 if not present
371 int FileTime( const char *path ){
374 if ( stat( path,&buf ) == -1 ) {
387 Parse a token out of a string
390 char *COM_Parse( char *data ){
403 while ( ( c = *data ) <= ' ' )
407 return NULL; // end of file;
413 if ( c == '/' && data[1] == '/' ) {
414 while ( *data && *data != '\n' )
420 // handle quoted strings specially
435 // parse single characters
436 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
443 // parse a regular word
450 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
459 int Q_strncasecmp( const char *s1, const char *s2, int n ){
468 return 0; // strings are equal until end point
472 if ( c1 >= 'a' && c1 <= 'z' ) {
475 if ( c2 >= 'a' && c2 <= 'z' ) {
479 return -1; // strings not equal
484 return 0; // strings are equal
487 int Q_stricmp( const char *s1, const char *s2 ){
488 return Q_strncasecmp( s1, s2, 99999 );
491 int Q_strcasecmp( const char *s1, const char *s2 ){
492 return Q_strncasecmp( s1, s2, 99999 );
496 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
497 // started getting warnings about that function, prolly a duplicate with the runtime function
498 // maybe we still need to have it in linux builds
500 char *strupr (char *start)
513 char *strlower( char *start ){
518 *in = tolower( *in );
526 =============================================================================
530 =============================================================================
538 Checks for the given parameter in the program's command line arguments
539 Returns the argument number (1 to argc-1) or 0 if not present
542 int CheckParm( const char *check ){
545 for ( i = 1; i < myargc; i++ )
547 if ( !Q_stricmp( check, myargv[i] ) ) {
562 int Q_filelength( FILE *f ){
567 fseek( f, 0, SEEK_END );
569 fseek( f, pos, SEEK_SET );
575 FILE *SafeOpenWrite( const char *filename ){
578 f = fopen( filename, "wb" );
581 Error( "Error opening %s: %s",filename,strerror( errno ) );
587 FILE *SafeOpenRead( const char *filename ){
590 f = fopen( filename, "rb" );
593 Error( "Error opening %s: %s",filename,strerror( errno ) );
600 void SafeRead( FILE *f, void *buffer, int count ){
601 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
602 Error( "File read failure" );
607 void SafeWrite( FILE *f, const void *buffer, int count ){
608 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
609 Error( "File write failure" );
619 qboolean FileExists( const char *filename ){
622 f = fopen( filename, "r" );
635 int LoadFile( const char *filename, void **bufferptr ){
640 f = SafeOpenRead( filename );
641 length = Q_filelength( f );
642 buffer = safe_malloc( length + 1 );
643 ( (char *)buffer )[length] = 0;
644 SafeRead( f, buffer, length );
656 rounds up memory allocation to 4K boundry
660 int LoadFileBlock( const char *filename, void **bufferptr ){
662 int length, nBlock, nAllocSize;
665 f = SafeOpenRead( filename );
666 length = Q_filelength( f );
668 nBlock = nAllocSize % MEM_BLOCKSIZE;
670 nAllocSize += MEM_BLOCKSIZE - nBlock;
672 buffer = safe_malloc( nAllocSize + 1 );
673 memset( buffer, 0, nAllocSize + 1 );
674 SafeRead( f, buffer, length );
689 int TryLoadFile( const char *filename, void **bufferptr ){
696 f = fopen( filename, "rb" );
700 length = Q_filelength( f );
701 buffer = safe_malloc( length + 1 );
702 ( (char *)buffer )[length] = 0;
703 SafeRead( f, buffer, length );
716 void SaveFile( const char *filename, const void *buffer, int count ){
719 f = SafeOpenWrite( filename );
720 SafeWrite( f, buffer, count );
726 void DefaultExtension( char *path, const char *extension ){
729 // if path doesnt have a .EXT, append extension
730 // (extension should include the .)
732 src = path + strlen( path ) - 1;
734 while ( *src != '/' && *src != '\\' && src != path )
737 return; // it has an extension
742 strcat( path, extension );
746 void DefaultPath( char *path, const char *basepath ){
749 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
750 return; // absolute path location
753 strcpy( path,basepath );
758 void StripFilename( char *path ){
761 length = strlen( path ) - 1;
762 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
767 void StripExtension( char *path ){
770 length = strlen( path ) - 1;
771 while ( length > 0 && path[length] != '.' )
774 if ( path[length] == '/' || path[ length ] == '\\' ) {
775 return; // no extension
789 // FIXME: should include the slash, otherwise
790 // backing to an empty path will be wrong when appending a slash
791 void ExtractFilePath( const char *path, char *dest ){
794 src = path + strlen( path ) - 1;
797 // back up until a \ or the start
799 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
802 memcpy( dest, path, src - path );
803 dest[src - path] = 0;
806 void ExtractFileBase( const char *path, char *dest ){
809 src = path + strlen( path ) - 1;
812 // back up until a \ or the start
814 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
817 while ( *src && *src != '.' )
824 void ExtractFileExtension( const char *path, char *dest ){
827 src = path + strlen( path ) - 1;
830 // back up until a . or the start
832 while ( src != path && *( src - 1 ) != '.' )
835 *dest = 0; // no extension
848 int ParseHex( const char *hex ){
858 if ( *str >= '0' && *str <= '9' ) {
861 else if ( *str >= 'a' && *str <= 'f' ) {
862 num += 10 + *str - 'a';
864 else if ( *str >= 'A' && *str <= 'F' ) {
865 num += 10 + *str - 'A';
868 Error( "Bad hex number: %s",hex );
877 int ParseNum( const char *str ){
878 if ( str[0] == '$' ) {
879 return ParseHex( str + 1 );
881 if ( str[0] == '0' && str[1] == 'x' ) {
882 return ParseHex( str + 2 );
887 // all output ends up through here
888 void FPrintf (int flag, char *buf)
894 void Sys_FPrintf (int flag, const char *format, ...)
896 char out_buffer[4096];
899 if ((flag == SYS_VRB) && (verbose == false))
902 va_start (argptr, format);
903 vsprintf (out_buffer, format, argptr);
906 FPrintf (flag, out_buffer);
909 void Sys_Printf (const char *format, ...)
911 char out_buffer[4096];
914 va_start (argptr, format);
915 vsprintf (out_buffer, format, argptr);
918 FPrintf (SYS_STD, out_buffer);
925 //For abnormal program terminations
928 void Error( const char *error, ...)
930 char out_buffer[4096];
934 va_start (argptr,error);
935 vsprintf (tmp, error, argptr);
938 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
940 FPrintf( SYS_ERR, out_buffer );
948 ============================================================================
952 ============================================================================
956 #define __BIG_ENDIAN__
959 #ifdef __BIG_ENDIAN__
961 short LittleShort( short l ){
965 b2 = ( l >> 8 ) & 255;
967 return ( b1 << 8 ) + b2;
970 short BigShort( short l ){
975 int LittleLong( int l ){
979 b2 = ( l >> 8 ) & 255;
980 b3 = ( l >> 16 ) & 255;
981 b4 = ( l >> 24 ) & 255;
983 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
986 int BigLong( int l ){
991 float LittleFloat( float l ){
992 union {byte b[4]; float f; } in, out;
1003 float BigFloat( float l ){
1011 short BigShort( short l ){
1015 b2 = ( l >> 8 ) & 255;
1017 return ( b1 << 8 ) + b2;
1020 short LittleShort( short l ){
1025 int BigLong( int l ){
1029 b2 = ( l >> 8 ) & 255;
1030 b3 = ( l >> 16 ) & 255;
1031 b4 = ( l >> 24 ) & 255;
1033 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1036 int LittleLong( int l ){
1040 float BigFloat( float l ){
1041 union {byte b[4]; float f; } in, out;
1052 float LittleFloat( float l ){
1060 //=======================================================
1063 // FIXME: byte swap?
1065 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1066 // and the initial and final xor values shown below... in other words, the
1067 // CCITT standard CRC used by XMODEM
1069 #define CRC_INIT_VALUE 0xffff
1070 #define CRC_XOR_VALUE 0x0000
1072 static unsigned short crctable[256] =
1074 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1075 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1076 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1077 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1078 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1079 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1080 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1081 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1082 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1083 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1084 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1085 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1086 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1087 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1088 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1089 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1090 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1091 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1092 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1093 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1094 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1095 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1096 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1097 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1098 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1099 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1100 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1101 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1102 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1103 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1104 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1105 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1108 void CRC_Init( unsigned short *crcvalue ){
1109 *crcvalue = CRC_INIT_VALUE;
1112 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1113 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1116 unsigned short CRC_Value( unsigned short crcvalue ){
1117 return crcvalue ^ CRC_XOR_VALUE;
1119 //=============================================================================
1126 void CreatePath( const char *path ){
1134 if ( path[1] == ':' ) {
1135 olddrive = _getdrive();
1136 _chdrive( toupper( path[0] ) - 'A' + 1 );
1140 if ( path[1] == ':' ) {
1144 for ( ofs = path + 1 ; *ofs ; ofs++ )
1147 if ( c == '/' || c == '\\' ) { // create the directory
1148 memcpy( dir, path, ofs - path );
1149 dir[ ofs - path ] = 0;
1155 if ( olddrive != -1 ) {
1156 _chdrive( olddrive );
1166 Used to archive source files
1169 void QCopyFile( const char *from, const char *to ){
1173 length = LoadFile( from, &buffer );
1175 SaveFile( to, buffer, length );
1179 void Sys_Sleep( int n ){
1183 #if defined ( __linux__ ) || defined ( __APPLE__ )