2 Copyright (C) 1999-2007 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 )
56 Error ("safe_malloc failed on allocation of %i bytes", size);
62 void *safe_malloc_info( size_t size, char* info )
68 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 )
100 struct _finddata_t fileinfo;
108 for (i=0 ; i<*argc ; i++)
112 || ( !strstr(path, "*") && !strstr(path, "?") ) )
114 ex_argv[ex_argc++] = path;
118 handle = _findfirst (path, &fileinfo);
122 ExtractFilePath (path, filebase);
126 sprintf (filename, "%s%s", filebase, fileinfo.name);
127 ex_argv[ex_argc++] = copystring (filename);
128 } while (_findnext( handle, &fileinfo ) != -1);
137 void ExpandWildcards (int *argc, char ***argv)
144 qdir will hold the path up to the quake directory, including the slash
149 gamedir will hold qdir + the game directory (id1, id2, etc)
157 void SetQdirFromPath( const char *path )
163 char basedirname[256];
165 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
172 // search for "quake2" in path
174 if ( !strcmp( game, "heretic2" ) )
175 strncpy(basedirname, HERETIC2_BASEDIRNAME, 256);
177 strncpy(basedirname, BASEDIRNAME, 256);
179 len = strlen(basedirname);
180 for (c=path+strlen(path)-1 ; c != path ; c--)
184 if (!Q_strncasecmp (c, basedirname, len))
187 //strncpy (qdir, path, c+len+2-path);
188 // the +2 assumes a 2 or 3 following quake which is not the
189 // case with a retail install
190 // so we need to add up how much to the next separator
193 while (*sep && *sep != '/' && *sep != '\\')
198 strncpy (qdir, path, c+len+count-path);
199 Sys_FPrintf( SYS_VRB, "qdir: %s\n", qdir);
200 for ( i = 0; i < strlen( qdir ); i++ )
202 if ( qdir[i] == '\\' )
209 if (*c == '/' || *c == '\\')
211 strncpy (gamedir, path, c+1-path);
213 for ( i = 0; i < strlen( gamedir ); i++ )
215 if ( gamedir[i] == '\\' )
219 Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir);
222 strcpy( writedir, gamedir );
223 else if ( writedir[strlen( writedir )-1] != '/' )
225 writedir[strlen( writedir )] = '/';
226 writedir[strlen( writedir )+1] = 0;
233 Error ("No gamedir in %s", path);
237 Error ("SetQdirFromPath: no '%s' in %s", basedirname, path);
240 char *ExpandArg (const char *path)
242 static char full[1024];
244 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
254 char *ExpandPath (const char *path)
256 static char full[1024];
258 Error ("ExpandPath called without qdir set");
259 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
260 strcpy( full, path );
263 sprintf (full, "%s%s", qdir, path);
267 char *ExpandGamePath (const char *path)
269 static char full[1024];
271 Error ("ExpandGamePath called without qdir set");
272 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
273 strcpy( full, path );
276 sprintf (full, "%s%s", gamedir, path);
280 char *ExpandPathAndArchive (const char *path)
283 char archivename[1024];
285 expanded = ExpandPath (path);
289 sprintf (archivename, "%s/%s", archivedir, path);
290 QCopyFile (expanded, archivename);
296 char *copystring(const char *s)
299 b = safe_malloc(strlen(s)+1);
311 double I_FloatTime (void)
319 // more precise, less portable
324 gettimeofday(&tp, &tzp);
329 return tp.tv_usec/1000000.0;
332 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
336 void Q_getwd (char *out)
344 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
348 while ( out[i] != 0 )
350 if ( out[i] == '\\' )
357 void Q_mkdir (const char *path)
360 if (_mkdir (path) != -1)
363 if (mkdir (path, 0777) != -1)
367 Error ("mkdir %s: %s",path, strerror(errno));
374 returns -1 if not present
377 int FileTime (const char *path)
381 if (stat (path,&buf) == -1)
393 Parse a token out of a string
396 char *COM_Parse (char *data)
409 while ( (c = *data) <= ' ')
414 return NULL; // end of file;
420 if (c=='/' && data[1] == '/')
422 while (*data && *data != '\n')
428 // handle quoted strings specially
445 // parse single characters
446 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
454 // parse a regular word
461 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
469 int Q_strncasecmp (const char *s1, const char *s2, int n)
479 return 0; // strings are equal until end point
483 if (c1 >= 'a' && c1 <= 'z')
485 if (c2 >= 'a' && c2 <= 'z')
488 return -1; // strings not equal
492 return 0; // strings are equal
495 int Q_stricmp (const char *s1, const char *s2)
497 return Q_strncasecmp (s1, s2, 99999);
500 int Q_strcasecmp (const char *s1, const char *s2)
502 return Q_strncasecmp (s1, s2, 99999);
506 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
507 // started getting warnings about that function, prolly a duplicate with the runtime function
508 // maybe we still need to have it in linux builds
510 char *strupr (char *start)
523 char *strlower (char *start)
537 =============================================================================
541 =============================================================================
549 Checks for the given parameter in the program's command line arguments
550 Returns the argument number (1 to argc-1) or 0 if not present
553 int CheckParm (const char *check)
557 for (i = 1;i<myargc;i++)
559 if ( !Q_stricmp(check, myargv[i]) )
573 int Q_filelength (FILE *f)
579 fseek (f, 0, SEEK_END);
581 fseek (f, pos, SEEK_SET);
587 FILE *SafeOpenWrite (const char *filename)
591 f = fopen(filename, "wb");
594 Error ("Error opening %s: %s",filename,strerror(errno));
599 FILE *SafeOpenRead (const char *filename)
603 f = fopen(filename, "rb");
606 Error ("Error opening %s: %s",filename,strerror(errno));
612 void SafeRead (FILE *f, void *buffer, int count)
614 if ( fread (buffer, 1, count, f) != (size_t)count)
615 Error ("File read failure");
619 void SafeWrite (FILE *f, const void *buffer, int count)
621 if (fwrite (buffer, 1, count, f) != (size_t)count)
622 Error ("File write failure");
631 qboolean FileExists (const char *filename)
635 f = fopen (filename, "r");
647 int LoadFile( const char *filename, void **bufferptr )
653 f = SafeOpenRead (filename);
654 length = Q_filelength (f);
655 buffer = safe_malloc (length+1);
656 ((char *)buffer)[length] = 0;
657 SafeRead (f, buffer, length);
669 rounds up memory allocation to 4K boundry
673 int LoadFileBlock( const char *filename, void **bufferptr )
676 int length, nBlock, nAllocSize;
679 f = SafeOpenRead (filename);
680 length = Q_filelength (f);
682 nBlock = nAllocSize % MEM_BLOCKSIZE;
684 nAllocSize += MEM_BLOCKSIZE - nBlock;
686 buffer = safe_malloc (nAllocSize+1);
687 memset(buffer, 0, nAllocSize+1);
688 SafeRead (f, buffer, length);
703 int TryLoadFile (const char *filename, void **bufferptr)
711 f = fopen (filename, "rb");
714 length = Q_filelength (f);
715 buffer = safe_malloc (length+1);
716 ((char *)buffer)[length] = 0;
717 SafeRead (f, buffer, length);
730 void SaveFile (const char *filename, const void *buffer, int count)
734 f = SafeOpenWrite (filename);
735 SafeWrite (f, buffer, count);
741 void DefaultExtension (char *path, const char *extension)
745 // if path doesnt have a .EXT, append extension
746 // (extension should include the .)
748 src = path + strlen(path) - 1;
750 while (*src != '/' && *src != '\\' && src != path)
753 return; // it has an extension
757 strcat (path, extension);
761 void DefaultPath (char *path, const char *basepath)
765 if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
766 return; // absolute path location
768 strcpy (path,basepath);
773 void StripFilename (char *path)
777 length = strlen(path)-1;
778 while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
783 void StripExtension (char *path)
787 length = strlen(path)-1;
788 while (length > 0 && path[length] != '.')
791 if (path[length] == '/' || path[ length ] == '\\' )
792 return; // no extension
804 // FIXME: should include the slash, otherwise
805 // backing to an empty path will be wrong when appending a slash
806 void ExtractFilePath (const char *path, char *dest)
810 src = path + strlen(path) - 1;
813 // back up until a \ or the start
815 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
818 memcpy (dest, path, src-path);
822 void ExtractFileBase (const char *path, char *dest)
826 src = path + strlen(path) - 1;
829 // back up until a \ or the start
831 while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
834 while (*src && *src != '.')
841 void ExtractFileExtension (const char *path, char *dest)
845 src = path + strlen(path) - 1;
848 // back up until a . or the start
850 while (src != path && *(src-1) != '.')
854 *dest = 0; // no extension
867 int ParseHex (const char *hex)
878 if (*str >= '0' && *str <= '9')
880 else if (*str >= 'a' && *str <= 'f')
881 num += 10 + *str-'a';
882 else if (*str >= 'A' && *str <= 'F')
883 num += 10 + *str-'A';
885 Error ("Bad hex number: %s",hex);
893 int ParseNum (const char *str)
896 return ParseHex (str+1);
897 if (str[0] == '0' && str[1] == 'x')
898 return ParseHex (str+2);
902 // all output ends up through here
903 void FPrintf (int flag, char *buf)
909 void Sys_FPrintf (int flag, const char *format, ...)
911 char out_buffer[4096];
914 if ((flag == SYS_VRB) && (verbose == false))
917 va_start (argptr, format);
918 vsprintf (out_buffer, format, argptr);
921 FPrintf (flag, out_buffer);
924 void Sys_Printf (const char *format, ...)
926 char out_buffer[4096];
929 va_start (argptr, format);
930 vsprintf (out_buffer, format, argptr);
933 FPrintf (SYS_STD, out_buffer);
940 //For abnormal program terminations
943 void Error( const char *error, ...)
945 char out_buffer[4096];
949 va_start (argptr,error);
950 vsprintf (tmp, error, argptr);
953 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
955 FPrintf( SYS_ERR, out_buffer );
963 ============================================================================
967 ============================================================================
971 #define __BIG_ENDIAN__
974 #ifdef __BIG_ENDIAN__
976 short LittleShort (short l)
986 short BigShort (short l)
992 int LittleLong (int l)
1001 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1010 float LittleFloat (float l)
1012 union {byte b[4]; float f;} in, out;
1023 float BigFloat (float l)
1032 short BigShort (short l)
1039 return (b1<<8) + b2;
1042 short LittleShort (short l)
1057 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1060 int LittleLong (int l)
1065 float BigFloat (float l)
1067 union {byte b[4]; float f;} in, out;
1078 float LittleFloat (float l)
1087 //=======================================================
1090 // FIXME: byte swap?
1092 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1093 // and the initial and final xor values shown below... in other words, the
1094 // CCITT standard CRC used by XMODEM
1096 #define CRC_INIT_VALUE 0xffff
1097 #define CRC_XOR_VALUE 0x0000
1099 static unsigned short crctable[256] =
1101 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1102 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1103 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1104 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1105 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1106 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1107 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1108 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1109 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1110 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1111 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1112 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1113 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1114 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1115 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1116 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1117 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1118 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1119 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1120 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1121 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1122 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1123 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1124 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1125 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1126 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1127 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1128 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1129 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1130 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1131 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1132 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1135 void CRC_Init(unsigned short *crcvalue)
1137 *crcvalue = CRC_INIT_VALUE;
1140 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1142 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1145 unsigned short CRC_Value(unsigned short crcvalue)
1147 return crcvalue ^ CRC_XOR_VALUE;
1149 //=============================================================================
1156 void CreatePath (const char *path)
1165 if ( path[1] == ':' )
1167 olddrive = _getdrive();
1168 _chdrive( toupper( path[0] ) - 'A' + 1 );
1175 for (ofs = path+1 ; *ofs ; ofs++)
1178 if (c == '/' || c == '\\')
1179 { // create the directory
1180 memcpy( dir, path, ofs - path );
1181 dir[ ofs - path ] = 0;
1187 if ( olddrive != -1 )
1189 _chdrive( olddrive );
1199 Used to archive source files
1202 void QCopyFile (const char *from, const char *to)
1207 length = LoadFile (from, &buffer);
1209 SaveFile (to, buffer, length);
1213 void Sys_Sleep(int n)
1218 #if defined (__linux__) || defined (__APPLE__)