]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/main.cpp
apply back 335 and 336, will need to update deps and put a zip out
[xonotic/netradiant.git] / radiant / main.cpp
index b6d1d41b862e1293b2eb31860f753a4aeadfba78..7e004003f17fd6d0256876251d72e0ebdebb14b2 100644 (file)
@@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #if defined (__linux__) || defined (__APPLE__)
   #include <gdk/gdkx.h>
   #include <pwd.h>
-  #include <unistd.h> 
+  #include <unistd.h>
   #ifdef __linux__
     #include <mntent.h>
   #endif
@@ -34,6 +34,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #endif
 
 #include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
+#include <glib/gi18n.h>
 #include "stdafx.h"
 #include <assert.h>
 #include <sys/types.h>
@@ -43,6 +45,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include "watchbsp.h"
 #include "filters.h"
+#include "glwidget.h"
 
 bool g_bBuildList = false;
 int g_argc;
@@ -231,10 +234,10 @@ int loki_getmountpoint(const char *device, char *mntpt, int max_size)
     endmntent( mountfp );
   }
   return(mounted);
-} 
+}
   #endif
 
-/* 
+/*
     This function gets the directory containing the running program.
     argv0 - the 0'th argument to the program
 */
@@ -419,10 +422,58 @@ void error_redirect (const gchar *domain, GLogLevelFlags log_level, const gchar
 //  Sys_FPrintf (SYS_NOCON, buf);
 }
 
