Win_main.cpp 29 KB

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