]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/environment.cpp
radiant/camwindow, radiant/xywindow: Fix use of uninitialized values
[xonotic/netradiant.git] / radiant / environment.cpp
index 9583b90fbc3761fff1e41f25be173f376aec0401..d6be70d54a6b1eb1db87d3f368d9fc1d2ed49499 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "environment.h"
+#include "globaldefs.h"
 
 #include "stream/textstream.h"
 #include "string/string.h"
 #include "cmdlib.h"
 
 int g_argc;
-char** g_argv;
+char const** g_argv;
 
-void args_init( int argc, char* argv[] ){
+void args_init( int argc, char const* argv[] ){
        int i, j, k;
 
        for ( i = 1; i < argc; i++ )
        {
                for ( k = i; k < argc; k++ )
+               {
                        if ( argv[k] != 0 ) {
                                break;
                        }
+               }
 
                if ( k > i ) {
                        k -= i;
                        for ( j = i + k; j < argc; j++ )
+                       {
                                argv[j - k] = argv[j];
+                       }
                        argc -= k;
                }
        }
@@ -54,8 +59,9 @@ void args_init( int argc, char* argv[] ){
        g_argv = argv;
 }
 
-char *gamedetect_argv_buffer[1024];
-void gamedetect_found_game( char *game, char *path ){
+char const *gamedetect_argv_buffer[1024];
+
+void gamedetect_found_game( char const *game, char *path ){
        int argc;
        static char buf[128];
 
@@ -79,7 +85,7 @@ void gamedetect_found_game( char *game, char *path ){
        g_argv = gamedetect_argv_buffer;
 }
 
-bool gamedetect_check_game( char *gamefile, const char *checkfile1, const char *checkfile2, char *buf /* must have 64 bytes free after bufpos */, int bufpos ){
+bool gamedetect_check_game( char const *gamefile, const char *checkfile1, const char *checkfile2, char *buf /* must have 64 bytes free after bufpos */, int bufpos ){
        buf[bufpos] = '/';
 
        strcpy( buf + bufpos + 1, checkfile1 );
@@ -107,12 +113,14 @@ void gamedetect(){
        bool nogamedetect = false;
        int i;
        for ( i = 1; i < g_argc - 1; ++i )
+       {
                if ( g_argv[i][0] == '-' ) {
                        if ( !strcmp( g_argv[i], "-gamedetect" ) ) {
                                nogamedetect = !strcmp( g_argv[i + 1], "false" );
                        }
                        ++i;
                }
+       }
        if ( !nogamedetect ) {
                static char buf[1024 + 64];
                strncpy( buf, environment_get_app_path(), sizeof( buf ) );
@@ -127,17 +135,19 @@ void gamedetect(){
                        // TODO add more games to this
 
                        // try to detect Nexuiz installs
-#if defined( WIN32 )
+#if GDEF_OS_WINDOWS
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) )
-#elif defined( __APPLE__ )
+#elif GDEF_OS_MACOS
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) )
-#else
+#elif GDEF_OS_LINUX
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf ) )
+#else
+                       if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", NULL, buf, p - buf ) )
 #endif
                        { return; }
 
-                       // try to detect Q2World installs
-                       if ( gamedetect_check_game( "q2w.game", "default/quake2world.version", NULL, buf, p - buf ) ) {
+                       // try to detect Quetoo installs
+                       if ( gamedetect_check_game( "quetoo.game", "default/icons/quetoo.png", NULL, buf, p - buf ) ) {
                                return;
                        }
 
@@ -157,8 +167,17 @@ void gamedetect(){
 
 namespace
 {
-CopiedString home_path;
-CopiedString app_path;
+       // executable file path
+       CopiedString app_filepath;
+       // directory paths
+       CopiedString home_path;
+       CopiedString app_path;
+       CopiedString lib_path;
+       CopiedString data_path;
+}
+
+const char* environment_get_app_filepath(){
+       return app_filepath.c_str();
 }
 
 const char* environment_get_home_path(){
@@ -169,17 +188,27 @@ const char* environment_get_app_path(){
        return app_path.c_str();
 }
 
+const char *environment_get_lib_path()
+{
+       return lib_path.c_str();
+}
+
+const char *environment_get_data_path()
+{
+       return data_path.c_str();
+}
+
 bool portable_app_setup(){
        StringOutputStream confdir( 256 );
        confdir << app_path.c_str() << "settings/";
-       if ( file_exists( confdir.c_str() ) ) {
+       if ( file_is_directory( confdir.c_str() ) ) {
                home_path = confdir.c_str();
                return true;
        }
        return false;
 }
 
-#if defined( POSIX )
+#if GDEF_OS_POSIX
 
 #include <stdlib.h>
 #include <pwd.h>
@@ -188,30 +217,34 @@ bool portable_app_setup(){
 #include <glib.h>
 
 const char* LINK_NAME =
-#if defined ( __linux__ )
+#if GDEF_OS_LINUX
        "/proc/self/exe"
-#else // FreeBSD and OSX
+#else // FreeBSD and macOS
        "/proc/curproc/file"
 #endif
 ;
 
-/// brief Returns the filename of the executable belonging to the current process, or 0 if not found.
-char* getexename( char *buf ){
+/// brief Returns the filename of the executable belonging to the current process, or empty string if not found.
+char const* getexename( char *buf ){
        /* Now read the symbolic link */
-       int ret = readlink( LINK_NAME, buf, PATH_MAX );
+       const int ret = readlink( LINK_NAME, buf, PATH_MAX );
 
        if ( ret == -1 ) {
                globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted( g_argv[0] );
-               const char* path = realpath( g_argv[0], buf );
-               if ( path == 0 ) {
+               if( realpath( g_argv[0], buf ) == 0 ) {
                        /* In case of an error, leave the handling up to the caller */
-                       return "";
+                       *buf = '\0';
                }
        }
+       else {
+               /* Ensure proper NUL termination */
+               buf[ret] = 0;
+       }
 
-       /* Ensure proper NUL termination */
-       buf[ret] = 0;
+       return buf;
+}
 
+char const* getexepath( char *buf ) {
        /* delete the program name */
        *( strrchr( buf, '/' ) ) = '\0';
 
@@ -224,7 +257,7 @@ char* getexename( char *buf ){
        return buf;
 }
 
-void environment_init( int argc, char* argv[] ){
+void environment_init( int argc, char const* argv[] ){
        // Give away unnecessary root privileges.
        // Important: must be done before calling gtk_init().
        char *loginname;
@@ -239,30 +272,68 @@ void environment_init( int argc, char* argv[] ){
 
        {
                char real[PATH_MAX];
-               app_path = getexename( real );
-               ASSERT_MESSAGE( !string_empty( app_path.c_str() ), "failed to deduce app path" );
+               app_filepath = getexename( real );
+               ASSERT_MESSAGE( !string_empty( app_filepath.c_str() ), "failed to deduce app path" );
+
+               strncpy( real, app_filepath.c_str(), strlen( app_filepath.c_str() ) );
+               app_path = getexepath( real );
+       }
+
+       {
+               StringOutputStream buffer;
+               buffer << app_path.c_str() << "../lib/" << RADIANT_BASENAME << "/";
+               if ( file_is_directory( buffer.c_str() ) ) {
+                       lib_path = buffer.c_str();
+               }
+               else {
+                       lib_path = app_path.c_str();
+               }
+       }
+
+       {
+               StringOutputStream buffer;
+               buffer << app_path.c_str() << "../share/" << RADIANT_BASENAME << "/";
+               if ( file_is_directory( buffer.c_str() ) ) {
+                       data_path = buffer.c_str();
+               }
+               else {
+                       data_path = app_path.c_str();
+               }
        }
 
        if ( !portable_app_setup() ) {
+               // this is used on both Linux and macOS
+               // but a macOS specific code may be written instead
                StringOutputStream home( 256 );
-               home << DirectoryCleaned( g_get_home_dir() ) << ".netradiant/";
+               home << DirectoryCleaned(g_get_user_config_dir()) << "/" << RADIANT_BASENAME << "/";
+               // first create ~/.config
+               // since it may be missing on brand new home directory
+               Q_mkdir( g_get_user_config_dir() );
+               // then create ~/.config/netradiant
                Q_mkdir( home.c_str() );
                home_path = home.c_str();
        }
        gamedetect();
 }
 
-#elif defined( WIN32 )
+#elif GDEF_OS_WINDOWS
 
 #include <windows.h>
 
-void environment_init( int argc, char* argv[] ){
+void environment_init( int argc, char const* argv[] ){
        args_init( argc, argv );
 
        {
                // get path to the editor
                char filename[MAX_PATH + 1];
+               StringOutputStream app_filepath_stream( 256 );
+               StringOutputStream app_path_stream( 256 );
+
                GetModuleFileName( 0, filename, MAX_PATH );
+               
+               app_filepath_stream << PathCleaned( filename );
+               app_filepath = app_filepath_stream.c_str();
+
                char* last_separator = strrchr( filename, '\\' );
                if ( last_separator != 0 ) {
                        *( last_separator + 1 ) = '\0';
@@ -271,23 +342,18 @@ void environment_init( int argc, char* argv[] ){
                {
                        filename[0] = '\0';
                }
-               StringOutputStream app( 256 );
-               app << PathCleaned( filename );
-               app_path = app.c_str();
+
+               app_path_stream << PathCleaned( filename );
+               app_path = app_path_stream.c_str();
+
+               lib_path = app_path;
+               data_path = app_path;
        }
 
        if ( !portable_app_setup() ) {
                char *appdata = getenv( "APPDATA" );
                StringOutputStream home( 256 );
-               if ( !appdata || string_empty( appdata ) ) {
-                       ERROR_MESSAGE( "Application Data folder not available.\n"
-                                                  "Radiant will use C:\\ for user preferences.\n" );
-                       home << "C:";
-               }
-               else
-               {
-                       home << PathCleaned( appdata );
-               }
+               home << PathCleaned( appdata );
                home << "/NetRadiantSettings/";
                Q_mkdir( home.c_str() );
                home_path = home.c_str();