-int main (int argc, char* argv[])
-{
-  char *libgl, *ptr;
-  int i, j, k;
+#define GETTEXT_PACKAGE "radiant"
+#define LOCALEDIR "lang"
+
+int main( int argc, char* argv[] ) {
+       char *libgl, *ptr;
+       int i, j, k;
+
+  /*
+    Rambetter on Sat Nov 13, 2010:
+
+    The following line fixes parsing and writing of floating point numbers in locales such as
+    Italy, Germany, and others outside of en_US.  In particular, in such problem locales, users
+    are not able to use certain map entities such as "light" because the definitions of these entities
+    in the entity definition files contain floating point values written in the standard "C" format
+    (containing a dot instead of, for example, a comma).  The call sscanf() is all over the code,
+    including parsing entity definition files and reading Radiant preferences.  sscanf() is sensitive
+    to locale (in particular when reading floating point numbers).
+
+    The line below is the minimalistic way to address only this particular problem - the parsing
+    and writing of floating point values.  There may be other yet-undiscovered bugs related to
+    locale still lingering in the code.  When such bugs are discovered, they should be addressed by
+    setting more than just "LC_NUMERIC=C" (for example LC_CTYPE for regular expression matching)
+    or by fixing the problem in the actual code instead of fiddling with LC_* variables.
+
+    Another way to fix the floating point format problem is to locate all calls such as *scanf()
+    and *printf() in the code and replace them with other functions.  However, we're also using
+    external libraries such as libxml and [maybe?] they use locale to parse their numeric values.
+    I'm just saying, it may get ugly if we try to fix the problem without setting LC_NUMERIC.
+
+    Usage of sscanf() throughout the code looks like so:
+      sscanf(str, "%f %f %f", &val1, &val2, &val3);
+    Code like this exists in many files, here are 4 examples:
+      tools/quake3/q3map2/light.c
+      tools/quake3/q3map2/model.c
+      radiant/preferences.cpp
+      plugins/entity/miscmodel.cpp
+
+    Also affected are printf() calls when using formats that contain "%f".
+
+    I did some research and putenv() seems to be the best choice for being cross-platform.  It
+    used to be a function in Windows (now deprecated):
+      http://msdn.microsoft.com/en-us/library/ms235321(VS.80).aspx
+    And of course it's defined in UNIX.
+
+    One more thing.  the gtk_init() call below modifies all of the locale settings.  In fact if it
+    weren't for gtk_init(), we wouldn't have to set LC_NUMERIC (parsing of floating points with
+    a dot works just fine before the gtk_init() call on a sample Linux system).  If we were to
+    just setlocale() here, it would get clobbered by gtk_init().  So instead of using setlocale()
+    _after_ gtk_init(), I chose to fix this problem via environment variable.  I think it's cleaner
+    that way.
+  */
+  putenv("LC_NUMERIC=C");
 
 #ifdef _WIN32
   libgl = "opengl32.dll";
@@ -442,14 +493,23 @@ int main (int argc, char* argv[])
   char *loginname;
   struct passwd *pw;
   seteuid(getuid());
-  if (geteuid() == 0 && (loginname = getlogin()) != NULL &&
-      (pw = getpwnam(loginname)) != NULL)
-    setuid(pw->pw_uid);
+  if ( geteuid() == 0 && ( loginname = getlogin() ) != NULL && ( pw = getpwnam(loginname) ) != NULL ) {
+         setuid(pw->pw_uid);
+  }
 #endif
 
-  gtk_disable_setlocale();
+
+       bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
+       bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+       textdomain(GETTEXT_PACKAGE);
+//  gtk_disable_setlocale();
 
   gtk_init(&argc, &argv);
+  gtk_gl_init(&argc, &argv);
+  gdk_gl_init(&argc, &argv);
+
+  // TODO: Find a better place to call this.
+  gtk_glwidget_create_font();
 
   if ((ptr = getenv ("Q3R_LIBGL")) != NULL)
     libgl = ptr;
@@ -507,24 +567,9 @@ int main (int argc, char* argv[])
   g_strBitmapsPath = g_strAppPath;
   g_strBitmapsPath += "bitmaps/";
 
-#if 0
-  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
-  // now check if we are running from a network installation
-  // use a dummy file as the flag
-  FILE *f_netrun;
-  CString strNetrun;
-  strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME;
-  f_netrun = fopen(strNetrun.GetBuffer(), "r");
-  if (f_netrun)
-  {
-    fclose(f_netrun);
-    g_PrefsDlg.m_bUseHomePath = true;
-  }
-#endif
   CGameDialog::UpdateNetrun(false); // read the netrun configuration
 
-  if (CGameDialog::GetNetrun())
-  {
+  if ( CGameDialog::GetNetrun() ) {
     // we have to find a per-user g_strTempPath
     // this behaves the same as on Linux
     g_strTempPath = getenv("USERPROFILE");
@@ -573,20 +618,13 @@ int main (int argc, char* argv[])
 
   g_strAppPath = real;
 
-#if 0
-  printf("g_strAppPath: %s\n", g_strAppPath.GetBuffer());
-#endif
-
   // radiant is installed in the parent dir of "tools/"
   // NOTE: this is not very easy for debugging
   // maybe add options to lookup in several places?
   // (for now I had to create symlinks)
   g_strBitmapsPath = g_strAppPath;
   g_strBitmapsPath += "bitmaps/";
-#if 0
-  printf("g_strBitmapsPath: %s\n", g_strBitmapsPath.GetBuffer());
-#endif
-  
+
   // we will set this right after the game selection is done
   g_strGameToolsPath = g_strAppPath;
 
@@ -601,15 +639,13 @@ int main (int argc, char* argv[])
   we need to catch when it happens, to cleanup the stateful prefs which might be killing it
   and to turn on console logging for lookup of the problem
   this is the first part of the two step .pid system
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
   */
   g_pidFile = g_strTempPath.GetBuffer ();
   g_pidFile += "radiant.pid";
 
   FILE *pid;
-  pid = fopen (g_pidFile.GetBuffer(), "r");
-  if (pid != NULL)
-  {
+  pid = fopen( g_pidFile.GetBuffer(), "r" );
+  if ( pid != NULL ) {
     fclose (pid);
     CString msg;
 
@@ -651,19 +687,19 @@ int main (int argc, char* argv[])
   }
 
   // create a primary .pid for global init run
-  pid = fopen (g_pidFile.GetBuffer(), "w");
-  if (pid)
-    fclose (pid);
-  
+  pid = fopen( g_pidFile.GetBuffer(), "w" );
+  if ( pid ) {
+         fclose( pid );
+  }
+
   // a safe check to avoid people running broken installations
   // (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing)
   // make something idiot proof and someone will make better idiots, this may be overkill
   // let's leave it disabled in debug mode in any case
-  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
 #ifndef _DEBUG
-#define CHECK_VERSION
+  //#define CHECK_VERSION
 #endif
-#ifdef CHECK_VERSION  
+#ifdef CHECK_VERSION
   // locate and open RADIANT_MAJOR and RADIANT_MINOR
   qboolean bVerIsGood = true;
   Str ver_file_name;
@@ -726,21 +762,19 @@ int main (int argc, char* argv[])
     _exit(-1);
   }
 #endif
-  
+
   g_qeglobals.disable_ini = false;
-  g_PrefsDlg.Init ();
+  g_PrefsDlg.Init();
 
   // close the primary
-  if (remove (g_pidFile.GetBuffer ()) == -1)
-  {
+  if ( remove( g_pidFile.GetBuffer () ) == -1 ) {
     CString msg;
     msg = "WARNING: Could not delete "; msg += g_pidGameFile;
     gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
   }
-  
+
   /*!
   now the secondary game dependant .pid file
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
   */
   g_pidGameFile = g_PrefsDlg.m_rc_path->str;
   g_pidGameFile += "radiant-game.pid";
@@ -816,7 +850,6 @@ int main (int argc, char* argv[])
     Sys_LogFile();
   }
 
-  // FIXME http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
   // we should search in g_strTempPath, then move over to look at g_strAppPath?
 #ifdef _WIN32
   // fine tune the look of the app using a gtk rc file
@@ -845,7 +878,7 @@ int main (int argc, char* argv[])
 #endif
 
 #ifndef SKIP_SPLASH
-  create_splash ();
+  create_splash();
 #endif
 
   if (!QGL_Init(libgl, ""))
@@ -865,38 +898,39 @@ int main (int argc, char* argv[])
 #endif
 
   // redirect Gtk warnings to the console
-  g_log_set_handler ("Gdk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
+  g_log_set_handler"Gdk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
                                              G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
-  g_log_set_handler ("Gtk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
+  g_log_set_handler"Gtk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
                                              G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
 
   // spog - creates new filters list for the first time
-  g_qeglobals.d_savedinfo.filters = NULL; //initialise to NULL
+  g_qeglobals.d_savedinfo.filters = NULL;
   g_qeglobals.d_savedinfo.filters = FilterUpdate(g_qeglobals.d_savedinfo.filters);
 
-  g_pParentWnd = new MainFrame ();
+  g_pParentWnd = new MainFrame();
 
-  if (g_PrefsDlg.m_bLoadLastMap && g_PrefsDlg.m_strLastMap.GetLength() > 0)
-    Map_LoadFile(g_PrefsDlg.m_strLastMap.GetBuffer());
-  else
-    Map_New();
+  if ( g_PrefsDlg.m_bLoadLastMap && g_PrefsDlg.m_strLastMap.GetLength() > 0 ) {
+         Map_LoadFile(g_PrefsDlg.m_strLastMap.GetBuffer());
+  } else {
+         Map_New();
+  }
 
   // load up shaders now that we have the map loaded
   // eviltypeguy
-  Texture_ShowStartupShaders ();
+  Texture_ShowStartupShaders();
 
 #ifndef SKIP_SPLASH
-  gdk_window_raise (splash_screen->window);
-  gtk_window_set_transient_for (GTK_WINDOW (splash_screen), GTK_WINDOW (g_pParentWnd->m_pWidget));
-  gtk_timeout_add (1000, try_destroy_splash, NULL);
+  gdk_window_raise(splash_screen->window);
+  gtk_window_set_transient_for( GTK_WINDOW( splash_screen ), GTK_WINDOW( g_pParentWnd->m_pWidget ) );
+  gtk_timeout_add( 1000, try_destroy_splash, NULL );
 #endif
-  
+
   g_pParentWnd->GetSynapseServer().DumpActiveClients();
 
   //++timo: temporary debug
   g_pParentWnd->DoWatchBSP();
 
-  gtk_main ();
+  gtk_main();
 
   // close the log file if any
   // NOTE: don't save prefs past this point!
@@ -908,7 +942,7 @@ int main (int argc, char* argv[])
   // NOTE TTimo not sure what this _exit(0) call is worth
   //   restricting it to linux build
 #ifdef __linux__
-  _exit (0);
+  _exit( 0 );
 #endif
   return 0;
 }
@@ -958,7 +992,7 @@ void QE_ExpandBspString (char *bspaction, GPtrArray *out_array, char *mapname)
   // HACK: halflife compiler tools don't support -fs_game
   // HACK: neither does JKII/SoF2/ etc..
   // do we use & have fs_game?
-  
+
   if (g_pGameDescription->mGameFile != "hl.game" &&
       *ValueForKey(g_qeglobals.d_project_entity,"gamename") != '\0')
     {
@@ -1113,9 +1147,9 @@ void RunBsp (char *command)
     {
       strSys += (char *)g_ptr_array_index( sys, i);
 #ifdef _WIN32  // write temp\junk.txt in win32... NOTE: stops output to shell prompt window
-      if (i==0) 
+      if (i==0)
         strSys += " >";
-      else 
+      else
         strSys += " >>";
       strSys += "\"";
       strSys += temppath;
@@ -1147,7 +1181,7 @@ void RunBsp (char *command)
     if (!hFile)
       Error ("Can't write to %s", batpath);
     fprintf (hFile, strSys.GetBuffer());
-    fclose (hFile); 
+    fclose (hFile);
 #endif
 
     Pointfile_Delete ();
@@ -1211,7 +1245,7 @@ int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer )
     0,                              // reserved
     0, 0, 0                         // layer masks ignored
   };                              //
-  int pixelformat = 0;            
+  int pixelformat = 0;
 
   zbuffer = true;
   if ( !zbuffer )
@@ -1221,15 +1255,15 @@ int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer )
   {
     LPVOID lpMsgBuf;
     FormatMessage(
-                 FORMAT_MESSAGE_ALLOCATE_BUFFER | 
-                 FORMAT_MESSAGE_FROM_SYSTEM | 
+                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                 FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL,
                  GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                  (LPTSTR) &lpMsgBuf,
                  0,
-                 NULL 
+                 NULL
                  );
     Sys_FPrintf (SYS_WRN, "GetLastError: %s", lpMsgBuf);
     Error ("ChoosePixelFormat failed");