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__)
39 #include <sys/types.h>
47 bool g_bBuildList = false;
51 // =============================================================================
54 // get rid of it when debugging
59 static GtkWidget *splash_screen;
61 // called based on a timer, or in particular cases when we don't want to keep it around
62 gint try_destroy_splash (gpointer data)
66 gtk_widget_destroy (splash_screen);
72 static void create_splash ()
74 GtkWidget *alert_frame, *alert_frame1, *pixmap;
76 splash_screen = gtk_window_new (GTK_WINDOW_POPUP);
77 gtk_window_position (GTK_WINDOW (splash_screen), GTK_WIN_POS_CENTER);
78 gtk_widget_realize (splash_screen);
80 alert_frame1 = gtk_frame_new (NULL);
81 gtk_widget_show (alert_frame1);
82 gtk_container_add (GTK_CONTAINER (splash_screen), alert_frame1);
83 gtk_frame_set_shadow_type (GTK_FRAME (alert_frame1), GTK_SHADOW_OUT);
85 alert_frame = gtk_frame_new (NULL);
86 gtk_widget_show (alert_frame);
88 gtk_container_add (GTK_CONTAINER (alert_frame1), alert_frame);
89 gtk_frame_set_shadow_type (GTK_FRAME (alert_frame), GTK_SHADOW_IN);
90 gtk_container_border_width (GTK_CONTAINER (alert_frame), 3);
92 pixmap = gtk_preview_new (GTK_PREVIEW_COLOR);
93 gtk_widget_show (pixmap);
94 gtk_container_add (GTK_CONTAINER (alert_frame), pixmap);
97 guint16 width, height;
100 str = g_strGameToolsPath;
101 str += "bitmaps/splash.bmp";
103 unsigned char* load_bitmap_file (const char* filename, guint16* width, guint16* height);
104 buf = load_bitmap_file (str.GetBuffer (), &width, &height);
108 str = g_strBitmapsPath;
111 buf = load_bitmap_file (str.GetBuffer (), &width, &height);
116 GtkPreview *preview = GTK_PREVIEW (pixmap);
117 gtk_preview_size (preview, width, height);
118 for (int y = 0; y < height; y++)
119 gtk_preview_draw_row (preview, buf+y*width*3, 0, y, width);
122 gtk_widget_show_all (splash_screen);
124 while (gtk_events_pending ())
125 gtk_main_iteration ();
128 // =============================================================================
131 #if defined (__linux__) || defined (__APPLE__)
133 /* A short game name, could be used as argv[0] */
134 static char game_name[100] = "";
136 /* The directory where the data files can be found (run directory) */
137 static char datapath[PATH_MAX];
139 char *loki_gethomedir(void)
143 home = getenv("HOME");
150 while ( (pwd = getpwent()) != NULL )
152 if ( pwd->pw_uid == id )
163 /* Must be called BEFORE loki_initialize */
164 void loki_setgamename(const char *n)
166 strncpy(game_name, n, sizeof(game_name));
170 /* Code to determine the mount point of a CD-ROM */
171 int loki_getmountpoint(const char *device, char *mntpt, int max_size)
173 char devpath[PATH_MAX], mntdevpath[PATH_MAX];
175 struct mntent *mntent;
178 /* Nothing to do with no device file */
179 if ( device == NULL )
185 /* Get the fully qualified path of the CD-ROM device */
186 if ( realpath(device, devpath) == NULL )
188 perror("realpath() on your CD-ROM failed");
192 /* Get the mount point */
194 memset(mntpt, 0, max_size);
195 mountfp = setmntent( _PATH_MNTTAB, "r" );
196 if ( mountfp != NULL )
199 while ( (mntent = getmntent( mountfp )) != NULL )
201 char *tmp, mntdev[1024];
203 strcpy(mntdev, mntent->mnt_fsname);
204 if ( strcmp(mntent->mnt_type, "supermount") == 0 )
206 tmp = strstr(mntent->mnt_opts, "dev=");
209 strcpy(mntdev, tmp+strlen("dev="));
210 tmp = strchr(mntdev, ',');
217 if ( strncmp(mntdev, "/dev", 4) ||
218 realpath(mntdev, mntdevpath) == NULL )
222 if ( strcmp( mntdevpath, devpath ) == 0 )
225 assert((int)strlen( mntent->mnt_dir ) < max_size);
226 strncpy( mntpt, mntent->mnt_dir, max_size-1);
227 mntpt[max_size-1] = '\0';
231 endmntent( mountfp );
238 This function gets the directory containing the running program.
239 argv0 - the 0'th argument to the program
242 // I don't understand this function. It looks like something cut from another piece of software
243 // we somehow get the g_strAppPath from it, but it's done through a weird scan across $PATH env. var.
244 // even worse, it doesn't behave the same in all cases .. works well when ran through gdb and borks when ran from a shell
245 void loki_initpaths(char *argv0)
247 char temppath[PATH_MAX]; //, env[100];
248 char *home; //, *ptr, *data_env;
250 home = loki_gethomedir();
256 if (*game_name == 0) /* Game name defaults to argv[0] */
257 loki_setgamename(argv0);
259 strcpy(temppath, argv0); /* If this overflows, it's your own fault :) */
260 if ( ! strrchr(temppath, '/') )
267 path = getenv("PATH");
270 /* Initialize our filename variable */
273 /* Get next entry from path variable */
274 last = strchr(path, ':');
276 last = path+strlen(path);
278 /* Perform tilde expansion */
281 strcpy(temppath, home);
285 /* Fill in the rest of the filename */
286 if ( last > (path+1) )
288 strncat(temppath, path, (last-path));
289 strcat(temppath, "/");
291 strcat(temppath, "./");
292 strcat(temppath, argv0);
294 /* See if it exists, and update path */
295 if ( access(temppath, X_OK) == 0 )
301 } while ( *last && !found );
305 /* Increment argv0 to the basename */
306 argv0 = strrchr(argv0, '/')+1;
309 /* Now canonicalize it to a full pathname for the data path */
310 if ( realpath(temppath, datapath) )
312 /* There should always be '/' in the path */
313 *(strrchr(datapath, '/')) = '\0';
317 char *loki_getdatapath(void)
325 // =============================================================================
327 void error_redirect (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
329 gboolean in_recursion;
333 in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
334 is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
335 log_level = (GLogLevelFlags) (log_level & G_LOG_LEVEL_MASK);
338 message = "(NULL) message";
341 strcpy (buf, domain);
348 case G_LOG_LEVEL_ERROR:
350 strcat (buf, "ERROR (recursed) **: ");
352 strcat (buf, "ERROR **: ");
354 case G_LOG_LEVEL_CRITICAL:
356 strcat (buf, "CRITICAL (recursed) **: ");
358 strcat (buf, "CRITICAL **: ");
360 case G_LOG_LEVEL_WARNING:
362 strcat (buf, "WARNING (recursed) **: ");
364 strcat (buf, "WARNING **: ");
366 case G_LOG_LEVEL_MESSAGE:
368 strcat (buf, "Message (recursed): ");
370 strcat (buf, "Message: ");
372 case G_LOG_LEVEL_INFO:
374 strcat (buf, "INFO (recursed): ");
376 strcat (buf, "INFO: ");
378 case G_LOG_LEVEL_DEBUG:
380 strcat (buf, "DEBUG (recursed): ");
382 strcat (buf, "DEBUG: ");
385 /* we are used for a log level that is not defined by GLib itself,
386 * try to make the best out of it.
389 strcat (buf, "LOG (recursed:");
391 strcat (buf, "LOG (");
394 gchar string[] = "0x00): ";
395 gchar *p = string + 2;
398 i = g_bit_nth_msf (log_level, -1);
401 *p = '0' + (i & 0xf);
405 strcat (buf, string);
410 strcat (buf, message);
412 strcat (buf, "\naborting...\n");
416 printf ("%s\n", buf);
417 Sys_FPrintf (SYS_WRN, buf);
418 // TTimo NOTE: in some cases it may be handy to log only to the file
419 // Sys_FPrintf (SYS_NOCON, buf);
422 int main( int argc, char* argv[] ) {
427 libgl = "opengl32.dll";
430 #if defined (__linux__)
431 libgl = "libGL.so.1";
435 libgl = "/usr/X11R6/lib/libGL.1.dylib";
438 #if defined (__linux__) || defined (__APPLE__)
439 // Give away unnecessary root privileges.
440 // Important: must be done before calling gtk_init().
444 if ( geteuid() == 0 && ( loginname = getlogin() ) != NULL && ( pw = getpwnam(loginname) ) != NULL ) {
449 gtk_disable_setlocale();
451 gtk_init(&argc, &argv);
453 if ((ptr = getenv ("Q3R_LIBGL")) != NULL)
456 for (i = 1; i < argc; i++)
458 char* param = argv[i];
460 if (param[0] == '-' && param[1] == '-')
464 if ((strcmp (param, "libgl") == 0) && (i != argc))
467 argv[i] = argv[i+1] = NULL;
469 } else if (strcmp (param, "builddefs") == 0)
477 for (i = 1; i < argc; i++)
479 for (k = i; k < argc; k++)
486 for (j = i + k; j < argc; j++)
495 g_strPluginsDir = "plugins/";
496 g_strModulesDir = "modules/";
499 // get path to the editor
500 char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
501 GetModuleFileName(NULL, pBuffer, _MAX_PATH);
502 pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
503 QE_ConvertDOSToUnixName(pBuffer, pBuffer);
504 g_strAppPath.ReleaseBuffer();
506 g_strBitmapsPath = g_strAppPath;
507 g_strBitmapsPath += "bitmaps/";
509 CGameDialog::UpdateNetrun(false); // read the netrun configuration
511 if ( CGameDialog::GetNetrun() ) {
512 // we have to find a per-user g_strTempPath
513 // this behaves the same as on Linux
514 g_strTempPath = getenv("USERPROFILE");
515 if (!g_strTempPath.GetLength())
518 msg = "Radiant is configured to run from a network installation.\n";
519 msg += "I couldn't find the environement variable USERPROFILE\n";
520 msg += "I'm going to use C:\\RadiantSettings. Please set USERPROFILE\n";
521 gtk_MessageBox (NULL, msg, "Radiant - Network mode", MB_OK);
522 g_strTempPath = "C:\\";
524 g_strTempPath += "\\RadiantSettings\\";
525 Q_mkdir(g_strTempPath.GetBuffer(), 0755);
526 g_strTempPath += RADIANT_VERSION;
527 g_strTempPath += "\\";
528 Q_mkdir(g_strTempPath.GetBuffer(), 0755);
532 // use the core path as temp (to save commandlist.txt, and do the .pid files)
533 g_strTempPath = g_strAppPath;
538 #if defined (__linux__) || defined (__APPLE__)
540 home = g_get_home_dir ();
543 Q_mkdir (home.GetBuffer (), 0775);
544 home += RADIANT_VERSION;
545 Q_mkdir (home.GetBuffer (), 0775);
546 g_strTempPath = home.GetBuffer ();
547 AddSlash (g_strTempPath);
549 loki_initpaths(argv[0]);
551 // NOTE: we build g_strAppPath with a '/' (or '\' on WIN32)
552 // it's a general convention in Radiant to have the slash at the end of directories
554 realpath (loki_getdatapath(), real);
555 if (real[strlen(real)-1] != '/')
560 // radiant is installed in the parent dir of "tools/"
561 // NOTE: this is not very easy for debugging
562 // maybe add options to lookup in several places?
563 // (for now I had to create symlinks)
564 g_strBitmapsPath = g_strAppPath;
565 g_strBitmapsPath += "bitmaps/";
567 // we will set this right after the game selection is done
568 g_strGameToolsPath = g_strAppPath;
573 g_strDTDPath = g_strAppPath;
574 g_strDTDPath += "dtds/";
577 the global prefs loading / game selection dialog might fail for any reason we don't know about
578 we need to catch when it happens, to cleanup the stateful prefs which might be killing it
579 and to turn on console logging for lookup of the problem
580 this is the first part of the two step .pid system
581 http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
583 g_pidFile = g_strTempPath.GetBuffer ();
584 g_pidFile += "radiant.pid";
587 pid = fopen( g_pidFile.GetBuffer(), "r" );
592 if (remove (g_pidFile.GetBuffer ()) == -1)
594 msg = "WARNING: Could not delete "; msg += g_pidFile;
595 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
598 // in debug, never prompt to clean registry, turn console logging auto after a failed start
600 msg = "Found the file ";
602 msg += ".\nThis indicates that Radiant failed during the game selection startup last time it was run.\n"
603 "Choose YES to clean Radiant's registry settings and shut down Radiant.\n"
604 "WARNING: the global prefs will be lost if you choose YES.";
606 if (gtk_MessageBox (NULL, msg, "Radiant - Reset global startup?", MB_YESNO | MB_ICONQUESTION) == IDYES)
608 // remove global prefs and shutdown
609 g_PrefsDlg.mGamesDialog.Reset();
610 // remove the prefs file (like a full reset of the registry)
611 //remove (g_PrefsDlg.m_inipath->str);
612 gtk_MessageBox(NULL, "Removed global settings, choose OK to close Radiant.", "Radiant", MB_OK );
615 msg = "Logging console output to ";
616 msg += g_strTempPath;
617 msg += "radiant.log\nRefer to the log if Radiant fails to start again.";
619 gtk_MessageBox (NULL, msg, "Radiant - Console Log", MB_OK);
622 // set without saving, the class is not in a coherent state yet
623 // just do the value change and call to start logging, CGamesDialog will pickup when relevant
624 g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
625 g_PrefsDlg.mGamesDialog.m_bForceLogConsole = true;
629 // create a primary .pid for global init run
630 pid = fopen( g_pidFile.GetBuffer(), "w" );
635 // a safe check to avoid people running broken installations
636 // (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing)
637 // make something idiot proof and someone will make better idiots, this may be overkill
638 // let's leave it disabled in debug mode in any case
639 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
641 //#define CHECK_VERSION
644 // locate and open RADIANT_MAJOR and RADIANT_MINOR
645 qboolean bVerIsGood = true;
647 ver_file_name = g_strAppPath;
648 ver_file_name += "RADIANT_MAJOR";
649 FILE *ver_file = fopen (ver_file_name.GetBuffer(), "r");
654 fread(buf, 1, 10, ver_file);
655 // chomp it (the hard way)
657 while(buf[chomp] >= '0' && buf[chomp] <= '9')
660 if (strcmp(buf, RADIANT_MAJOR_VERSION))
662 Sys_Printf("ERROR: file RADIANT_MAJOR doesn't match ('%s')\n", buf);
668 Sys_Printf("ERROR: can't find RADIANT_MAJOR in '%s'\n", ver_file_name.GetBuffer());
671 ver_file_name = g_strAppPath;
672 ver_file_name += "RADIANT_MINOR";
673 ver_file = fopen (ver_file_name.GetBuffer(), "r");
678 fread(buf, 1, 10, ver_file);
679 // chomp it (the hard way)
681 while(buf[chomp] >= '0' && buf[chomp] <= '9')
684 if (strcmp(buf, RADIANT_MINOR_VERSION))
686 Sys_Printf("ERROR: file RADIANT_MINOR doesn't match ('%s')\n", buf);
692 Sys_Printf("ERROR: can't find RADIANT_MINOR in '%s'\n", ver_file_name.GetBuffer());
698 msg = "This editor binary (" RADIANT_VERSION ") doesn't match what the latest setup has configured in this directory\n";
699 msg += "Make sure you run the right/latest editor binary you installed\n";
700 msg += g_strAppPath; msg += "\n";
701 msg += "Check http://www.qeradiant.com/faq/index.cgi?file=219 for more information";
702 gtk_MessageBox(NULL, msg.GetBuffer(), "Radiant", MB_OK, "http://www.qeradiant.com/faq/index.cgi?file=219");
707 g_qeglobals.disable_ini = false;
711 if ( remove( g_pidFile.GetBuffer () ) == -1 ) {
713 msg = "WARNING: Could not delete "; msg += g_pidGameFile;
714 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
718 now the secondary game dependant .pid file
719 http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
721 g_pidGameFile = g_PrefsDlg.m_rc_path->str;
722 g_pidGameFile += "radiant-game.pid";
724 pid = fopen (g_pidGameFile.GetBuffer(), "r");
729 if (remove (g_pidGameFile.GetBuffer ()) == -1)
731 msg = "WARNING: Could not delete "; msg += g_pidGameFile;
732 gtk_MessageBox (NULL, msg, "Radiant", MB_OK | MB_ICONERROR );
735 msg = "Found the file ";
736 msg += g_pidGameFile;
737 msg += ".\nThis indicates that Radiant failed to load the last time it was run.\n"
738 "Choose YES to clean Radiant's registry settings and shut down Radiant.\n"
739 "WARNING: preferences will be lost if you choose YES.";
741 // in debug, never prompt to clean registry, turn console logging auto after a failed start
744 if (gtk_MessageBox (NULL, msg, "Radiant - Clean Registry?", MB_YESNO | MB_ICONQUESTION) == IDYES)
746 // remove the game prefs files
747 remove (g_PrefsDlg.m_inipath->str);
749 sprintf(buf, "%sSavedInfo.bin", g_PrefsDlg.m_rc_path->str);
751 // remove the global pref too
752 g_PrefsDlg.mGamesDialog.Reset();
753 gtk_MessageBox(NULL, "Cleaned registry settings, choose OK to close Radiant.\nThe next time Radiant runs it will use default settings.", "Radiant", MB_OK );
756 msg = "Logging console output to ";
757 msg += g_strTempPath;
758 msg += "radiant.log\nRefer to the log if Radiant fails to start again.";
760 gtk_MessageBox (NULL, msg, "Radiant - Console Log", MB_OK);
763 // force console logging on! (will go in prefs too)
764 g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
765 g_PrefsDlg.mGamesDialog.SavePrefs();
768 g_PrefsDlg.LoadPrefs();
772 // create one, will remove right after entering message loop
773 pid = fopen (g_pidGameFile.GetBuffer(), "w");
777 g_PrefsDlg.LoadPrefs();
779 #ifndef _DEBUG // I can't be arsed about that prompt in debug mode
780 // if console logging is on in the prefs, warn about performance hit
781 if (g_PrefsDlg.mGamesDialog.m_bLogConsole)
783 if (gtk_MessageBox (NULL, "Preferences indicate that console logging is on. This affects performance.\n"
784 "Turn it off?", "Radiant", MB_YESNO | MB_ICONQUESTION) == IDYES)
786 g_PrefsDlg.mGamesDialog.m_bLogConsole = false;
787 g_PrefsDlg.mGamesDialog.SavePrefs();
791 // toggle console logging if necessary
795 // FIXME http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
796 // we should search in g_strTempPath, then move over to look at g_strAppPath?
798 // fine tune the look of the app using a gtk rc file
799 // we try to load an RC file placed in the application directory
800 // build the full path
802 sRCFile = g_strAppPath;
803 sRCFile += "radiantgtkrc";
804 // we load that file with g_new in gtk_rc_parse_file (gtkrc.c), change the '/' into '\\'
805 pBuffer = (char *)sRCFile.GetBuffer();
806 for (i=0; i<sRCFile.GetLength(); i++)
813 // check the file exists
814 if (access(sRCFile.GetBuffer(), R_OK) != 0)
815 Sys_Printf("RC file %s not found\n", sRCFile.GetBuffer());
818 Sys_Printf ("Attemping to load RC file %s\n", sRCFile.GetBuffer());
819 gtk_rc_parse (sRCFile.GetBuffer());
827 if (!QGL_Init(libgl, ""))
829 Sys_FPrintf (SYS_ERR, "Failed to load OpenGL libraries\n");
834 #if defined (__linux__) || defined (__APPLE__)
835 if ((qglXQueryExtension == NULL) || (qglXQueryExtension(GDK_DISPLAY(),NULL,NULL) != True))
837 Sys_FPrintf (SYS_ERR, "glXQueryExtension failed\n");
843 // redirect Gtk warnings to the console
844 g_log_set_handler( "Gdk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
845 G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
846 g_log_set_handler( "Gtk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
847 G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, NULL);
849 // spog - creates new filters list for the first time
850 g_qeglobals.d_savedinfo.filters = NULL;
851 g_qeglobals.d_savedinfo.filters = FilterUpdate(g_qeglobals.d_savedinfo.filters);
853 g_pParentWnd = new MainFrame();
855 if ( g_PrefsDlg.m_bLoadLastMap && g_PrefsDlg.m_strLastMap.GetLength() > 0 ) {
856 Map_LoadFile(g_PrefsDlg.m_strLastMap.GetBuffer());
861 // load up shaders now that we have the map loaded
863 Texture_ShowStartupShaders();
866 gdk_window_raise(splash_screen->window);
867 gtk_window_set_transient_for( GTK_WINDOW( splash_screen ), GTK_WINDOW( g_pParentWnd->m_pWidget ) );
868 gtk_timeout_add( 1000, try_destroy_splash, NULL );
871 g_pParentWnd->GetSynapseServer().DumpActiveClients();
873 //++timo: temporary debug
874 g_pParentWnd->DoWatchBSP();
878 // close the log file if any
879 // NOTE: don't save prefs past this point!
880 g_PrefsDlg.mGamesDialog.m_bLogConsole = false;
881 // set the console window to NULL to avoid Sys_Printf crashing
882 g_qeglobals_gui.d_edit = NULL;
885 // NOTE TTimo not sure what this _exit(0) call is worth
886 // restricting it to linux build
893 // ydnar: quick and dirty fix, just make the buffer bigger
894 #define BIG_PATH_MAX 4096
896 // TTimo: decompose the BSP command into several steps so we can monitor them eventually
897 void QE_ExpandBspString (char *bspaction, GPtrArray *out_array, char *mapname)
901 char src[BIG_PATH_MAX];
902 char rsh[BIG_PATH_MAX];
903 char base[BIG_PATH_MAX];
905 strcpy(src, mapname);
907 in = strstr(src, "maps/");
910 in = strstr(src, "maps/");
927 ExtractFileName (mapname, base);
930 // this important step alters the map name to add fs_game
931 // NOTE: it used to add fs_basepath too
932 // the fs_basepath addition moved to being in the project file during the bug fixing rush
933 // but it may not have been the right thing to do
935 // HACK: halflife compiler tools don't support -fs_game
936 // HACK: neither does JKII/SoF2/ etc..
937 // do we use & have fs_game?
939 if (g_pGameDescription->mGameFile != "hl.game" &&
940 *ValueForKey(g_qeglobals.d_project_entity,"gamename") != '\0')
943 sprintf(src, "-fs_game %s \"%s\"", ValueForKey(g_qeglobals.d_project_entity,"gamename"), mapname);
947 sprintf(src, "\"%s\"", mapname);
952 QE_ConvertDOSToUnixName(src, src);
954 // initialise the first step
955 out = new char[BIG_PATH_MAX]; //% PATH_MAX
956 g_ptr_array_add( out_array, out );
958 in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
971 // we process these only if monitoring
972 if (g_PrefsDlg.m_bWatchBSP)
974 // -connect global option (the only global option so far anyway)
975 strcpy (tmp, " -connect 127.0.0.1:39000 ");
1002 out = new char[BIG_PATH_MAX]; //% PATH_MAX
1003 g_ptr_array_add( out_array, out );
1010 void FindReplace(CString& strContents, const char* pTag, const char* pValue)
1012 if (strcmp(pTag, pValue) == 0)
1014 for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
1016 int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
1017 CString strLeft = strContents.Left(nPos);
1018 CString strRight = strContents.Right(nRightLen);
1020 strLeft += strRight;
1021 strContents = strLeft;
1025 // save the map, deals with regioning
1026 void SaveWithRegion(char *name)
1028 strcpy (name, currentmap);
1031 // temporary cut the region to save regular map
1032 region_active = false;
1033 Map_SaveFile (name, false);
1034 region_active = true;
1035 StripExtension (name);
1036 strcat (name, ".reg");
1039 Map_SaveFile (name, region_active);
1042 void RunBsp (char *command)
1045 char batpath[BIG_PATH_MAX]; //% PATH_MAX
1046 char temppath[BIG_PATH_MAX]; //% PATH_MAX
1047 char name[BIG_PATH_MAX]; //% PATH_MAX
1048 char cWork[BIG_PATH_MAX]; //% PATH_MAX
1052 SetInspectorMode(W_CONSOLE);
1054 strcpy (temppath, g_strTempPath.GetBuffer ());
1056 SaveWithRegion(name);
1058 const char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd");
1061 CString strPath, strFile;
1063 ExtractPath_and_Filename(name, strPath, strFile);
1065 strncpy(cWork, strPath, 1024);
1066 strcat(cWork, strFile);
1069 strcpy(cWork, name);
1072 // get the array ready
1073 //++timo TODO: free the array, free the strings ourselves with delete[]
1074 sys = g_ptr_array_new();
1076 QE_ExpandBspString (command, sys, cWork);
1078 if (g_PrefsDlg.m_bWatchBSP)
1080 // grab the file name for engine running
1081 char *bspname = new char[1024];
1082 ExtractFileName( currentmap, bspname );
1083 StripExtension( bspname );
1084 g_pParentWnd->GetWatchBSP()->DoMonitoringLoop( sys, bspname );
1087 // write all the steps in a single BAT / .sh file and run it, don't bother monitoring it
1089 for (i=0; i < sys->len; i++ )
1091 strSys += (char *)g_ptr_array_index( sys, i);
1092 #ifdef _WIN32 // write temp\junk.txt in win32... NOTE: stops output to shell prompt window
1099 strSys += "junk.txt\"";
1104 #if defined (__linux__) || defined (__APPLE__)
1107 sprintf (batpath, "%sqe3bsp.sh", temppath);
1108 Sys_Printf("Writing the compile script to '%s'\n", batpath);
1109 Sys_Printf("The build output will be saved in '%sjunk.txt'\n", temppath);
1110 hFile = fopen(batpath, "w");
1112 Error ("Can't write to %s", batpath);
1113 fprintf (hFile, "#!/bin/sh \n\n");
1114 fprintf (hFile, strSys.GetBuffer());
1116 chmod (batpath, 0744);
1120 sprintf (batpath, "%sqe3bsp.bat", temppath);
1121 Sys_Printf("Writing the compile script to '%s'\n", batpath);
1122 Sys_Printf("The build output will be saved in '%sjunk.txt'\n", temppath);
1123 hFile = fopen(batpath, "w");
1125 Error ("Can't write to %s", batpath);
1126 fprintf (hFile, strSys.GetBuffer());
1130 Pointfile_Delete ();
1132 #if defined (__linux__) || defined (__APPLE__)
1140 Error ("CreateProcess failed");
1143 execlp (batpath, batpath, NULL);
1144 printf ("execlp error !");
1153 Sys_Printf ("Running bsp command...\n");
1154 Sys_Printf ("\n%s\n", strSys.GetBuffer());
1156 WinExec( batpath, SW_SHOWNORMAL );
1160 // yeah, do it .. but not now right before 1.1-TA-beta release
1161 Sys_Printf("TODO: erase GPtrArray\n");
1169 int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer )
1171 static PIXELFORMATDESCRIPTOR pfd = {
1172 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1173 1, // version number
1174 PFD_DRAW_TO_WINDOW | // support window
1175 PFD_SUPPORT_OPENGL | // support OpenGL
1176 PFD_DOUBLEBUFFER, // double buffered
1177 PFD_TYPE_RGBA, // RGBA type
1178 24, // 24-bit color depth
1179 0, 0, 0, 0, 0, 0, // color bits ignored
1180 0, // no alpha buffer
1181 0, // shift bit ignored
1182 0, // no accumulation buffer
1183 0, 0, 0, 0, // accum bits ignored
1185 0, // no stencil buffer
1186 0, // no auxiliary buffer
1187 PFD_MAIN_PLANE, // main layer
1189 0, 0, 0 // layer masks ignored
1191 int pixelformat = 0;
1197 if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
1201 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1202 FORMAT_MESSAGE_FROM_SYSTEM |
1203 FORMAT_MESSAGE_IGNORE_INSERTS,
1206 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
1211 Sys_FPrintf (SYS_WRN, "GetLastError: %s", lpMsgBuf);
1212 Error ("ChoosePixelFormat failed");
1215 if (!SetPixelFormat(hDC, pixelformat, &pfd))
1216 Error ("SetPixelFormat failed");