WIN_QE3.CPP (17589B)
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 "mru.h" 25 #include "PrefsDlg.h" 26 27 //////////////////////////////////////////////////////////////////////////// 28 // BSP frontend plugin 29 // global flag for BSP frontend plugin is g_qeglobals.bBSPFrontendPlugin 30 _QERPlugBSPFrontendTable g_BSPFrontendTable; 31 CStringArray g_BSPFrontendCommands; 32 33 extern CEdit* g_pEdit; 34 35 int screen_width; 36 int screen_height; 37 qboolean have_quit; 38 39 int update_bits; 40 41 HANDLE bsp_process; 42 43 //=========================================== 44 45 void Sys_MarkMapModified (void) 46 { 47 char title[1024]; 48 49 if (modified != 1) 50 { 51 modified = true; // mark the map as changed 52 sprintf (title, "%s *", currentmap); 53 54 QE_ConvertDOSToUnixName( title, title ); 55 Sys_SetTitle (title); 56 } 57 } 58 59 60 void Sys_SetTitle (char *text) 61 { 62 SetWindowText (g_qeglobals.d_hwndMain, text); 63 } 64 65 HCURSOR waitcursor; 66 67 void Sys_BeginWait (void) 68 { 69 waitcursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); 70 } 71 72 void Sys_EndWait (void) 73 { 74 if (waitcursor) 75 { 76 SetCursor (waitcursor); 77 waitcursor = NULL; 78 } 79 } 80 81 82 void Sys_GetCursorPos (int *x, int *y) 83 { 84 POINT lpPoint; 85 86 GetCursorPos (&lpPoint); 87 *x = lpPoint.x; 88 *y = lpPoint.y; 89 } 90 91 void Sys_SetCursorPos (int x, int y) 92 { 93 SetCursorPos (x, y); 94 } 95 96 97 void Sys_Beep (void) 98 { 99 MessageBeep (MB_ICONASTERISK); 100 } 101 102 char *TranslateString (char *buf) 103 { 104 static char buf2[32768]; 105 int i, l; 106 char *out; 107 108 l = strlen(buf); 109 out = buf2; 110 for (i=0 ; i<l ; i++) 111 { 112 if (buf[i] == '\n') 113 { 114 *out++ = '\r'; 115 *out++ = '\n'; 116 } 117 else 118 *out++ = buf[i]; 119 } 120 *out++ = 0; 121 122 return buf2; 123 } 124 125 126 void Sys_ClearPrintf (void) 127 { 128 char text[4]; 129 text[0] = 0; 130 131 SendMessage (g_qeglobals.d_hwndEdit, WM_SETTEXT, 0, (LPARAM)text); 132 } 133 134 135 #define SCROLLBACK_MAX_LINES 600 136 #define SCROLLBACK_DEL_CHARS 500 137 138 void Sys_Printf (char *text, ...) 139 { 140 va_list argptr; 141 char buf[32768]; 142 char *out; 143 LRESULT result; // PGM 144 DWORD oldPosS, oldPosE; // PGM 145 146 va_start (argptr,text); 147 vsprintf (buf, text,argptr); 148 va_end (argptr); 149 150 out = TranslateString (buf); 151 152 #ifdef LATER 153 Sys_Status(out); 154 #else 155 //PGM 156 result = SendMessage (g_qeglobals.d_hwndEdit, EM_GETLINECOUNT, 0, 0); 157 if(result > SCROLLBACK_MAX_LINES) 158 { 159 char replaceText[5]; 160 161 replaceText[0] = '\0'; 162 163 SendMessage (g_qeglobals.d_hwndEdit, WM_SETREDRAW, (WPARAM)0, (LPARAM)0); 164 SendMessage (g_qeglobals.d_hwndEdit, EM_GETSEL, (WPARAM)&oldPosS, (LPARAM)&oldPosE); 165 SendMessage (g_qeglobals.d_hwndEdit, EM_SETSEL, 0, SCROLLBACK_DEL_CHARS); 166 SendMessage (g_qeglobals.d_hwndEdit, EM_REPLACESEL, (WPARAM)0, (LPARAM)replaceText); 167 SendMessage (g_qeglobals.d_hwndEdit, EM_SETSEL, oldPosS, oldPosE); 168 SendMessage (g_qeglobals.d_hwndEdit, WM_SETREDRAW, (WPARAM)1, (LPARAM)0); 169 } 170 //PGM 171 172 SendMessage (g_qeglobals.d_hwndEdit, EM_REPLACESEL, 0, (LPARAM)out); 173 #endif 174 175 } 176 177 178 double Sys_DoubleTime (void) 179 { 180 return clock()/ 1000.0; 181 } 182 183 void PrintPixels (HDC hDC) 184 { 185 int i; 186 PIXELFORMATDESCRIPTOR p[64]; 187 188 printf ("### flags color layer\n"); 189 for (i=1 ; i<64 ; i++) 190 { 191 if (!DescribePixelFormat ( hDC, i, sizeof(p[0]), &p[i])) 192 break; 193 printf ("%3i %5i %5i %5i\n", i, 194 p[i].dwFlags, 195 p[i].cColorBits, 196 p[i].bReserved); 197 } 198 printf ("%i modes\n", i-1); 199 } 200 201 202 203 //========================================================================== 204 205 void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC ) 206 { 207 qwglMakeCurrent( NULL, NULL ); 208 qwglDeleteContext( hGLRC ); 209 ReleaseDC( hWnd, hDC ); 210 } 211 212 int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer ) 213 { 214 static PIXELFORMATDESCRIPTOR pfd = { 215 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 216 1, // version number 217 PFD_DRAW_TO_WINDOW | // support window 218 PFD_SUPPORT_OPENGL | // support OpenGL 219 PFD_DOUBLEBUFFER, // double buffered 220 PFD_TYPE_RGBA, // RGBA type 221 24, // 24-bit color depth 222 0, 0, 0, 0, 0, 0, // color bits ignored 223 0, // no alpha buffer 224 0, // shift bit ignored 225 0, // no accumulation buffer 226 0, 0, 0, 0, // accum bits ignored 227 32, // depth bits 228 0, // no stencil buffer 229 0, // no auxiliary buffer 230 PFD_MAIN_PLANE, // main layer 231 0, // reserved 232 0, 0, 0 // layer masks ignored 233 }; // 234 int pixelformat = 0; 235 236 zbuffer = true; 237 if ( !zbuffer ) 238 pfd.cDepthBits = 0; 239 240 if (g_PrefsDlg.m_bSGIOpenGL) 241 { 242 if ( (pixelformat = qwglChoosePixelFormat(hDC, &pfd)) == 0 ) 243 { 244 printf("%d",GetLastError()); 245 Error ("ChoosePixelFormat failed"); 246 } 247 248 if (!qwglSetPixelFormat(hDC, pixelformat, &pfd)) 249 Error ("SetPixelFormat failed"); 250 } 251 else 252 { 253 if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ) 254 { 255 printf("%d",GetLastError()); 256 Error ("ChoosePixelFormat failed"); 257 } 258 259 if (!SetPixelFormat(hDC, pixelformat, &pfd)) 260 Error ("SetPixelFormat failed"); 261 } 262 263 return pixelformat; 264 } 265 266 /* 267 ================= 268 Error 269 270 For abnormal program terminations 271 ================= 272 */ 273 void Error (char *error, ...) 274 { 275 va_list argptr; 276 char text[1024]; 277 char text2[1024]; 278 int err; 279 280 err = GetLastError (); 281 int i = qglGetError(); 282 283 va_start (argptr,error); 284 vsprintf (text, error,argptr); 285 va_end (argptr); 286 287 sprintf (text2, "%s\nGetLastError() = %i - %i\nAn unrecoverable error has occured. Would you like to edit Preferences before exiting Q3Radiant?", text, err, i); 288 289 if (MessageBox(g_qeglobals.d_hwndMain, text2, "Error", MB_YESNO) == IDYES) 290 { 291 g_PrefsDlg.LoadPrefs(); 292 g_PrefsDlg.DoModal(); 293 } 294 295 exit (1); 296 } 297 298 299 void Warning (char *error, ...) 300 { 301 va_list argptr; 302 char text[1024]; 303 int err; 304 305 err = GetLastError (); 306 int i = qglGetError(); 307 308 va_start (argptr,error); 309 vsprintf (text, error,argptr); 310 va_end (argptr); 311 312 Sys_Printf(text); 313 } 314 315 316 /* 317 ====================================================================== 318 319 FILE DIALOGS 320 321 ====================================================================== 322 */ 323 324 qboolean ConfirmModified (void) 325 { 326 if (!modified) 327 return true; 328 329 if (MessageBox (g_qeglobals.d_hwndMain, "This will lose changes to the map" 330 , "warning", MB_OKCANCEL) == IDCANCEL) 331 return false; 332 return true; 333 } 334 335 static OPENFILENAME ofn; /* common dialog box structure */ 336 static char szDirName[MAX_PATH]; /* directory string */ 337 static char szFile[260]; /* filename string */ 338 static char szFileTitle[260]; /* file title string */ 339 static char szFilter[260] = /* filter string */ 340 "Map file (*.map, *.reg)\0*.map\0*.reg\0\0"; 341 static char szProjectFilter[260] = /* filter string */ 342 "Q3Radiant project (*.qe4, *.prj)\0*.qe4\0*.prj\0\0"; 343 static char chReplace; /* string separator for szFilter */ 344 static int i, cbString; /* integer count variables */ 345 static HANDLE hf; /* file handle */ 346 347 void OpenDialog (void) 348 { 349 /* 350 * Obtain the system directory name and 351 * store it in szDirName. 352 */ 353 354 strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "mapspath") ); 355 if (strlen(szDirName) == 0) 356 { 357 strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "basepath") ); 358 strcat (szDirName, "\\maps"); 359 } 360 361 /* Place the terminating null character in the szFile. */ 362 363 szFile[0] = '\0'; 364 365 /* Set the members of the OPENFILENAME structure. */ 366 367 ofn.lStructSize = sizeof(OPENFILENAME); 368 ofn.hwndOwner = g_qeglobals.d_hwndCamera; 369 ofn.lpstrFilter = szFilter; 370 ofn.nFilterIndex = 1; 371 ofn.lpstrFile = szFile; 372 ofn.nMaxFile = sizeof(szFile); 373 ofn.lpstrFileTitle = szFileTitle; 374 ofn.nMaxFileTitle = sizeof(szFileTitle); 375 ofn.lpstrInitialDir = szDirName; 376 ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | 377 OFN_FILEMUSTEXIST; 378 379 /* Display the Open dialog box. */ 380 381 if (!GetOpenFileName(&ofn)) 382 return; // canceled 383 384 // Add the file in MRU. 385 //FIXME 386 AddNewItem( g_qeglobals.d_lpMruMenu, ofn.lpstrFile); 387 388 // Refresh the File menu. 389 //FIXME 390 PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0), 391 ID_FILE_EXIT); 392 393 /* Open the file. */ 394 395 Map_LoadFile (ofn.lpstrFile); 396 } 397 398 void ProjectDialog (void) 399 { 400 /* 401 * Obtain the system directory name and 402 * store it in szDirName. 403 */ 404 405 strcpy (szDirName, ValueForKey(g_qeglobals.d_project_entity, "basepath") ); 406 strcat (szDirName, "\\scripts"); 407 408 /* Place the terminating null character in the szFile. */ 409 410 szFile[0] = '\0'; 411 412 /* Set the members of the OPENFILENAME structure. */ 413 414 ofn.lStructSize = sizeof(OPENFILENAME); 415 ofn.hwndOwner = g_qeglobals.d_hwndCamera; 416 ofn.lpstrFilter = szProjectFilter; 417 ofn.nFilterIndex = 1; 418 ofn.lpstrFile = szFile; 419 ofn.nMaxFile = sizeof(szFile); 420 ofn.lpstrFileTitle = szFileTitle; 421 ofn.nMaxFileTitle = sizeof(szFileTitle); 422 ofn.lpstrInitialDir = szDirName; 423 ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | 424 OFN_FILEMUSTEXIST; 425 426 /* Display the Open dialog box. */ 427 428 if (!GetOpenFileName(&ofn)) 429 return; // canceled 430 431 // Refresh the File menu. 432 PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0), 433 ID_FILE_EXIT); 434 435 /* Open the file. */ 436 if (!QE_LoadProject(ofn.lpstrFile)) 437 Error ("Couldn't load project file"); 438 } 439 440 441 extern void AddSlash(CString& strPath); 442 void SaveAsDialog (bool bRegion) 443 { 444 strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "basepath") ); 445 CString strPath = szDirName; 446 AddSlash(strPath); 447 strPath += "maps"; 448 449 /* Place the terminating null character in the szFile. */ 450 451 szFile[0] = '\0'; 452 453 /* Set the members of the OPENFILENAME structure. */ 454 455 ofn.lStructSize = sizeof(OPENFILENAME); 456 ofn.hwndOwner = g_qeglobals.d_hwndCamera; 457 ofn.lpstrFilter = szFilter; 458 ofn.nFilterIndex = 1; 459 ofn.lpstrFile = szFile; 460 ofn.nMaxFile = sizeof(szFile); 461 ofn.lpstrFileTitle = szFileTitle; 462 ofn.nMaxFileTitle = sizeof(szFileTitle); 463 ofn.lpstrInitialDir = strPath; 464 ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | 465 OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT; 466 467 /* Display the Open dialog box. */ 468 469 if (!GetSaveFileName(&ofn)) 470 return; // canceled 471 472 if (bRegion) 473 DefaultExtension (ofn.lpstrFile, ".reg"); 474 else 475 DefaultExtension (ofn.lpstrFile, ".map"); 476 477 if (!bRegion) 478 { 479 strcpy (currentmap, ofn.lpstrFile); 480 AddNewItem(g_qeglobals.d_lpMruMenu, ofn.lpstrFile); 481 PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0), ID_FILE_EXIT); 482 } 483 Map_SaveFile (ofn.lpstrFile, bRegion); // ignore region 484 } 485 486 /* 487 ======================================================= 488 489 Menu modifications 490 491 ======================================================= 492 */ 493 494 /* 495 ================== 496 FillBSPMenu 497 498 ================== 499 */ 500 char *bsp_commands[256]; 501 502 void FillBSPMenu (void) 503 { 504 HMENU hmenu; 505 epair_t *ep; 506 int i; 507 static int count; 508 509 hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_BSP); 510 511 for (i=0 ; i<count ; i++) 512 DeleteMenu (hmenu, CMD_BSPCOMMAND+i, MF_BYCOMMAND); 513 count = 0; 514 515 if ( g_qeglobals.bBSPFrontendPlugin ) 516 { 517 CString str = g_BSPFrontendTable.m_pfnGetBSPMenu(); 518 char cTemp[1024]; 519 strcpy(cTemp, str); 520 char* token = strtok(cTemp, ",;"); 521 if (token && *token == ' ') 522 { 523 while (*token == ' ') 524 token++; 525 } 526 i = 0; 527 // first token is menu name 528 ModifyMenu( GetMenu(g_qeglobals.d_hwndMain), MENU_BSP, MF_BYPOSITION, MENU_BSP, (LPCTSTR)token ); 529 // redraw the menu bar 530 DrawMenuBar( g_qeglobals.d_hwndMain ); 531 token = strtok(NULL, ",;"); 532 while (token != NULL) 533 { 534 g_BSPFrontendCommands.Add(token); 535 AppendMenu (hmenu, MF_ENABLED|MF_STRING, CMD_BSPCOMMAND+i, (LPCTSTR)token ); 536 token = strtok(NULL, ",;"); 537 i++; 538 } 539 count = i; 540 } 541 else 542 { 543 i = 0; 544 for (ep = g_qeglobals.d_project_entity->epairs ; ep ; ep=ep->next) 545 { 546 if (ep->key[0] == 'b' && ep->key[1] == 's' && ep->key[2] == 'p') 547 { 548 bsp_commands[i] = ep->key; 549 AppendMenu (hmenu, MF_ENABLED|MF_STRING, 550 CMD_BSPCOMMAND+i, (LPCTSTR)ep->key); 551 i++; 552 } 553 } 554 count = i; 555 } 556 } 557 558 //============================================== 559 void AddSlash(CString& strPath) 560 { 561 if (strPath.GetLength() > 0) 562 { 563 if (strPath.GetAt(strPath.GetLength()-1) != '\\') 564 strPath += '\\'; 565 } 566 } 567 568 569 bool ExtractPath_and_Filename(const char* pPath, CString& strPath, CString& strFilename) 570 { 571 CString strPathName = pPath; 572 int nSlash = strPathName.ReverseFind('\\'); 573 if (nSlash >= 0) 574 { 575 strPath = strPathName.Left(nSlash+1); 576 strFilename = strPathName.Right(strPathName.GetLength() - nSlash - 1); 577 } 578 else strFilename = pPath; 579 return true; 580 } 581 582 583 /* 584 =============== 585 CheckBspProcess 586 587 See if the BSP is done yet 588 =============== 589 */ 590 extern void FindReplace(CString& strContents, const char* pTag, const char* pValue); 591 extern CTime g_tBegin; 592 593 void CheckBspProcess (void) 594 { 595 char outputpath[1024]; 596 char temppath[512]; 597 DWORD exitcode; 598 char *out; 599 BOOL ret; 600 601 if (!bsp_process) 602 return; 603 604 ret = GetExitCodeProcess (bsp_process, &exitcode); 605 if (!ret) 606 Error ("GetExitCodeProcess failed"); 607 if (exitcode == STILL_ACTIVE) 608 return; 609 610 bsp_process = 0; 611 612 GetTempPath(512, temppath); 613 sprintf (outputpath, "%sjunk.txt", temppath); 614 615 LoadFile (outputpath, (void **)&out); 616 Sys_Printf ("%s", out); 617 Sys_Printf ("\ncompleted.\n"); 618 free (out); 619 620 CTime tEnd = CTime::GetCurrentTime(); 621 CTimeSpan tElapsed = tEnd - g_tBegin; 622 CString strElapsed; 623 strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds()); 624 Sys_Printf(strElapsed.GetBuffer(0)); 625 626 627 Sys_Beep (); 628 Pointfile_Check(); 629 // run game if no PointFile and pref is set 630 //++timo needs to stop after BSP if leaked .. does run through vis and light instead .. 631 if (g_PrefsDlg.m_bRunQuake == TRUE && !g_qeglobals.d_pointfile_display_list) 632 { 633 char cCurDir[1024]; 634 GetCurrentDirectory(1024, cCurDir); 635 CString strExePath = g_PrefsDlg.m_strQuake2; 636 CString strOrgPath; 637 CString strOrgFile; 638 ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile); 639 if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map 640 { 641 CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath"); 642 strExePath += " +set game "; 643 strExePath += strBasePath; 644 WinExec(strExePath, SW_SHOW); 645 } 646 else 647 { 648 CString strCopyPath = strExePath; 649 char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1); 650 pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0'; 651 strCopyPath.ReleaseBuffer(); 652 SetCurrentDirectory(strCopyPath); 653 CString strOrgPath; 654 CString strOrgFile; 655 ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile); 656 AddSlash(strCopyPath); 657 FindReplace(strOrgFile, ".map", ".bsp"); 658 //++timo modified for Quake3 !! 659 strCopyPath += "baseq3\\maps\\"; 660 strCopyPath += strOrgFile; 661 AddSlash(strOrgPath); 662 strOrgPath += strOrgFile; 663 bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0); 664 if (!bRun) 665 bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE); 666 if (bRun) 667 { 668 FindReplace(strOrgFile, ".bsp", ""); 669 strExePath += " +map "; 670 strExePath += strOrgFile; 671 WinExec(strExePath, SW_SHOW); 672 } 673 } 674 SetCurrentDirectory(cCurDir); 675 } 676 } 677 678 extern int cambuttonstate; 679 680 extern "C" { 681 void *Com_Allocate( int bytes ) { 682 return malloc(bytes); 683 } 684 685 void Com_Dealloc( void *ptr ) { 686 free(ptr); 687 } 688 689 690 void Com_Printf( const char *msg, ... ) { 691 va_list argptr; 692 char buf[32768]; 693 char *out; 694 695 va_start (argptr,msg); 696 vsprintf (buf, msg,argptr); 697 va_end (argptr); 698 699 out = TranslateString (buf); 700 701 Sys_Printf(buf); 702 } 703 704 void Com_Error( int level, const char *error, ... ) { 705 va_list argptr; 706 char buf[32768]; 707 char *out; 708 709 va_start (argptr,error); 710 vsprintf (buf, error,argptr); 711 va_end (argptr); 712 713 out = TranslateString (buf); 714 715 Sys_Printf(buf); 716 } 717 718 void Com_DPrintf( const char *msg, ... ) { 719 return; 720 } 721 722 int FS_Write( const void *buffer, int len, fileHandle_t h ) { 723 SafeWrite(reinterpret_cast<FILE*>(h), buffer, len); 724 return len; 725 } 726 727 int FS_ReadFile( const char *qpath, void **buffer ) { 728 CString strPath = ValueForKey(g_qeglobals.d_project_entity, "basepath"); 729 AddSlash(strPath); 730 strPath += qpath; 731 return LoadFile(strPath, buffer); 732 } 733 734 void FS_FreeFile( void *buffer ) { 735 Com_Dealloc(buffer); 736 } 737 738 fileHandle_t FS_FOpenFileWrite( const char *filename ) { 739 CString strPath = ValueForKey(g_qeglobals.d_project_entity, "basepath"); 740 AddSlash(strPath); 741 strPath += filename; 742 // bad casting ptr to int 743 return reinterpret_cast<fileHandle_t>(SafeOpenWrite(strPath)); 744 } 745 746 void FS_FCloseFile( fileHandle_t f ) { 747 fclose(reinterpret_cast<FILE*>(f)); 748 } 749 750 751 752 } 753