Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

Win_main.cpp (29415B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, 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.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 #include "stdafx.h"
     23 #include "qe3.h"
     24 #include <process.h>
     25 #include "mru.h"
     26 #include "entityw.h"
     27 #include "PrefsDlg.h"
     28 
     29 static HWND      s_hwndToolbar;
     30 
     31 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize);
     32 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize);
     33 
     34 static HWND CreateMyStatusWindow(HINSTANCE hInst);
     35 static HWND CreateToolBar(HINSTANCE hinst);
     36 
     37 extern void WXY_Print( void );
     38 
     39 /*
     40 ==============================================================================
     41 
     42   MENU
     43 
     44 ==============================================================================
     45 */
     46 
     47 void OpenDialog (void);
     48 void SaveAsDialog (bool bRegion);
     49 qboolean ConfirmModified (void);
     50 void  Select_Ungroup (void);
     51 
     52 void QE_ExpandBspString (char *bspaction, char *out, char *mapname, bool useTemps)
     53 {
     54 	char	*in;
     55 	char	src[2048];
     56 	char	rsh[2048];
     57 	char	base[2048];
     58 
     59 	strcpy(src, mapname);
     60 	strlwr(src);
     61 	in = strstr(src, "maps/");
     62 	if (!in)
     63 	{
     64 		in = strstr(src, "maps\\");
     65 	}
     66 	if (in)
     67 	{
     68 		in += 5;
     69 		strcpy(base, in);
     70 		in = base;
     71 		while (*in)
     72 		{
     73 			if (*in == '\\')
     74 			{
     75 				*in = '/';
     76 			}
     77 			in++;
     78 		}
     79 	}
     80 	else
     81 	{
     82 		ExtractFileName (mapname, base);
     83 	}
     84 
     85   if (useTemps) {
     86     CString str;
     87     CString strExt = "map";
     88     if ( strstr(mapname, ".reg") ) {
     89       strExt = "reg";
     90     }
     91     str.Format("%s/maps/%i.%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), ::GetTickCount(), strExt);
     92     CopyFile(mapname, str, FALSE);
     93 	  sprintf (src, "-tempname %s %s/maps/%s", str, ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
     94   } else {
     95 	  sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
     96   }
     97 	strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd"));
     98 
     99   QE_ConvertDOSToUnixName(src, src);
    100 
    101 	in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
    102 	while (*in)
    103 	{
    104 		if (in[0] == '!')
    105 		{
    106 			strcpy (out, rsh);
    107 			out += strlen(rsh);
    108 			in++;
    109 			continue;
    110 		}
    111 		if (in[0] == '$')
    112 		{
    113 			strcpy (out, src);
    114 			out += strlen(src);
    115 			in++;
    116 			continue;
    117 		}
    118 		if (in[0] == '@')
    119 		{
    120 			*out++ = '"';
    121 			in++;
    122 			continue;
    123 		}
    124 		*out++ = *in++;
    125 	}
    126 	*out = 0;
    127 }
    128 
    129 void FindReplace(CString& strContents, const char* pTag, const char* pValue)
    130 {
    131   if (strcmp(pTag, pValue) == 0)
    132     return;
    133   for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
    134   {
    135     int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
    136     CString strLeft = strContents.Left(nPos);
    137     CString strRight = strContents.Right(nRightLen);
    138     strLeft += pValue;
    139     strLeft += strRight;
    140     strContents = strLeft;
    141   }
    142 }
    143 
    144 
    145 
    146 HWND g_hWnd = NULL;
    147 HANDLE g_hToolThread = NULL;
    148 CString g_strParams;
    149 
    150 UINT ToolThread(LPVOID pParam)
    151 {
    152   char* p = reinterpret_cast<char*>(pParam);
    153   if (g_PrefsDlg.m_bPAK)
    154     RunTools(p, g_hWnd, g_PrefsDlg.m_strPAKFile);
    155   else
    156     RunTools(p, g_hWnd, "");
    157   g_hToolThread = NULL;
    158   delete []p;
    159   return 0;
    160 }
    161 
    162 void ThreadTools(char* p)
    163 {
    164   CWinThread* pThread = AfxBeginThread(ToolThread, reinterpret_cast<LPVOID>(p));
    165   g_hToolThread = pThread->m_hThread;
    166 }
    167 
    168 HWND g_hwndFoundIt = NULL;
    169 
    170 BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
    171   char buff[1024];
    172   const char* p = reinterpret_cast<const char*>(lParam);
    173   GetWindowText(hwnd, buff, 1024);
    174   if (!strcmpi(p, buff)) {
    175     g_hwndFoundIt = hwnd;
    176     return 1;
    177   }
    178   return 1;
    179 }
    180 
    181 
    182 HWND FindAnyWindow(const char *pTitle) {
    183   HWND hwndDesktop = GetDesktopWindow();
    184   g_hwndFoundIt = NULL;
    185   if ( hwndDesktop ) {
    186     EnumChildWindows(hwndDesktop, (WNDENUMPROC)EnumChildProc, reinterpret_cast<LPARAM>(pTitle));
    187   }
    188   return g_hwndFoundIt;
    189 }
    190 
    191 
    192 const UINT wm_AddCommand = RegisterWindowMessage( "Q3MPC_AddCommand" );
    193 
    194 CTime g_tBegin;
    195 void RunBsp (char *command)
    196 {
    197 	char	sys[2048];
    198 	char	batpath[2048];
    199 	char	outputpath[2048];
    200 	char	temppath[1024];
    201 	char	name[2048];
    202 	char	cWork[2048];
    203 	FILE	*hFile;
    204 	BOOL	ret;
    205 	PROCESS_INFORMATION ProcessInformation;
    206 	STARTUPINFO	startupinfo;
    207   HWND hwndPClient = NULL;
    208 
    209   g_hWnd = g_pParentWnd->GetSafeHwnd();
    210 	SetInspectorMode(W_CONSOLE);
    211   g_tBegin = CTime::GetCurrentTime();
    212 
    213 	
    214 	DWORD	dwExitcode;
    215   ret = GetExitCodeProcess (g_hToolThread, &dwExitcode);
    216   if (dwExitcode != STILL_ACTIVE)
    217     g_hToolThread = NULL;
    218 
    219 	if (bsp_process || g_hToolThread)
    220 	{
    221 		Sys_Printf ("BSP is still going...\n");
    222 		return;
    223 	}
    224 
    225   outputpath[0] = '\0';
    226 	GetTempPath(512, temppath);
    227 
    228   CString strOutFile = temppath;
    229   AddSlash(strOutFile);
    230   strOutFile += "junk.txt";
    231 
    232 	sprintf (outputpath, " >>%s\r\n", strOutFile);
    233 
    234   strcpy (name, currentmap);
    235 	if (region_active)
    236 	{
    237 		Map_SaveFile (name, false);
    238 		StripExtension (name);
    239 		strcat (name, ".reg");
    240 	}
    241 
    242 	Map_SaveFile (name, region_active);
    243 
    244   // FIXME: this code just gets worse and worse
    245   CString strPath, strFile;
    246 
    247   char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd");
    248   if (rsh == NULL)
    249   {
    250     ExtractPath_and_Filename(name, strPath, strFile);
    251     AddSlash(strPath);
    252     BuildShortPathName(strPath, cWork, 1024);
    253     strcat(cWork, strFile);
    254   }
    255   else
    256   {
    257     strcpy(cWork, name);
    258   }
    259 
    260   hwndPClient = FindWindow(NULL, "Q3Map Process Client");
    261   if ( hwndPClient == NULL ) {
    262     hwndPClient = FindAnyWindow("Q3Map Process Client");
    263   }
    264 
    265   Sys_Printf("Window info for Process Client %i\n", reinterpret_cast<int>(hwndPClient));
    266 
    267   bool processServer = (rsh && strlen(rsh) > 0 && hwndPClient);
    268 
    269   QE_ExpandBspString (command, sys, cWork, processServer);
    270 
    271   // if we can find the q3map process server running 
    272   // we will submit maps to it instead of via createprocess
    273   //
    274   if (processServer)
    275   {
    276     CString str;
    277     char cBuff[2048];
    278     char *pStart = sys;
    279     char *pEnd = strstr(pStart, "&&");
    280     while (pEnd)
    281     {
    282       int nLen = pEnd-pStart-1;
    283       strncpy(cBuff, pStart, nLen);
    284       cBuff[nLen] = 0;
    285       str = cBuff;
    286       FindReplace(str, rsh, "");
    287       str.TrimLeft(' ');
    288       str.TrimRight(' ');
    289       ATOM a = GlobalAddAtom(str);
    290       PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
    291       pStart = pEnd+2;
    292       pEnd = strstr(pStart, "&&");
    293     }
    294     str = pStart;
    295     FindReplace(str, rsh, "");
    296     str.TrimLeft(' ');
    297     str.TrimRight(' ');
    298     ATOM a = GlobalAddAtom(str);
    299     PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
    300     Sys_Printf("Commands sent to Q3Map Process Client\n");
    301     return;
    302   }
    303 
    304   CString strSys = sys;
    305 
    306   FindReplace(strSys, "&&", outputpath);
    307   strcpy(sys, strSys);
    308   strcat(sys, outputpath);
    309 
    310   if (g_PrefsDlg.m_bInternalBSP)
    311   {
    312     g_tBegin = CTime::GetCurrentTime();
    313     strSys.MakeLower();
    314     char* p = new char[strSys.GetLength()+1];
    315     strcpy(p, strSys.GetBuffer(0));
    316     ThreadTools(p);
    317   }
    318   else
    319   {
    320 	  Sys_ClearPrintf ();
    321 	  Sys_Printf ("==================\nRunning bsp command...\n");
    322 	  Sys_Printf ("\n%s\n", sys);
    323 
    324 	  //++timo removed the old way BSP commands .. dumping to junk.txt doesn't work on my win98 box
    325 	  // FIXME : will most likely break Quake2 BSP commands, is fitted to a one-lined sys command
    326 	  //
    327 	  // write qe3bsp.bat
    328 	  //
    329 
    330 	  sprintf (batpath, "%sqe3bsp.bat", temppath);
    331 	  hFile = fopen(batpath, "w");
    332 	  if (!hFile)
    333 		  Error ("Can't write to %s", batpath);
    334 	  fprintf (hFile, sys);
    335 	  fclose (hFile);
    336 
    337 	  Pointfile_Delete ();
    338 
    339 	  // delete junk.txt file
    340 	  remove(strOutFile);
    341 
    342 	  GetStartupInfo (&startupinfo);
    343 
    344 	  ret = CreateProcess(
    345 		  batpath,
    346 		  NULL,
    347 		  NULL,
    348 		  NULL,
    349 		  FALSE,
    350 		  0,
    351 		  NULL,
    352 		  NULL,
    353 		  &startupinfo,
    354 		  &ProcessInformation
    355 		  );
    356 
    357 	  if (!ret)
    358 		  Error ("CreateProcess failed");
    359 
    360 	  bsp_process = ProcessInformation.hProcess;
    361 
    362 	  Sleep (100);	// give the new process a chance to open it's window
    363 
    364 	  BringWindowToTop( g_qeglobals.d_hwndMain );	// pop us back on top
    365 #if 0
    366 	  //
    367 	  // write qe3bsp.bat
    368 	  //
    369 	  sprintf (batpath, "%sqe3bsp.bat", temppath);
    370 	  hFile = fopen(batpath, "w");
    371 	  if (!hFile)
    372 		  Error ("Can't write to %s", batpath);
    373 	  fprintf (hFile, sys);
    374 	  fclose (hFile);
    375 
    376 	  //
    377 	  // write qe3bsp2.bat
    378 	  //
    379 	  sprintf (batpath, "%sqe3bsp2.bat", temppath);
    380 	  hFile = fopen(batpath, "w");
    381 	  if (!hFile)
    382 		  Error ("Can't write to %s", batpath);
    383 	  fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath);
    384 	  fclose (hFile);
    385 
    386 	  Pointfile_Delete ();
    387 
    388 	  GetStartupInfo (&startupinfo);
    389 
    390 	  ret = CreateProcess(
    391       batpath,		// pointer to name of executable module 
    392       NULL,			// pointer to command line string
    393       NULL,			// pointer to process security attributes 
    394       NULL,			// pointer to thread security attributes 
    395       FALSE,			// handle inheritance flag 
    396       0 /*DETACHED_PROCESS*/,		// creation flags
    397       NULL,			// pointer to new environment block 
    398       NULL,			// pointer to current directory name 
    399       &startupinfo,	// pointer to STARTUPINFO 
    400       &ProcessInformation 	// pointer to PROCESS_INFORMATION  
    401      );
    402 
    403 	  if (!ret)
    404 		  Error ("CreateProcess failed");
    405 
    406 	  bsp_process = ProcessInformation.hProcess;
    407 
    408 	  Sleep (100);	// give the new process a chance to open it's window
    409 
    410 	  //BringWindowToTop( g_qeglobals.d_hwndMain );	// pop us back on top
    411 	  //SetFocus (g_qeglobals.d_hwndCamera);
    412 #endif
    413   }
    414 }
    415 
    416 void DLLBuildDone()
    417 {
    418   g_hToolThread = NULL;
    419   CTime tEnd = CTime::GetCurrentTime();
    420   CTimeSpan tElapsed = tEnd - g_tBegin;
    421   CString strElapsed;
    422   strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds());
    423 	Sys_Printf(strElapsed.GetBuffer(0));
    424 	Pointfile_Check();
    425 
    426   if (g_PrefsDlg.m_bRunQuake == TRUE)
    427   {
    428     char cCurDir[1024];
    429     GetCurrentDirectory(1024, cCurDir);
    430     CString strExePath = g_PrefsDlg.m_strQuake2;
    431     CString strOrgPath;
    432     CString strOrgFile;
    433     ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
    434     if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map
    435     {
    436 	    CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
    437       strExePath += " +set game ";
    438       strExePath += strBasePath;
    439       WinExec(strExePath, SW_SHOW);
    440     }
    441     else
    442     {
    443       CString strCopyPath = strExePath;
    444       char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1);
    445       pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0';
    446       strCopyPath.ReleaseBuffer();
    447       SetCurrentDirectory(strCopyPath);
    448       CString strOrgPath;
    449       CString strOrgFile;
    450       ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
    451       AddSlash(strCopyPath);
    452       FindReplace(strOrgFile, ".map", ".bsp");
    453       strCopyPath += "\\baseq2\\maps\\";
    454       strCopyPath += strOrgFile;
    455       AddSlash(strOrgPath);
    456       strOrgPath += strOrgFile;
    457       bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0);
    458       if (!bRun)
    459         bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE);
    460       if (bRun)
    461       {
    462         FindReplace(strOrgFile, ".bsp", "");
    463         strExePath += " +map ";
    464         strExePath += strOrgFile;
    465         WinExec(strExePath, SW_SHOW);
    466       }
    467     }
    468     SetCurrentDirectory(cCurDir);
    469   }
    470 
    471 }
    472 
    473 /*
    474 =============
    475 DoColor
    476 
    477 =============
    478 */
    479 
    480 class CMyColorDialog : public CColorDialog 
    481 {
    482   DECLARE_DYNCREATE(CMyColorDialog);
    483      // Construction
    484 public:
    485      CMyColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd*
    486 pParentWnd = NULL );
    487      // Statics
    488 protected:
    489      enum { NCUSTCOLORS = 16 };
    490      static COLORREF c_CustColors[NCUSTCOLORS];
    491      static COLORREF c_LastCustColors[NCUSTCOLORS];
    492      static bool c_NeedToInitCustColors;
    493 protected:
    494      static void InitCustColors();
    495      static void SaveCustColors();
    496      // Dialog Data
    497 protected:
    498      //{{AFX_DATA(CMyColorDialog)
    499      //}}AFX_DATA
    500      // Overrides
    501 protected:
    502      // ClassWizard generate virtual function overrides
    503      //{{AFX_VIRTUAL(CMyColorDialog)
    504 public:
    505      virtual int DoModal();
    506 protected:
    507      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    508      //}}AFX_VIRTUAL
    509      // Implementation
    510 protected:
    511      // Generated message map functions
    512      //{{AFX_MSG(CMyColorDialog)
    513      //}}AFX_MSG
    514      DECLARE_MESSAGE_MAP()
    515 };
    516 
    517 IMPLEMENT_DYNCREATE(CMyColorDialog, CColorDialog)
    518 
    519 bool CMyColorDialog::c_NeedToInitCustColors = true;
    520 COLORREF CMyColorDialog::c_CustColors[];
    521 COLORREF CMyColorDialog::c_LastCustColors[];
    522 
    523 #define SECTION _T("Custom Colors")
    524 
    525 void CMyColorDialog::InitCustColors() {
    526      for (int i = 0; i < NCUSTCOLORS; i++) {
    527           CString entry; entry.Format("%d",i);
    528           c_LastCustColors[i] = c_CustColors[i] =
    529 		::AfxGetApp()->GetProfileInt(SECTION,entry,RGB(255,255,255));
    530      }
    531      c_NeedToInitCustColors= false;
    532 }
    533 
    534 void CMyColorDialog::SaveCustColors() {
    535      for (int i = 0; i < NCUSTCOLORS; i++) {
    536           if (c_LastCustColors[i] != c_CustColors[i]) {
    537                CString entry; entry.Format("%d",i);
    538                if (c_CustColors[i] == RGB(255,255,255)) {
    539                     ::AfxGetApp()->WriteProfileString(SECTION,entry,NULL);
    540                } else {
    541                     ::AfxGetApp()->WriteProfileInt(SECTION, entry,c_CustColors[i]);
    542                }
    543                c_LastCustColors[i] = c_CustColors[i];
    544           }
    545      }
    546 }
    547 
    548 CMyColorDialog::CMyColorDialog( COLORREF clrInit, DWORD dwFlags, 
    549 		CWnd* pParentWnd) : CColorDialog(clrInit,dwFlags,pParentWnd)
    550 {
    551      //{{AFX_DATA_INIT(CMyColorDialog)
    552      //}}AFX_DATA_INIT
    553      if (c_NeedToInitCustColors) {
    554           InitCustColors();
    555      }
    556      m_cc.lpCustColors = c_CustColors;
    557 }
    558 
    559 int CMyColorDialog::DoModal() {
    560      int code = CColorDialog::DoModal();
    561      SaveCustColors();
    562      return code;
    563 }
    564 
    565 void CMyColorDialog::DoDataExchange(CDataExchange* pDX) {
    566      // overridden (calls this base class)
    567      CColorDialog::DoDataExchange(pDX);
    568      //{{AFX_DATA_MAP(CMyColorDialog)
    569      //}}AFX_DATA_MAP
    570 }
    571 
    572 BEGIN_MESSAGE_MAP(CMyColorDialog, CColorDialog)
    573 //{{AFX_MSG_MAP(CMyColorDialog)
    574 //}}AFX_MSG_MAP
    575 END_MESSAGE_MAP()
    576 
    577 void DoNewColor(int* i1, int* i2, int* i3)
    578 {
    579 	COLORREF cr = (*i1) +
    580                 ((*i2) <<8) +
    581 		            ((*i3) <<16);
    582   CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
    583   if (dlg.DoModal() == IDOK)
    584   {
    585 	  *i1 = (dlg.m_cc.rgbResult & 255);
    586 	  *i2 = ((dlg.m_cc.rgbResult >> 8) & 255);
    587 	  *i3 = ((dlg.m_cc.rgbResult >> 16) & 255);
    588   }
    589 
    590 }
    591 
    592 
    593 qboolean DoColor(int iIndex)
    594 {
    595 
    596 	COLORREF cr = (int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) +
    597                 (((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) +
    598 		            (((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16);
    599   CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
    600   if (dlg.DoModal() == IDOK)
    601   {
    602 	  g_qeglobals.d_savedinfo.colors[iIndex][0] = (dlg.m_cc.rgbResult&255)/255.0;
    603 	  g_qeglobals.d_savedinfo.colors[iIndex][1] = ((dlg.m_cc.rgbResult>>8)&255)/255.0;
    604 	  g_qeglobals.d_savedinfo.colors[iIndex][2] = ((dlg.m_cc.rgbResult>>16)&255)/255.0;
    605 
    606 	  /* 
    607 	  ** scale colors so that at least one component is at 1.0F 
    608 	  ** if this is meant to select an entity color
    609 	  */
    610 	  if ( iIndex == COLOR_ENTITY )
    611 	  {
    612 		  float largest = 0.0F;
    613 
    614 		  if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest )
    615 			  largest = g_qeglobals.d_savedinfo.colors[iIndex][0];
    616 		  if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest )
    617 			  largest = g_qeglobals.d_savedinfo.colors[iIndex][1];
    618 		  if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest )
    619 			  largest = g_qeglobals.d_savedinfo.colors[iIndex][2];
    620 
    621 		  if ( largest == 0.0F )
    622 		  {
    623 			  g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F;
    624 			  g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F;
    625 			  g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F;
    626 		  }
    627 		  else
    628 		  {
    629 			  float scaler = 1.0F / largest;
    630 
    631 			  g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler;
    632 			  g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler;
    633 			  g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler;
    634 		  }
    635 	  }
    636 
    637 	  Sys_UpdateWindows (W_ALL);
    638 	  return true;
    639   }
    640   else return false;
    641 
    642 }
    643 
    644 
    645 /* Copied from MSDN */
    646 
    647 BOOL DoMru(HWND hWnd,WORD wId)
    648 {
    649 	char szFileName[128];
    650 	OFSTRUCT of;
    651 	BOOL fExist;
    652 
    653 	GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName));
    654 
    655 	// Test if the file exists.
    656 
    657 	fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR;
    658 
    659 	if (fExist) {
    660 
    661 		// Place the file on the top of MRU.
    662 		AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName);
    663 
    664 		// Now perform opening this file !!!
    665 		Map_LoadFile (szFileName);	
    666 	}
    667 	else
    668 		// Remove the file on MRU.
    669 		DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE);
    670 
    671 	// Refresh the File menu.
    672 	PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0),
    673 			ID_FILE_EXIT);
    674 
    675 	return fExist;
    676 }
    677 
    678 
    679 
    680 /*
    681 ==============
    682 Main_Create
    683 ==============
    684 */
    685 
    686 void MFCCreate (HINSTANCE hInstance)
    687 {
    688 	HMENU hMenu = NULL;
    689 	int i = sizeof(g_qeglobals.d_savedinfo);
    690   long l = i;
    691 
    692   g_qeglobals.d_savedinfo.exclude |= (EXCLUDE_HINT | EXCLUDE_CLIP);
    693 	LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
    694 
    695   int nOldSize = g_qeglobals.d_savedinfo.iSize;
    696 	if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo))
    697 	{
    698 		// fill in new defaults
    699 		g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo);
    700 		g_qeglobals.d_savedinfo.fGamma = 1.0;
    701 		g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_BILINEARMIPMAP;
    702     g_qeglobals.d_savedinfo.m_nTextureTweak = 1;
    703   
    704 		//g_qeglobals.d_savedinfo.exclude = INCLUDE_EASY | INCLUDE_NORMAL | INCLUDE_HARD | INCLUDE_DEATHMATCH;
    705 		g_qeglobals.d_savedinfo.show_coordinates = true;
    706 		g_qeglobals.d_savedinfo.show_names       = false;
    707 
    708 		for (i=0 ; i<3 ; i++)
    709 		{
    710 			g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
    711 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
    712 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75;
    713 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
    714 			g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
    715 		}
    716 
    717 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
    718 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
    719 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
    720 
    721 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0;
    722 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0;
    723 		g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0;
    724 
    725 		g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
    726 		g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
    727 		g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
    728 
    729 		g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
    730 		g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
    731 		g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
    732 
    733 		g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0;
    734 		g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0;
    735 		g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0;
    736 
    737 		g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5;
    738 		g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0;
    739 		g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75;
    740 
    741 
    742     // old size was smaller, reload original prefs
    743     if (nOldSize < sizeof(g_qeglobals.d_savedinfo))
    744     {
    745       long l = nOldSize;
    746 	    LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
    747     }
    748 
    749 	}
    750 	if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 )
    751 	{
    752 		// by default all of these are checked because that's how they're defined in the menu editor
    753 		if ( !g_qeglobals.d_savedinfo.show_names )
    754 			CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED );
    755 		if ( !g_qeglobals.d_savedinfo.show_coordinates )
    756 			CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED );
    757 
    758 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS )
    759 			CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
    760 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT )
    761 			CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED );
    762 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS )
    763 			CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
    764 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER )
    765 			CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
    766 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD )
    767 			CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
    768 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP )
    769 			CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
    770 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT )
    771 			CheckMenuItem( hMenu, ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED );
    772 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK )
    773 			CheckMenuItem( hMenu, ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED );
    774 	}
    775 
    776 }
    777 
    778 
    779 /*
    780 =============================================================
    781 
    782 REGISTRY INFO
    783 
    784 =============================================================
    785 */
    786 
    787 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize)
    788 {
    789 	LONG lres;
    790 	DWORD dwDisp;
    791 	HKEY  hKeyId;
    792 
    793 	if (g_qeglobals.use_ini)
    794 	{
    795 		lres = RegCreateKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, NULL,
    796 			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
    797 	}
    798 	else
    799 	{
    800 		lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, NULL, 
    801 				REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
    802 	}
    803     
    804 	if (lres != ERROR_SUCCESS)
    805 		return FALSE;
    806 
    807 	lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, (unsigned char*)pvBuf, lSize);
    808     
    809 	RegCloseKey(hKeyId);
    810 
    811 	if (lres != ERROR_SUCCESS)
    812 		return FALSE;
    813 
    814 	return TRUE;
    815 }
    816 
    817 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize)
    818 {
    819 	HKEY  hKey;
    820 	long lres, lType, lSize;
    821 
    822 	if (plSize == NULL)
    823 		plSize = &lSize;
    824 
    825 	if (g_qeglobals.use_ini)
    826 	{
    827 		lres = RegOpenKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, KEY_READ, &hKey);
    828 	}
    829 	else
    830 	{
    831 		lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, KEY_READ, &hKey);
    832   }
    833 
    834 	lres = RegQueryValueEx(hKey, pszName, NULL, (unsigned long*)&lType, (unsigned char*)pvBuf, (unsigned long*)plSize);
    835 
    836 	RegCloseKey(hKey);
    837 
    838 	if (lres != ERROR_SUCCESS)
    839 	{
    840 #ifdef _DEBUG
    841 		char Message[1024];
    842 		FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, lres, 0, &(Message[0]), 1024, NULL );
    843 		Sys_Printf( "WARNING: RegQueryValueEx failed in LoadRegistryInfo for %s : %s", pszName, Message );
    844 #endif
    845 		return FALSE;
    846 	}
    847 
    848 	return TRUE;
    849 }
    850 
    851 BOOL SaveWindowState(HWND hWnd, const char *pszName)
    852 {
    853 	RECT rc;
    854 	GetWindowRect(hWnd, &rc);
    855 	if (hWnd != g_qeglobals.d_hwndMain) // && g_pParentWnd->CurrentStyle() == QR_QE4)
    856   {
    857     if (::GetParent(hWnd) != g_qeglobals.d_hwndMain)
    858     {
    859       ::SetParent(hWnd, g_qeglobals.d_hwndMain);
    860     }
    861 		MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2);
    862 
    863   }
    864 	BOOL b = SaveRegistryInfo(pszName, &rc, sizeof(rc));
    865   return b;
    866 }
    867 
    868 
    869 BOOL LoadWindowState(HWND hWnd, const char *pszName)
    870 {
    871 	RECT rc;
    872   LONG lSize = sizeof(rc);
    873 
    874 	if (LoadRegistryInfo(pszName, &rc, &lSize))
    875 	{
    876 		if (rc.left < 0)
    877 			rc.left = 0;
    878 		if (rc.top < 0)
    879 			rc.top = 0;
    880 		if (rc.right < rc.left + 16)
    881 			rc.right = rc.left + 16;
    882 		if (rc.bottom < rc.top + 16)
    883 			rc.bottom = rc.top + 16;
    884 
    885 		MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, 
    886 				rc.bottom - rc.top, FALSE);
    887 		return TRUE;
    888 	}
    889 
    890 	return FALSE;
    891 }
    892 
    893 /*
    894 ===============================================================
    895 
    896   STATUS WINDOW
    897 
    898 ===============================================================
    899 */
    900 
    901 void Sys_UpdateStatusBar( void )
    902 {
    903 	extern int   g_numbrushes, g_numentities;
    904 
    905 	char numbrushbuffer[100]="";
    906 
    907 	sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
    908   g_pParentWnd->SetStatusText(2, numbrushbuffer);
    909 	//Sys_Status( numbrushbuffer, 2 );
    910 }
    911 
    912 void Sys_Status(const char *psz, int part )
    913 {
    914 	SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz);
    915 }
    916 
    917 static HWND CreateMyStatusWindow(HINSTANCE hInst)
    918 {
    919 	HWND hWnd;
    920 	int partsize[3] = { 300, 1100, -1 };
    921 
    922 	hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles
    923             STATUSCLASSNAME,                 // status bar
    924             "",                              // no text 
    925             WS_CHILD | WS_BORDER | WS_VISIBLE,  // styles
    926             -100, -100, 10, 10,              // x, y, cx, cy
    927             g_qeglobals.d_hwndMain,          // parent window
    928             (HMENU)100,                      // window ID
    929             hInst,                           // instance
    930             NULL);							 // window data
    931 
    932 	SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize );
    933     
    934 	return hWnd;
    935 }
    936 
    937 //==============================================================
    938 
    939 #define NUMBUTTONS 15
    940 HWND CreateToolBar(HINSTANCE hinst)
    941 { 
    942     HWND hwndTB; 
    943     TBADDBITMAP tbab; 
    944     TBBUTTON tbb[NUMBUTTONS]; 
    945     
    946      // Ensure that the common control DLL is loaded. 
    947 
    948     InitCommonControls(); 
    949  
    950     // Create a toolbar that the user can customize and that has a 
    951     // tooltip associated with it. 
    952 
    953     hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL, 
    954         WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER, 
    955         0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL); 
    956  
    957     // Send the TB_BUTTONSTRUCTSIZE message, which is required for 
    958     // backward compatibility. 
    959 
    960     SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
    961  
    962     // Add the bitmap containing button images to the toolbar. 
    963 
    964     tbab.hInst = hinst; 
    965     tbab.nID   = IDR_TOOLBAR1; 
    966     SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab); 
    967  
    968     // Fill the TBBUTTON array with button information, and add the 
    969     // buttons to the toolbar. 
    970 
    971     tbb[0].iBitmap = 0; 
    972     tbb[0].idCommand = ID_BRUSH_FLIPX; 
    973     tbb[0].fsState = TBSTATE_ENABLED; 
    974     tbb[0].fsStyle = TBSTYLE_BUTTON; 
    975     tbb[0].dwData = 0; 
    976     tbb[0].iString = 0; 
    977  
    978     tbb[1].iBitmap = 2; 
    979     tbb[1].idCommand = ID_BRUSH_FLIPY; 
    980     tbb[1].fsState = TBSTATE_ENABLED; 
    981     tbb[1].fsStyle = TBSTYLE_BUTTON; 
    982     tbb[1].dwData = 0; 
    983     tbb[1].iString = 0; 
    984  
    985     tbb[2].iBitmap = 4; 
    986     tbb[2].idCommand = ID_BRUSH_FLIPZ; 
    987     tbb[2].fsState = TBSTATE_ENABLED;
    988     tbb[2].fsStyle = TBSTYLE_BUTTON; 
    989     tbb[2].dwData = 0; 
    990     tbb[2].iString = 0; 
    991  
    992     tbb[3].iBitmap = 1; 
    993     tbb[3].idCommand = ID_BRUSH_ROTATEX; 
    994     tbb[3].fsState = TBSTATE_ENABLED; 
    995     tbb[3].fsStyle = TBSTYLE_BUTTON; 
    996     tbb[3].dwData = 0; 
    997     tbb[3].iString = 0; 
    998  
    999     tbb[4].iBitmap = 3; 
   1000     tbb[4].idCommand = ID_BRUSH_ROTATEY; 
   1001     tbb[4].fsState = TBSTATE_ENABLED; 
   1002     tbb[4].fsStyle = TBSTYLE_BUTTON; 
   1003     tbb[4].dwData = 0; 
   1004     tbb[4].iString = 0; 
   1005 
   1006     tbb[5].iBitmap = 5; 
   1007     tbb[5].idCommand = ID_BRUSH_ROTATEZ; 
   1008     tbb[5].fsState = TBSTATE_ENABLED; 
   1009     tbb[5].fsStyle = TBSTYLE_BUTTON; 
   1010     tbb[5].dwData = 0; 
   1011     tbb[5].iString = 0; 
   1012 
   1013     tbb[6].iBitmap = 6; 
   1014     tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL; 
   1015     tbb[6].fsState = TBSTATE_ENABLED; 
   1016     tbb[6].fsStyle = TBSTYLE_BUTTON; 
   1017     tbb[6].dwData = 0; 
   1018     tbb[6].iString = 0; 
   1019 
   1020     tbb[7].iBitmap = 7; 
   1021     tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING; 
   1022     tbb[7].fsState = TBSTATE_ENABLED; 
   1023     tbb[7].fsStyle = TBSTYLE_BUTTON; 
   1024     tbb[7].dwData = 0; 
   1025     tbb[7].iString = 0; 
   1026 
   1027     tbb[8].iBitmap = 8; 
   1028     tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL; 
   1029     tbb[8].fsState = TBSTATE_ENABLED; 
   1030     tbb[8].fsStyle = TBSTYLE_BUTTON; 
   1031     tbb[8].dwData = 0; 
   1032     tbb[8].iString = 0; 
   1033 
   1034 
   1035     tbb[9].iBitmap = 9; 
   1036     tbb[9].idCommand = ID_SELECTION_SELECTINSIDE; 
   1037     tbb[9].fsState = TBSTATE_ENABLED; 
   1038     tbb[9].fsStyle = TBSTYLE_BUTTON; 
   1039     tbb[9].dwData = 0; 
   1040     tbb[9].iString = 0; 
   1041 
   1042     tbb[10].iBitmap = 10; 
   1043     tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT; 
   1044     tbb[10].fsState = TBSTATE_ENABLED; 
   1045     tbb[10].fsStyle = TBSTYLE_BUTTON; 
   1046     tbb[10].dwData = 0; 
   1047     tbb[10].iString = 0; 
   1048 
   1049 
   1050     tbb[11].iBitmap = 11;
   1051     tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW; 
   1052     tbb[11].fsState = TBSTATE_ENABLED; 
   1053     tbb[11].fsStyle = TBSTYLE_BUTTON; 
   1054     tbb[11].dwData = 0; 
   1055     tbb[11].iString = 0; 
   1056 
   1057     tbb[12].iBitmap = 12;
   1058     tbb[12].idCommand = ID_TEXTURES_WIREFRAME; 
   1059     tbb[12].fsState = TBSTATE_ENABLED; 
   1060     tbb[12].fsStyle = TBSTYLE_BUTTON; 
   1061     tbb[12].dwData = 0; 
   1062     tbb[12].iString = 0; 
   1063 
   1064     tbb[13].iBitmap = 13;
   1065     tbb[13].idCommand = ID_TEXTURES_FLATSHADE; 
   1066     tbb[13].fsState = TBSTATE_ENABLED; 
   1067     tbb[13].fsStyle = TBSTYLE_BUTTON; 
   1068     tbb[13].dwData = 0; 
   1069     tbb[13].iString = 0; 
   1070 
   1071     tbb[14].iBitmap = 14;
   1072     tbb[14].idCommand = ID_VIEW_TRILINEAR; 
   1073     tbb[14].fsState = TBSTATE_ENABLED; 
   1074     tbb[14].fsStyle = TBSTYLE_BUTTON; 
   1075     tbb[14].dwData = 0; 
   1076     tbb[14].iString = 0; 
   1077 
   1078     SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS,
   1079         (LPARAM) (LPTBBUTTON) &tbb); 
   1080  
   1081     ShowWindow(hwndTB, SW_SHOW); 
   1082 
   1083     return hwndTB; 
   1084 } 
   1085