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 #if defined (__linux__) || defined (__APPLE__)
37 #include <glib/gi18n.h>
40 #include <sys/types.h>
48 bool g_bBuildList = false;
52 // =============================================================================
55 // get rid of it when debugging
60 static GtkWidget *splash_screen;
62 // called based on a timer, or in particular cases when we don't want to keep it around
63 gint try_destroy_splash (gpointer data)
67 gtk_widget_destroy (splash_screen);
73 static void create_splash ()
75 GtkWidget *alert_frame, *alert_frame1, *pixmap;
77 splash_screen = gtk_window_new (GTK_WINDOW_POPUP);
78 gtk_window_position (GTK_WINDOW (splash_screen), GTK_WIN_POS_CENTER);
79 gtk_widget_realize (splash_screen);
81 alert_frame1 = gtk_frame_new (NULL);
82 gtk_widget_show (alert_frame1);
83 gtk_container_add (GTK_CONTAINER (splash_screen), alert_frame1);
84 gtk_frame_set_shadow_type (GTK_FRAME (alert_frame1), GTK_SHADOW_OUT);
86 alert_frame = gtk_frame_new (NULL);
87 gtk_widget_show (alert_frame);
89 gtk_container_add (GTK_CONTAINER (alert_frame1), alert_frame);
90 gtk_frame_set_shadow_type (GTK_FRAME (alert_frame), GTK_SHADOW_IN);
91 gtk_container_border_width (GTK_CONTAINER (alert_frame), 3);
93 pixmap = gtk_preview_new (GTK_PREVIEW_COLOR);
94 gtk_widget_show (pixmap);
95 gtk_container_add (GTK_CONTAINER (alert_frame), pixmap);
98 guint16 width, height;
101 str = g_strGameToolsPath;
102 str += "bitmaps/splash.bmp";
104 unsigned char* load_bitmap_file (const char* filename, guint16* width, guint16* height);
105 buf = load_bitmap_file (str.GetBuffer (), &width, &height);
109 str = g_strBitmapsPath;
112 buf = load_bitmap_file (str.GetBuffer (), &width, &height);
117 GtkPreview *preview = GTK_PREVIEW (pixmap);
118 gtk_preview_size (preview, width, height);
119 for (int y = 0; y < height; y++)
120 gtk_preview_draw_row (preview, buf+y*width*3, 0, y, width);
123 gtk_widget_show_all (splash_screen);
125 while (gtk_events_pending ())
126 gtk_main_iteration ();
129 // =============================================================================
132 #if defined (__linux__) || defined (__APPLE__)
134 /* A short game name, could be used as argv[0] */
135 static char game_name[100] = "";
137 /* The directory where the data files can be found (run directory) */
138 static char datapath[PATH_MAX];
140 char *loki_gethomedir(void)
144 home = getenv("HOME");
151 while ( (pwd = getpwent()) != NULL )
153 if ( pwd->pw_uid == id )
164 /* Must be called BEFORE loki_initialize */
165 void loki_setgamename(const char *n)
167 strncpy(game_name, n, sizeof(game_name));
171 /* Code to determine the mount point of a CD-ROM */
172 int loki_getmountpoint(const char *device, char *mntpt, int max_size)
174 char devpath[PATH_MAX], mntdevpath[PATH_MAX];
176 struct mntent *mntent;
179 /* Nothing to do with no device file */
180 if ( device == NULL )
186 /* Get the fully qualified path of the CD-ROM device */
187 if ( realpath(device, devpath) == NULL )
189 perror("realpath() on your CD-ROM failed");
193 /* Get the mount point */
195 memset(mntpt, 0, max_size);
196 mountfp = setmntent( _PATH_MNTTAB, "r" );
197 if ( mountfp != NULL )
200 while ( (mntent = getmntent( mountfp )) != NULL )
202 char *tmp, mntdev[1024];
204 strcpy(mntdev, mntent->mnt_fsname);
205 if ( strcmp(mntent->mnt_type, "supermount") == 0 )
207 tmp = strstr(mntent->mnt_opts, "dev=");
210 strcpy(mntdev, tmp+strlen("dev="));
211 tmp = strchr(mntdev, ',');
218 if ( strncmp(mntdev, "/dev", 4) ||
219 realpath(mntdev, mntdevpath) == NULL )
223 if ( strcmp( mntdevpath, devpath ) == 0 )
226 assert((int)strlen( mntent->mnt_dir ) < max_size);
227 strncpy( mntpt, mntent->mnt_dir, max_size-1);
228 mntpt[max_size-1] = '\0';
232 endmntent( mountfp );
239 This function gets the directory containing the running program.
240 argv0 - the 0'th argument to the program
243 // I don't understand this function. It looks like something cut from another piece of software
244 // we somehow get the g_strAppPath from it, but it's done through a weird scan across $PATH env. var.
245 // even worse, it doesn't behave the same in all cases .. works well when ran through gdb and borks when ran from a shell
246 void loki_initpaths(char *argv0)
248 char temppath[PATH_MAX]; //, env[100];
249 char *home; //, *ptr, *data_env;
251 home = loki_gethomedir();
257 if (*game_name == 0) /* Game name defaults to argv[0] */
258 loki_setgamename(argv0);
260 strcpy(temppath, argv0); /* If this overflows, it's your own fault :) */
261 if ( ! strrchr(temppath, '/') )
268 path = getenv("PATH");
271 /* Initialize our filename variable */
274 /* Get next entry from path variable */
275 last = strchr(path, ':');
277 last = path+strlen(path);
279 /* Perform tilde expansion */
282 strcpy(temppath, home);
286 /* Fill in the rest of the filename */
287 if ( last > (path+1) )
289 strncat(temppath, path, (last-path));
290 strcat(temppath, "/");
292 strcat(temppath, "./");
293 strcat(temppath, argv0);
295 /* See if it exists, and update path */
296 if ( access(temppath, X_OK) == 0 )
302 } while ( *last && !found );
306 /* Increment argv0 to the basename */
307 argv0 = strrchr(argv0, '/')+1;
310 /* Now canonicalize it to a full pathname for the data path */
311 if ( realpath(temppath, datapath) )
313 /* There should always be '/' in the path */
314 *(strrchr(datapath, '/')) = '\0';
318 char *loki_getdatapath(void)
326 // =============================================================================
328 void error_redirect (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
330 gboolean in_recursion;
334 in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
335 is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
336 log_level = (GLogLevelFlags) (log_level & G_LOG_LEVEL_MASK);
339 message = "(NULL) message";
342 strcpy (buf, domain);
349 case G_LOG_LEVEL_ERROR:
351 strcat (buf, "ERROR (recursed) **: ");
353 strcat (buf, "ERROR **: ");
355 case G_LOG_LEVEL_CRITICAL:
357 strcat (buf, "CRITICAL (recursed) **: ");
359 strcat (buf, "CRITICAL **: ");
361 case G_LOG_LEVEL_WARNING:
363 strcat (buf, "WARNING (recursed) **: ");
365 strcat (buf, "WARNING **: ");
367 case G_LOG_LEVEL_MESSAGE:
369 strcat (buf, "Message (recursed): ");
371 strcat (buf, "Message: ");
373 case G_LOG_LEVEL_INFO:
375 strcat (buf, "INFO (recursed): ");
377 strcat (buf, "INFO: ");
379 case G_LOG_LEVEL_DEBUG:
381 strcat (buf, "DEBUG (recursed): ");
383 strcat (buf, "DEBUG: ");
386 /* we are used for a log level that is not defined by GLib itself,
387 * try to make the best out of it.
390 strcat (buf, "LOG (recursed:");
392 strcat (buf, "LOG (");
395 gchar string[] = "0x00): ";
396 gchar *p = string + 2;
399 i = g_bit_nth_msf (log_level, -1);
402 *p = '0' + (i & 0xf);
406 strcat (buf, string);
411 strcat (buf, message);
413 strcat (buf, "\naborting...\n");
417 printf ("%s\n", buf);
418 Sys_FPrintf (SYS_WRN, buf);
419 // TTimo NOTE: in some cases it may be handy to log only to the file
420 // Sys_FPrintf (SYS_NOCON, buf);
423 #define GETTEXT_PACKAGE "radiant"
424 #define LOCALEDIR "lang"
426 int main( int argc, char* argv[] ) {
431 libgl = "opengl32.dll";
434 #if defined (__linux__)
435 libgl = "libGL.so.1";
439 libgl = "/usr/X11R6/lib/libGL.1.dylib";
442 #if defined (__linux__) || defined (__APPLE__)
443 // Give away unnecessary root privileges.
444 // Important: must be done before calling gtk_init().
448 if ( geteuid() == 0 && ( loginname = getlogin() ) != NULL && ( pw = getpwnam(loginname) ) != NULL ) {
454 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
455 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
456 textdomain(GETTEXT_PACKAGE);
457 // gtk_disable_setlocale();
459 gtk_init(&argc, &argv);
461 if ((ptr = getenv ("Q3R_LIBGL")) != NULL)
464 for (i = 1; i < argc; i++)
466 char* param = argv[i];
468 if (param[0] == '-' && param[1] == '-')
472 if ((strcmp (param, "libgl") == 0) && (i != argc))
475 argv[i] = argv[i+1] = NULL;
477 } else if (strcmp (param, "builddefs") == 0)
485 for (i = 1; i < argc; i++)
487 for (k = i; k < argc; k++)
494 for (j = i + k; j < argc; j++)
503 g_strPluginsDir = "plugins/";
504 g_strModulesDir = "modules/";
507 // get path to the editor
508 char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
509 GetModuleFileName(NULL, pBuffer, _MAX_PATH);
510 pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
511 QE_ConvertDOSToUnixName(pBuffer, pBuffer);
512 g_strAppPath.ReleaseBuffer();
514 g_strBitmapsPath = g_strAppPath;
515 g_strBitmapsPath += "bitmaps/";
517 CGameDialog::UpdateNetrun(false); // read the netrun configuration
519 if ( CGameDialog::GetNetrun() ) {
520 // we have to find a per-user g_strTempPath
521 // this behaves the same as on Linux
522 g_strTempPath = getenv("USERPROFILE");
523 if (!g_strTempPath.GetLength())
526 msg = "Radiant is configured to run from a network installation.\n";
527 msg += "I couldn't find the environement variable USERPROFILE\n";
528 msg += "I'm going to use C:\\RadiantSettings. Please set USERPROFILE\n";
529 gtk_MessageBox (NULL, msg, "Radiant - Network mode", MB_OK);
530 g_strTempPath = "C:\\";
532 g_strTempPath += "\\RadiantSettings\\";
533 Q_mkdir(g_strTempPath.GetBuffer(), 0755);
534 g_strTempPath += RADIANT_VERSION;
535 g_strTempPath += "\\";
536 Q_mkdir(g_strTempPath.GetBuffer(), 0755);
540 // use the core path as temp (to save commandlist.txt, and do the .pid files)
541 g_strTempPath = g_strAppPath;
546 #if defined (__linux__) || defined (__APPLE__)
548 home = g_get_home_dir ();
551 Q_mkdir (home.GetBuffer (), 0775);
552 home += RADIANT_VERSION;
553 Q_mkdir (home.GetBuffer (), 0775);
554 g_strTempPath = home.GetBuffer ();
555 AddSlash (g_strTempPath);
557 loki_initpaths(argv[0]);
559 // NOTE: we build g_strAppPath with a '/' (or '\' on WIN32)
560 // it's a general convention in Radiant to have the slash at the end of directories
562 realpath (loki_getdatapath(), real);
563 if (real[strlen(real)-1] != '/')
568 // radiant is installed in the parent dir of "tools/"
569 // NOTE: this is not very easy for debugging
570 // maybe add options to lookup in several places?
571 // (for now I had to create symlinks)
572 g_strBitmapsPath = g_strAppPath;
573 g_strBitmapsPath += "bitmaps/";
575 // we will set this right after the game selection is done
576 g_strGameToolsPath = g_strAppPath;
581 g_strDTDPath = g_strAppPath;
582 g_strDTDPath += "dtds/";
585 the global prefs loading / game selection dialog might fail for any reason we don't know about
586 we need to catch when it happens, to cleanup the stateful prefs which might be killing it
587 and to turn on console logging for lookup of the problem
588 this is the first part of the two step .pid system
589 http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
591 g_pidFile = g_strTempPath.GetBuffer ();
592 g_pidFile += "radiant.pid";
595 pid = fopen( g_pidFile.GetBuffer(), "r" );
600 if (remove (g_pidFile.GetBuffer ()) == -1)
602 msg = "WARNING: Could not delete "; msg += g_pidFile;
603 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
606 // in debug, never prompt to clean registry, turn console logging auto after a failed start
608 msg = "Found the file ";
610 msg += ".\nThis indicates that Radiant failed during the game selection startup last time it was run.\n"
611 "Choose YES to clean Radiant's registry settings and shut down Radiant.\n"
612 "WARNING: the global prefs will be lost if you choose YES.";
614 if (gtk_MessageBox (NULL, msg, "Radiant - Reset global startup?", MB_YESNO | MB_ICONQUESTION) == IDYES)
616 // remove global prefs and shutdown
617 g_PrefsDlg.mGamesDialog.Reset();
618 // remove the prefs file (like a full reset of the registry)
619 //remove (g_PrefsDlg.m_inipath->str);
620 gtk_MessageBox(NULL, "Removed global settings, choose OK to close Radiant.", "Radiant", MB_OK );
623 msg = "Logging console output to ";
624 msg += g_strTempPath;
625 msg += "radiant.log\nRefer to the log if Radiant fails to start again.";
627 gtk_MessageBox (NULL, msg, "Radiant - Console Log", MB_OK);
630 // set without saving, the class is not in a coherent state yet
631 // just do the value change and call to start logging, CGamesDialog will pickup when relevant
632 g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
633 g_PrefsDlg.mGamesDialog.m_bForceLogConsole = true;
637 // create a primary .pid for global init run
638 pid = fopen( g_pidFile.GetBuffer(), "w" );
643 // a safe check to avoid people running broken installations
644 // (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing)
645 // make something idiot proof and someone will make better idiots, this may be overkill
646 // let's leave it disabled in debug mode in any case
647 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
649 //#define CHECK_VERSION
652 // locate and open RADIANT_MAJOR and RADIANT_MINOR
653 qboolean bVerIsGood = true;
655 ver_file_name = g_strAppPath;
656 ver_file_name += "RADIANT_MAJOR";
657 FILE *ver_file = fopen (ver_file_name.GetBuffer(), "r");
662 fread(buf, 1, 10, ver_file);
663 // chomp it (the hard way)
665 while(buf[chomp] >= '0' && buf[chomp] <= '9')
668 if (strcmp(buf, RADIANT_MAJOR_VERSION))
670 Sys_Printf("ERROR: file RADIANT_MAJOR doesn't match ('%s')\n", buf);
676 Sys_Printf("ERROR: can't find RADIANT_MAJOR in '%s'\n", ver_file_name.GetBuffer());
679 ver_file_name = g_strAppPath;
680 ver_file_name += "RADIANT_MINOR";
681 ver_file = fopen (ver_file_name.GetBuffer(), "r");
686 fread(buf, 1, 10, ver_file);
687 // chomp it (the hard way)
689 while(buf[chomp] >= '0' && buf[chomp] <= '9')
692 if (strcmp(buf, RADIANT_MINOR_VERSION))
694 Sys_Printf("ERROR: file RADIANT_MINOR doesn't match ('%s')\n", buf);
700 Sys_Printf("ERROR: can't find RADIANT_MINOR in '%s'\n", ver_file_name.GetBuffer());
706 msg = "This editor binary (" RADIANT_VERSION ") doesn't match what the latest setup has configured in this directory\n";
707 msg += "Make sure you run the right/latest editor binary you installed\n";
708 msg += g_strAppPath; msg += "\n";
709 msg += "Check http://www.qeradiant.com/faq/index.cgi?file=219 for more information";
710 gtk_MessageBox(NULL, msg.GetBuffer(), "Radiant", MB_OK, "http://www.qeradiant.com/faq/index.cgi?file=219");
715 g_qeglobals.disable_ini = false;
719 if ( remove( g_pidFile.GetBuffer () ) == -1 ) {
721 msg = "WARNING: Could not delete "; msg += g_pidGameFile;
722 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
726 now the secondary game dependant .pid file
727 http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
729 g_pidGameFile = g_PrefsDlg.m_rc_path->str;
730 g_pidGameFile += "radiant-game.pid";
732 pid = fopen (g_pidGameFile.GetBuffer(), "r");
737 if (remove (g_pidGameFile.GetBuffer ()) == -1)
739 msg = "WARNING: Could not delete "; msg += g_pidGameFile;
740 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
743 msg = "Found the file ";
744 msg += g_pidGameFile;
745 msg += ".\nThis indicates that Radiant failed to load the last time it was run.\n"
746 "Choose YES to clean Radiant's registry settings and shut down Radiant.\n"
747 "WARNING: preferences will be lost if you choose YES.";
749 // in debug, never prompt to clean registry, turn console logging auto after a failed start
752 if (gtk_MessageBox (NULL, msg, "Radiant - Clean Registry?", MB_YESNO | MB_ICONQUESTION) == IDYES)
754 // remove the game prefs files
755 remove (g_PrefsDlg.m_inipath->str);
757 sprintf(buf, "%sSavedInfo.bin", g_PrefsDlg.m_rc_path->str);
759 // remove the global pref too
760 g_PrefsDlg.mGamesDialog.Reset();
761 gtk_MessageBox(NULL, "Cleaned registry settings, choose OK to close Radiant.\nThe next time Radiant runs it will use default settings.", "Radiant", MB_OK );
764 msg = "Logging console output to ";
765 msg += g_strTempPath;
766 msg += "radiant.log\nRefer to the log if Radiant fails to start again.";
768 gtk_MessageBox (NULL, msg, "Radiant - Console Log", MB_OK);
771 // force console logging on! (will go in prefs too)
772 g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
773 g_PrefsDlg.mGamesDialog.SavePrefs();
776 g_PrefsDlg.LoadPrefs();
780 // create one, will remove right after entering message loop
781 pid = fopen (g_pidGameFile.GetBuffer(), "w");
785 g_PrefsDlg.LoadPrefs();
787 #ifndef _DEBUG // I can't be arsed about that prompt in debug mode
788 // if console logging is on in the prefs, warn about performance hit
789 if (g_PrefsDlg.mGamesDialog.m_bLogConsole)
791 if (gtk_MessageBox (NULL, "Preferences indicate that console logging is on. This affects performance.\n"
792 "Turn it off?", "Radiant", MB_YESNO | MB_ICONQUESTION) == IDYES)
794 g_PrefsDlg.mGamesDialog.m_bLogConsole = false;
795 g_PrefsDlg.mGamesDialog.SavePrefs();
799 // toggle console logging if necessary
803 // FIXME http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
804 // we should search in g_strTempPath, then move over to look at g_strAppPath?
806 // fine tune the look of the app using a gtk rc file
807 // we try to load an RC file placed in the application directory
808 // build the full path
810 sRCFile = g_strAppPath;
811 sRCFile += "radiantgtkrc";
812 // we load that file with g_new in gtk_rc_parse_file (gtkrc.c), change the '/' into '\\'
813 pBuffer = (char *)sRCFile.GetBuffer();
814 for (i=0; i<sRCFile.GetLength(); i++)
821 // check the file exists
822 if (access(sRCFile.GetBuffer(), R_OK) != 0)
823 Sys_Printf("RC file %s not found\n", sRCFile.GetBuffer());
826 Sys_Printf ("Attemping to load RC file %s\n", sRCFile.GetBuffer());
827 gtk_rc_parse (sRCFile.GetBuffer());
835 if (!QGL_Init(libgl, ""))
837 Sys_FPrintf (SYS_ERR, "Failed to load OpenGL libraries\n");
842 #if defined (__linux__) || defined (__APPLE__)
843 if ((qglXQueryExtension == NULL) || (qglXQueryExtension(GDK_DISPLAY(),NULL,NULL) != True))
845 Sys_FPrintf (SYS_ERR, "glXQueryExtension failed\n");
851 // redirect Gtk warnings to the console
852 g_log_set_handler( "Gdk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
853 G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
854 g_log_set_handler( "Gtk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
855 G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
857 // spog - creates new filters list for the first time
858 g_qeglobals.d_savedinfo.filters = NULL;
859 g_qeglobals.d_savedinfo.filters = FilterUpdate(g_qeglobals.d_savedinfo.filters);
861 g_pParentWnd = new MainFrame();
863 if ( g_PrefsDlg.m_bLoadLastMap && g_PrefsDlg.m_strLastMap.GetLength() > 0 ) {
864 Map_LoadFile(g_PrefsDlg.m_strLastMap.GetBuffer());
869 // load up shaders now that we have the map loaded
871 Texture_ShowStartupShaders();
874 gdk_window_raise(splash_screen->window);
875 gtk_window_set_transient_for( GTK_WINDOW( splash_screen ), GTK_WINDOW( g_pParentWnd->m_pWidget ) );
876 gtk_timeout_add( 1000, try_destroy_splash, NULL );
879 g_pParentWnd->GetSynapseServer().DumpActiveClients();
881 //++timo: temporary debug
882 g_pParentWnd->DoWatchBSP();
886 // close the log file if any
887 // NOTE: don't save prefs past this point!
888 g_PrefsDlg.mGamesDialog.m_bLogConsole = false;
889 // set the console window to NULL to avoid Sys_Printf crashing
890 g_qeglobals_gui.d_edit = NULL;
893 // NOTE TTimo not sure what this _exit(0) call is worth
894 // restricting it to linux build
901 // ydnar: quick and dirty fix, just make the buffer bigger
902 #define BIG_PATH_MAX 4096
904 // TTimo: decompose the BSP command into several steps so we can monitor them eventually
905 void QE_ExpandBspString (char *bspaction, GPtrArray *out_array, char *mapname)
909 char src[BIG_PATH_MAX];
910 char rsh[BIG_PATH_MAX];
911 char base[BIG_PATH_MAX];
913 strcpy(src, mapname);
915 in = strstr(src, "maps/");
918 in = strstr(src, "maps/");
935 ExtractFileName (mapname, base);
938 // this important step alters the map name to add fs_game
939 // NOTE: it used to add fs_basepath too
940 // the fs_basepath addition moved to being in the project file during the bug fixing rush
941 // but it may not have been the right thing to do
943 // HACK: halflife compiler tools don't support -fs_game
944 // HACK: neither does JKII/SoF2/ etc..
945 // do we use & have fs_game?
947 if (g_pGameDescription->mGameFile != "hl.game" &&
948 *ValueForKey(g_qeglobals.d_project_entity,"gamename") != '\0')
951 sprintf(src, "-fs_game %s \"%s\"", ValueForKey(g_qeglobals.d_project_entity,"gamename"), mapname);
955 sprintf(src, "\"%s\"", mapname);
960 QE_ConvertDOSToUnixName(src, src);
962 // initialise the first step
963 out = new char[BIG_PATH_MAX]; //% PATH_MAX
964 g_ptr_array_add( out_array, out );
966 in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
979 // we process these only if monitoring
980 if (g_PrefsDlg.m_bWatchBSP)
982 // -connect global option (the only global option so far anyway)
983 strcpy (tmp, " -connect 127.0.0.1:39000 ");
1010 out = new char[BIG_PATH_MAX]; //% PATH_MAX
1011 g_ptr_array_add( out_array, out );
1018 void FindReplace(CString& strContents, const char* pTag, const char* pValue)
1020 if (strcmp(pTag, pValue) == 0)
1022 for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
1024 int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
1025 CString strLeft = strContents.Left(nPos);
1026 CString strRight = strContents.Right(nRightLen);
1028 strLeft += strRight;
1029 strContents = strLeft;
1033 // save the map, deals with regioning
1034 void SaveWithRegion(char *name)
1036 strcpy (name, currentmap);
1039 // temporary cut the region to save regular map
1040 region_active = false;
1041 Map_SaveFile (name, false);
1042 region_active = true;
1043 StripExtension (name);
1044 strcat (name, ".reg");
1047 Map_SaveFile (name, region_active);
1050 void RunBsp (char *command)
1053 char batpath[BIG_PATH_MAX]; //% PATH_MAX
1054 char temppath[BIG_PATH_MAX]; //% PATH_MAX
1055 char name[BIG_PATH_MAX]; //% PATH_MAX
1056 char cWork[BIG_PATH_MAX]; //% PATH_MAX
1060 SetInspectorMode(W_CONSOLE);
1062 strcpy (temppath, g_strTempPath.GetBuffer ());
1064 SaveWithRegion(name);
1066 const char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd");
1069 CString strPath, strFile;
1071 ExtractPath_and_Filename(name, strPath, strFile);
1073 strncpy(cWork, strPath, 1024);
1074 strcat(cWork, strFile);
1077 strcpy(cWork, name);
1080 // get the array ready
1081 //++timo TODO: free the array, free the strings ourselves with delete[]
1082 sys = g_ptr_array_new();
1084 QE_ExpandBspString (command, sys, cWork);
1086 if (g_PrefsDlg.m_bWatchBSP)
1088 // grab the file name for engine running
1089 char *bspname = new char[1024];
1090 ExtractFileName( currentmap, bspname );
1091 StripExtension( bspname );
1092 g_pParentWnd->GetWatchBSP()->DoMonitoringLoop( sys, bspname );
1095 // write all the steps in a single BAT / .sh file and run it, don't bother monitoring it
1097 for (i=0; i < sys->len; i++ )
1099 strSys += (char *)g_ptr_array_index( sys, i);
1100 #ifdef _WIN32 // write temp\junk.txt in win32... NOTE: stops output to shell prompt window
1107 strSys += "junk.txt\"";
1112 #if defined (__linux__) || defined (__APPLE__)
1115 sprintf (batpath, "%sqe3bsp.sh", temppath);
1116 Sys_Printf("Writing the compile script to '%s'\n", batpath);
1117 Sys_Printf("The build output will be saved in '%sjunk.txt'\n", temppath);
1118 hFile = fopen(batpath, "w");
1120 Error ("Can't write to %s", batpath);
1121 fprintf (hFile, "#!/bin/sh \n\n");
1122 fprintf (hFile, strSys.GetBuffer());
1124 chmod (batpath, 0744);
1128 sprintf (batpath, "%sqe3bsp.bat", temppath);
1129 Sys_Printf("Writing the compile script to '%s'\n", batpath);
1130 Sys_Printf("The build output will be saved in '%sjunk.txt'\n", temppath);
1131 hFile = fopen(batpath, "w");
1133 Error ("Can't write to %s", batpath);
1134 fprintf (hFile, strSys.GetBuffer());
1138 Pointfile_Delete ();
1140 #if defined (__linux__) || defined (__APPLE__)
1148 Error ("CreateProcess failed");
1151 execlp (batpath, batpath, NULL);
1152 printf ("execlp error !");
1161 Sys_Printf ("Running bsp command...\n");
1162 Sys_Printf ("\n%s\n", strSys.GetBuffer());
1164 WinExec( batpath, SW_SHOWNORMAL );
1168 // yeah, do it .. but not now right before 1.1-TA-beta release
1169 Sys_Printf("TODO: erase GPtrArray\n");
1177 int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer )
1179 static PIXELFORMATDESCRIPTOR pfd = {
1180 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1181 1, // version number
1182 PFD_DRAW_TO_WINDOW | // support window
1183 PFD_SUPPORT_OPENGL | // support OpenGL
1184 PFD_DOUBLEBUFFER, // double buffered
1185 PFD_TYPE_RGBA, // RGBA type
1186 24, // 24-bit color depth
1187 0, 0, 0, 0, 0, 0, // color bits ignored
1188 0, // no alpha buffer
1189 0, // shift bit ignored
1190 0, // no accumulation buffer
1191 0, 0, 0, 0, // accum bits ignored
1193 0, // no stencil buffer
1194 0, // no auxiliary buffer
1195 PFD_MAIN_PLANE, // main layer
1197 0, 0, 0 // layer masks ignored
1199 int pixelformat = 0;
1205 if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
1209 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1210 FORMAT_MESSAGE_FROM_SYSTEM |
1211 FORMAT_MESSAGE_IGNORE_INSERTS,
1214 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
1219 Sys_FPrintf (SYS_WRN, "GetLastError: %s", lpMsgBuf);
1220 Error ("ChoosePixelFormat failed");
1223 if (!SetPixelFormat(hDC, pixelformat, &pfd))
1224 Error ("SetPixelFormat failed");