]> icculus.org git repositories - divverent/netradiant.git/blob - tools/quake3/q3map2/path_init.c
fix typo
[divverent/netradiant.git] / tools / quake3 / q3map2 / path_init.c
1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22 ----------------------------------------------------------------------------------
23
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27 ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define PATH_INIT_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41 /* path support */
42 #define MAX_BASE_PATHS  10
43 #define MAX_GAME_PATHS  10
44
45 char                                    *homePath;
46 qboolean                                homePathUsesDot;
47 char                                    installPath[ MAX_OS_PATH ];
48
49 int                                             numBasePaths;
50 char                                    *basePaths[ MAX_BASE_PATHS ];
51 int                                             numGamePaths;
52 char                                    *gamePaths[ MAX_GAME_PATHS ];
53 char                                    *homeBasePath = NULL;
54
55
56 /*
57 some of this code is based off the original q3map port from loki
58 and finds various paths. moved here from bsp.c for clarity.
59 */
60
61 /*
62 PathLokiGetHomeDir()
63 gets the user's home dir (for ~/.q3a)
64 */
65
66 #ifdef WIN32
67 #include <shlobj.h>
68 #endif
69 char *LokiGetHomeDir( qboolean *usedot )
70 {
71         *usedot = qtrue;
72         #ifndef Q_UNIX
73                 #ifndef WIN32
74                         return NULL;
75                 #else
76                         static char buf[MAX_OS_PATH];
77                         TCHAR mydocsdir[MAX_PATH + 1];
78                         if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, mydocsdir))
79                         {
80                                 snprintf(buf, sizeof(buf), "%s/My Games", mydocsdir);
81                                 *usedot = qfalse;
82                                 return buf;
83                         }
84                         return NULL;
85                 #endif
86         #else
87                 char                    *home;
88                 uid_t                   id;
89                 struct passwd   *pwd;
90                 
91                 
92                 /* get the home environment variable */
93                 home = getenv( "HOME" );
94                 if( home == NULL )
95                 {
96                         /* do some more digging */
97                         id = getuid();
98                         setpwent();
99                         while( (pwd = getpwent()) != NULL )
100                         {
101                                 if( pwd->pw_uid == id )
102                                 {
103                                         home = pwd->pw_dir;
104                                         break;
105                                 }
106                         }
107                         endpwent();
108                 }
109
110                 #ifdef __APPLE__
111                 {
112                         static char foo[MAX_OS_PATH];
113                         snprintf(foo, sizeof(foo), "%s/Library/Application Support", home);
114                         if(access(foo, X_OK) == 0)
115                         {
116                                 *usedot = qfalse;
117                                 home = foo;
118                         }
119                 }
120                 #endif
121                 
122                 /* return it */
123                 return home;
124         #endif
125 }
126
127
128
129 /*
130 PathLokiInitPaths()
131 initializes some paths on linux/os x
132 */
133
134 void LokiInitPaths( char *argv0 )
135 {
136         #ifndef Q_UNIX
137                 char            *home;
138
139                 /* this is kinda crap, but hey */
140                 strcpy( installPath, "../" );
141
142                 /* get home dir */
143                 home = LokiGetHomeDir(&homePathUsesDot);
144                 if( home == NULL )
145                         home = ".";
146
147                 /* set home path */
148                 homePath = home;
149         #else
150                 char            temp[ MAX_OS_PATH ];
151                 char            last0[ 2 ];
152                 char            *home;
153                 char            *path;
154                 char            *last;
155                 qboolean        found;
156                 
157                 
158                 /* get home dir */
159                 home = LokiGetHomeDir(&homePathUsesDot);
160                 if( home == NULL )
161                         home = ".";
162                 
163                 /* do some path divining */
164                 strcpy( temp, argv0 );
165                 if( strrchr( argv0, '/' ) )
166                         argv0 = strrchr( argv0, '/' ) + 1;
167                 else
168                 {
169                         /* get path environment variable */
170                         path = getenv( "PATH" );
171                         
172                         /* minor setup */
173                         last = last0;
174                         last[ 0 ] = path[ 0 ];
175                         last[ 1 ] = '\0';
176                         found = qfalse;
177                         
178                         /* go through each : segment of path */
179                         while( last[ 0 ] != '\0' && found == qfalse )
180                         {
181                                 /* null out temp */
182                                 temp[ 0 ] = '\0';
183                                 
184                                 /* find next chunk */
185                                 last = strchr( path, ':' );
186                                 if( last == NULL )
187                                         last = path + strlen( path );
188                                 
189                                 /* found home dir candidate */
190                                 if( *path == '~' )
191                                 {
192                                         strcpy( temp, home );
193                                         path++;
194                                 }
195                                 
196                                 /* concatenate */
197                                 if( last > (path + 1) )
198                                 {
199                                         strncat( temp, path, (last - path) );
200                                         strcat( temp, "/" );
201                                 }
202                                 strcat( temp, "./" );
203                                 strcat( temp, argv0 );
204                                 
205                                 /* verify the path */
206                                 if( access( temp, X_OK ) == 0 )
207                                         found++;
208                                 path = last + 1;
209                         }
210                 }
211                 
212                 /* flake */
213                 if( realpath( temp, installPath ) )
214                 {
215                         /* q3map is in "tools/" */
216                         *(strrchr( installPath, '/' )) = '\0';
217                         *(strrchr( installPath, '/' ) + 1) = '\0';
218                 }
219                 
220                 /* set home path */
221                 homePath = home;
222         #endif
223 }
224
225
226
227 /*
228 CleanPath() - ydnar
229 cleans a dos path \ -> /
230 */
231
232 void CleanPath( char *path )
233 {
234         while( *path )
235         {
236                 if( *path == '\\' )
237                         *path = '/';
238                 path++;
239         }
240 }
241
242
243
244 /*
245 GetGame() - ydnar
246 gets the game_t based on a -game argument
247 returns NULL if no match found
248 */
249
250 game_t *GetGame( char *arg )
251 {
252         int     i;
253         
254         
255         /* dummy check */
256         if( arg == NULL || arg[ 0 ] == '\0' )
257                 return NULL;
258         
259         /* joke */
260         if( !Q_stricmp( arg, "quake1" ) ||
261                 !Q_stricmp( arg, "quake2" ) ||
262                 !Q_stricmp( arg, "unreal" ) ||
263                 !Q_stricmp( arg, "ut2k3" ) ||
264                 !Q_stricmp( arg, "dn3d" ) ||
265                 !Q_stricmp( arg, "dnf" ) ||
266                 !Q_stricmp( arg, "hl" ) )
267         {
268                 Sys_Printf( "April fools, silly rabbit!\n" );
269                 exit( 0 );
270         }
271         
272         /* test it */
273         i = 0;
274         while( games[ i ].arg != NULL )
275         {
276                 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
277                         return &games[ i ];
278                 i++;
279         }
280         
281         /* no matching game */
282         return NULL;
283 }
284
285
286
287 /*
288 AddBasePath() - ydnar
289 adds a base path to the list
290 */
291
292 void AddBasePath( char *path )
293 {
294         /* dummy check */
295         if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
296                 return;
297         
298         /* add it to the list */
299         basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
300         strcpy( basePaths[ numBasePaths ], path );
301         CleanPath( basePaths[ numBasePaths ] );
302         numBasePaths++;
303 }
304
305
306
307 /*
308 AddHomeBasePath() - ydnar
309 adds a base path to the beginning of the list, prefixed by ~/
310 */
311
312 void AddHomeBasePath( char *path )
313 {
314         int             i;
315         char    temp[ MAX_OS_PATH ];
316         
317         if(!homePath)
318                 return;
319         
320         /* dummy check */
321         if( path == NULL || path[ 0 ] == '\0' )
322                 return;
323
324         /* concatenate home dir and path */
325         sprintf( temp, "%s/%s", homePath, homePathUsesDot ? path : (path+1) );
326         
327 #ifdef WIN32
328         {
329                 /* on Win32, we ONLY add it if the directory already exists */
330                 GDir *dir;
331                 dir = g_dir_open (temp, 0, NULL);
332                 if(!dir)
333                         return;
334                 g_dir_close(dir);
335         }
336 #endif
337
338         /* make a hole */
339         for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
340                 basePaths[ i + 1 ] = basePaths[ i ];
341         
342         /* add it to the list */
343         basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
344         strcpy( basePaths[ 0 ], temp );
345         CleanPath( basePaths[ 0 ] );
346         numBasePaths++;
347 }
348
349
350
351 /*
352 AddGamePath() - ydnar
353 adds a game path to the list
354 */
355
356 void AddGamePath( char *path )
357 {
358         int     i;
359
360         /* dummy check */
361         if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
362                 return;
363         
364         /* add it to the list */
365         gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
366         strcpy( gamePaths[ numGamePaths ], path );
367         CleanPath( gamePaths[ numGamePaths ] );
368         numGamePaths++;
369
370         /* don't add it if it's already there */
371         for (i = 0; i < numGamePaths - 1; i++)
372         {
373                 if (strcmp(gamePaths[i], gamePaths[numGamePaths - 1]) == 0)
374                 {
375                         free(gamePaths[numGamePaths - 1]);
376                         gamePaths[numGamePaths - 1] = NULL;
377                         numGamePaths--;
378                         break;
379                 }
380         }
381         
382 }
383
384
385
386
387 /*
388 InitPaths() - ydnar
389 cleaned up some of the path initialization code from bsp.c
390 will remove any arguments it uses
391 */
392
393 void InitPaths( int *argc, char **argv )
394 {
395         int             i, j, k, len, len2;
396         char    temp[ MAX_OS_PATH ];
397         
398         
399         /* note it */
400         Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
401         
402         /* get the install path for backup */
403         LokiInitPaths( argv[ 0 ] );
404         
405         /* set game to default (q3a) */
406         game = &games[ 0 ];
407         numBasePaths = 0;
408         numGamePaths = 0;
409         
410         /* parse through the arguments and extract those relevant to paths */
411         for( i = 0; i < *argc; i++ )
412         {
413                 /* check for null */
414                 if( argv[ i ] == NULL )
415                         continue;
416                 
417                 /* -game */
418                 if( strcmp( argv[ i ], "-game" ) == 0 )
419                 {
420                         if( ++i >= *argc )
421                                 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
422                         argv[ i - 1 ] = NULL;
423                         game = GetGame( argv[ i ] );
424                         if( game == NULL )
425                                 game = &games[ 0 ];
426                         argv[ i ] = NULL;
427                 }
428
429                 /* -fs_forbiddenpath */
430                 else if( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 )
431                 {
432                         if( ++i >= *argc )
433                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
434                         argv[ i - 1 ] = NULL;
435                         if(g_numForbiddenDirs < VFS_MAXDIRS)
436                         {
437                                 strncpy(g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX);
438                                 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
439                                 ++g_numForbiddenDirs;
440                         }
441                         argv[ i ] = NULL;
442                 }
443
444                 /* -fs_basepath */
445                 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
446                 {
447                         if( ++i >= *argc )
448                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
449                         argv[ i - 1 ] = NULL;
450                         AddBasePath( argv[ i ] );
451                         argv[ i ] = NULL;
452                 }
453                 
454                 /* -fs_game */
455                 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
456                 {
457                         if( ++i >= *argc )
458                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
459                         argv[ i - 1 ] = NULL;
460                         AddGamePath( argv[ i ] );
461                         argv[ i ] = NULL;
462                 }
463                 
464                 /* -fs_nohomebase */
465                 else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
466                 {
467                         if( ++i >= *argc )
468                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
469                         argv[ i - 1 ] = NULL;
470                         homeBasePath = argv[i];
471                         argv[ i ] = NULL;
472                 }
473         }
474         
475         /* remove processed arguments */
476         for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
477         {
478                 for( ; j < *argc && argv[ j ] == NULL; j++ );
479                 argv[ i ] = argv[ j ];
480                 if( argv[ i ] != NULL )
481                         k++;
482         }
483         *argc = k;
484         
485         /* add standard game path */
486         AddGamePath( game->gamePath );
487         
488         /* if there is no base path set, figure it out */
489         if( numBasePaths == 0 )
490         {
491                 /* this is another crappy replacement for SetQdirFromPath() */
492                 len2 = strlen( game->magic );
493                 for( i = 0; i < *argc && numBasePaths == 0; i++ )
494                 {
495                         /* extract the arg */
496                         strcpy( temp, argv[ i ] );
497                         CleanPath( temp );
498                         len = strlen( temp );
499                         Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
500                         
501                         /* this is slow, but only done once */
502                         for( j = 0; j < (len - len2); j++ )
503                         {
504                                 /* check for the game's magic word */
505                                 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
506                                 {
507                                         /* now find the next slash and nuke everything after it */
508                                         while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
509                                         temp[ j ] = '\0';
510                                         
511                                         /* add this as a base path */
512                                         AddBasePath( temp );
513                                         break;
514                                 }
515                         }
516                 }
517                 
518                 /* add install path */
519                 if( numBasePaths == 0 )
520                         AddBasePath( installPath );
521                 
522                 /* check again */
523                 if( numBasePaths == 0 )
524                         Error( "Failed to find a valid base path." );
525         }
526         
527         /* this only affects unix */
528         if(homeBasePath)
529                 AddHomeBasePath( homeBasePath );
530         else
531                 AddHomeBasePath( game->homeBasePath );
532         
533         /* initialize vfs paths */
534         if( numBasePaths > MAX_BASE_PATHS )
535                 numBasePaths = MAX_BASE_PATHS;
536         if( numGamePaths > MAX_GAME_PATHS )
537                 numGamePaths = MAX_GAME_PATHS;
538         
539         /* walk the list of game paths */
540         for( j = 0; j < numGamePaths; j++ )
541         {
542                 /* walk the list of base paths */
543                 for( i = 0; i < numBasePaths; i++ )
544                 {
545                         /* create a full path and initialize it */
546                         sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
547                         vfsInitDirectory( temp );
548                 }
549         }
550         
551         /* done */
552         Sys_Printf( "\n" );
553 }
554
555
556
557