1
0
forked from 0ad/0ad

improvements from work: [update-workspaces required]

- split precompiled.h into several headers (simplifies reuse)
- enable additional warnings not in W4
- split ErrorReaction into ErrorReactionInternal - clarifies which
values can actually be returned by debug_DisplayError
- wsdl: slightly safer HDC usage via CS_OWNDC, avoid dipping into DC
cache via ValidateRect instead of BeginPaint; remove unused thread
create
- StdDeserializer - wasn't including byte_order => BYTE_ORDER was
undefined
- wsysdep: clean up error dialog message handling

This was SVN commit r8828.
This commit is contained in:
janwas 2010-12-09 11:16:21 +00:00
parent 78f2924f9c
commit ba2a9d7af3
21 changed files with 460 additions and 383 deletions

View File

@ -524,6 +524,7 @@ function setup_all_libs ()
"lib/file/common",
"lib/file/io",
"lib/file/vfs",
"lib/pch",
"lib/posix",
"lib/res",
"lib/res/graphics",

View File

@ -77,9 +77,9 @@ static void def_log(const wchar_t* text)
}
static ErrorReaction def_display_error(const wchar_t* UNUSED(text), size_t UNUSED(flags))
static ErrorReactionInternal def_display_error(const wchar_t* UNUSED(text), size_t UNUSED(flags))
{
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
}
@ -171,7 +171,7 @@ void ah_log(const wchar_t* text)
ah.log(text);
}
ErrorReaction ah_display_error(const wchar_t* text, size_t flags)
ErrorReactionInternal ah_display_error(const wchar_t* text, size_t flags)
{
return ah.display_error(text, flags);
}

View File

@ -162,12 +162,12 @@ extern void ah_log(const wchar_t* text);
*
* @param text error message.
* @param flags see DebugDisplayErrorFlags.
* @return ErrorReaction.
* @return ErrorReactionInternal.
*
* the default implementation just returns ER_NOT_IMPLEMENTED, which
* the default implementation just returns ERI_NOT_IMPLEMENTED, which
* causes the normal sys_display_error to be used.
**/
extern ErrorReaction ah_display_error(const wchar_t* text, size_t flags);
extern ErrorReactionInternal ah_display_error(const wchar_t* text, size_t flags);
/**
@ -182,7 +182,7 @@ struct AppHooks
const wchar_t* (*translate)(const wchar_t* text);
void (*translate_free)(const wchar_t* text);
void (*log)(const wchar_t* text);
ErrorReaction (*display_error)(const wchar_t* text, size_t flags);
ErrorReactionInternal (*display_error)(const wchar_t* text, size_t flags);
};
/**

View File

@ -365,39 +365,42 @@ static bool ShouldSuppressError(atomic_bool* suppress)
return false;
}
static ErrorReaction CallDisplayError(const wchar_t* text, size_t flags)
static ErrorReactionInternal CallDisplayError(const wchar_t* text, size_t flags)
{
// first try app hook implementation
ErrorReaction er = ah_display_error(text, flags);
ErrorReactionInternal er = ah_display_error(text, flags);
// .. it's only a stub: default to normal implementation
if(er == ER_NOT_IMPLEMENTED)
if(er == ERI_NOT_IMPLEMENTED)
er = sys_display_error(text, flags);
return er;
}
static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, atomic_bool* suppress)
static ErrorReaction PerformErrorReaction(ErrorReactionInternal er, size_t flags, atomic_bool* suppress)
{
const bool shouldHandleBreak = (flags & DE_MANUAL_BREAK) == 0;
switch(er)
{
case ER_BREAK:
case ERI_CONTINUE:
return ER_CONTINUE;
case ERI_BREAK:
// handle "break" request unless the caller wants to (doing so here
// instead of within the dlgproc yields a correct call stack)
if(shouldHandleBreak)
{
debug_break();
er = ER_CONTINUE;
return ER_CONTINUE;
}
break;
else
return ER_BREAK;
case ER_SUPPRESS:
case ERI_SUPPRESS:
(void)cpu_CAS(suppress, 0, DEBUG_SUPPRESS);
er = ER_CONTINUE;
break;
return ER_CONTINUE;
case ER_EXIT:
case ERI_EXIT:
isExiting = 1; // see declaration
COMPILER_FENCE;
@ -408,9 +411,12 @@ static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, atomic
#endif
exit(EXIT_FAILURE);
}
return er;
case ERI_NOT_IMPLEMENTED:
default:
debug_break(); // not expected to be reached
return ER_CONTINUE;
}
}
ErrorReaction debug_DisplayError(const wchar_t* description,
@ -434,7 +440,7 @@ ErrorReaction debug_DisplayError(const wchar_t* description,
{
// in non-debug-info mode, simply display the given description
// and then return immediately
ErrorReaction er = CallDisplayError(description, flags);
ErrorReactionInternal er = CallDisplayError(description, flags);
return PerformErrorReaction(er, flags, suppress);
}
@ -456,7 +462,7 @@ ErrorReaction debug_DisplayError(const wchar_t* description,
const wchar_t* text = debug_BuildErrorMessage(description, filename, line, func, context, lastFuncToSkip, &emm);
(void)debug_WriteCrashlog(text);
ErrorReaction er = CallDisplayError(text, flags);
ErrorReactionInternal er = CallDisplayError(text, flags);
// note: debug_break-ing here to make sure the app doesn't continue
// running is no longer necessary. debug_DisplayError now determines our

View File

@ -128,7 +128,8 @@ typedef volatile intptr_t atomic_bool;
const atomic_bool DEBUG_SUPPRESS = 0xAB;
/**
* choices offered by the shared error dialog
* choices offered by the error dialog that are returned
* by debug_DisplayError.
**/
enum ErrorReaction
{
@ -144,28 +145,37 @@ enum ErrorReaction
* only returned if DE_MANUAL_BREAK was passed; otherwise,
* debug_DisplayError will trigger a breakpoint itself.
**/
ER_BREAK,
ER_BREAK
};
/**
* all choices offered by the error dialog. those not defined in
* ErrorReaction are acted upon by debug_DisplayError and
* never returned to callers.
* (this separation avoids enumerator-not-handled warnings)
**/
enum ErrorReactionInternal
{
ERI_CONTINUE = ER_CONTINUE,
ERI_BREAK = ER_BREAK,
/**
* ignore and do not report again.
* note: non-persistent; only applicable during this program run.
* acted on by debug_DisplayError; never returned to caller.
**/
ER_SUPPRESS,
ERI_SUPPRESS,
/**
* exit the program immediately.
* acted on by debug_DisplayError; never returned to caller.
**/
ER_EXIT,
ERI_EXIT,
/**
* special return value for the display_error app hook stub to indicate
* that it has done nothing and that the normal sys_display_error
* implementation should be called instead.
* acted on by debug_DisplayError; never returned to caller.
**/
ER_NOT_IMPLEMENTED
ERI_NOT_IMPLEMENTED
};
/**
@ -283,10 +293,11 @@ STMT(\
{\
switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
{\
case ER_BREAK:\
debug_break();\
case ER_CONTINUE:\
break;\
case ER_BREAK:\
default:\
debug_break();\
break;\
}\
}\
@ -310,10 +321,11 @@ STMT(\
static atomic_bool suppress__;\
switch(debug_OnAssertionFailure(expr, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
{\
case ER_BREAK:\
debug_break();\
case ER_CONTINUE:\
break;\
case ER_BREAK:\
default:\
debug_break();\
break;\
}\
)
@ -329,10 +341,11 @@ STMT(\
static atomic_bool suppress__;\
switch(debug_OnError(err, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
{\
case ER_BREAK:\
debug_break();\
case ER_CONTINUE:\
break;\
case ER_BREAK:\
default:\
debug_break();\
break;\
}\
)

View File

@ -27,6 +27,9 @@
#include "lib/sysdep/compiler.h" // ICC_VERSION
#include "lib/sysdep/arch.h" // ARCH_IA32
#if MSC_VERSION
# pragma warning(disable:4710) // function not inlined
#endif
#if ICC_VERSION
# pragma warning(push)
# pragma warning(disable:82) // storage class is not first

View File

@ -0,0 +1,34 @@
// (included from precompiled.h)
#include "lib/external_libraries/suppress_boost_warnings.h"
// Boost
// .. if this package isn't going to be statically linked, we're better off
// using Boost via DLL. (otherwise, we would have to ensure the exact same
// compiler is used, which is a pain because MSC8, MSC9 and ICC 10 are in use)
#ifndef LIB_STATIC_LINK
# define BOOST_ALL_DYN_LINK
#endif
// the following boost libraries have been included in TR1 and are
// thus deemed usable:
#define BOOST_FILESYSTEM_VERSION 2
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
// (these ones are used more rarely, so we don't enable them in minimal configurations)
#if !MINIMAL_PCH
#include <boost/array.hpp>
using boost::array;
#include <boost/mem_fn.hpp>
using boost::mem_fn;
#include <boost/function.hpp>
using boost::function;
#include <boost/bind.hpp>
using boost::bind;
#endif // !MINIMAL_PCH

View File

@ -0,0 +1,82 @@
// (included from precompiled.h)
#if !MINIMAL_PCH
// all new-form C library headers
#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
//#include <ciso646> // defines e.g. "and" to "&". unnecessary and causes trouble with asm.
#include <climits>
#include <clocale>
#include <cmath>
//#include <csetjmp> // incompatible with libpng on Debian/Ubuntu
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>
#endif // !MINIMAL_PCH
#if MINIMAL_PCH < 2
// common C++98 STL headers
#include <algorithm>
#include <vector>
#endif
#if MINIMAL_PCH < 3
// all other C++98 STL headers
#include <deque>
#include <functional>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <utility>
#endif
#if !MINIMAL_PCH
// all other C++98 headers
#include <bitset>
#include <complex>
#include <exception>
#include <fstream>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <limits>
#include <locale>
#include <new>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <sstream>
#include <typeinfo>
#include <valarray>
#endif // !MINIMAL_PCH
#if !MINIMAL_PCH
// STL extensions
#if GCC_VERSION >= 402 // (see comment in stl.h about GCC versions)
# include <tr1/unordered_map>
# include <tr1/unordered_set>
#elif GCC_VERSION
# include <ext/hash_map>
# include <ext/hash_set>
#else
# include <hash_map>
# include <hash_set>
#endif
#endif // !MINIMAL_PCH

View File

@ -0,0 +1,52 @@
// (included from precompiled.h)
#include "lib/sysdep/compiler.h" // MSC_VERSION
#if MSC_VERSION
// .. temporarily disabled W4 (unimportant but ought to be fixed)
# pragma warning(disable:4201) // nameless struct (Matrix3D)
# pragma warning(disable:4244) // conversion from uintN to uint8
// .. permanently disabled W4
# pragma warning(disable:4103) // alignment changed after including header (boost has #pragma pack/pop in separate headers)
# pragma warning(disable:4127) // conditional expression is constant; rationale: see STMT in lib.h.
# pragma warning(disable:4351) // yes, default init of array entries is desired
# pragma warning(disable:4355) // 'this' used in base member initializer list
# pragma warning(disable:4718) // recursive call has no side effects, deleting
# pragma warning(disable:4786) // identifier truncated to 255 chars
# pragma warning(disable:4996) // function is deprecated
// .. disabled only for the precompiled headers
# pragma warning(disable:4702) // unreachable code (frequent in STL)
// .. VS2005 code analysis (very frequent ones)
# if MSC_VERSION >= 1400
# pragma warning(disable:6011) // dereferencing NULL pointer
# pragma warning(disable:6246) // local declaration hides declaration of the same name in outer scope
# endif
// .. Intel-specific
# if ICC_VERSION
# pragma warning(disable:383) // value copied to temporary, reference to temporary used
# pragma warning(disable:981) // operands are evaluated in unspecified order
# pragma warning(disable:1418) // external function definition with no prior declaration (raised for all non-static function templates)
# pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
# pragma warning(disable:1684) // conversion from pointer to same-sized integral type
# pragma warning(disable:1786) // function is deprecated (disabling 4996 isn't sufficient)
# pragma warning(disable:2415) // variable of static storage duration was declared but never referenced (raised by Boost)
# endif
// .. ENABLE ones disabled even in W4
# pragma warning(default:4062) // enumerator is not handled
//# pragma warning(default:4191) // unsafe conversion (false alarms for function pointers)
# pragma warning(default:4254) // [bit field] conversion, possible loss of data
//# pragma warning(default:4263) // member function does not override any base class virtual member function (happens in GUI)
# pragma warning(default:4265) // class has virtual functions, but destructor is not virtual
# pragma warning(default:4296) // [unsigned comparison vs. 0 =>] expression is always false
# pragma warning(default:4545 4546 4547 4548 4549) // ill-formed comma expressions
//# pragma warning(default:4555) // expression has no effect (triggered by STL unused)
# pragma warning(default:4557) // __assume contains effect
//# pragma warning(default:4619) // #pragma warning: there is no [such] warning number (false alarms in STL)
//# pragma warning(default:4668) // not defined as a preprocessor macro, replacing with '0' (frequent in Windows)
# pragma warning(default:4710) // function not inlined
# pragma warning(default:4836) // local types or unnamed types cannot be used as template arguments
# pragma warning(default:4905) // wide string literal cast to LPSTR
# pragma warning(default:4906) // string literal cast to LPWSTR
# pragma warning(default:4928) // illegal copy-initialization; more than one user-defined conversion has been implicitly applied
# pragma warning(default:4946) // reinterpret_cast used between related classes
#endif

View File

@ -22,7 +22,7 @@
/*
* precompiled header. must be the first non-comment part of every
* source file (VC6..8 requirement).
* source file (VC++ requirement).
*/
// some libraries have only a small number of source files, and the
@ -36,44 +36,20 @@
# define MINIMAL_PCH 0
#endif
#define _SECURE_SCL 0
#include "lib/config.h" // CONFIG_ENABLE_PCH
#include "lib/sysdep/compiler.h" // MSC_VERSION, HAVE_PCH
#include "lib/sysdep/os.h" // (must come before posix_types.h)
// disable some common and annoying warnings
// (done as soon as possible so that headers below are covered)
#if MSC_VERSION
// .. temporarily disabled W4 (unimportant but ought to be fixed)
# pragma warning(disable:4201) // nameless struct (Matrix3D)
# pragma warning(disable:4244) // conversion from uintN to uint8
// .. permanently disabled W4
# pragma warning(disable:4103) // alignment changed after including header (boost has #pragma pack/pop in separate headers)
# pragma warning(disable:4127) // conditional expression is constant; rationale: see STMT in lib.h.
# pragma warning(disable:4996) // function is deprecated
# pragma warning(disable:4786) // identifier truncated to 255 chars
# pragma warning(disable:4351) // yes, default init of array entries is desired
# pragma warning(disable:4355) // 'this' used in base member initializer list
# pragma warning(disable:4718) // recursive call has no side effects, deleting
// .. disabled only for the precompiled headers
# pragma warning(disable:4702) // unreachable code (frequent in STL)
// .. VS2005 code analysis (very frequent ones)
# if MSC_VERSION >= 1400
# pragma warning(disable:6011) // dereferencing NULL pointer
# pragma warning(disable:6246) // local declaration hides declaration of the same name in outer scope
# endif
# if ICC_VERSION
# pragma warning(disable:383) // value copied to temporary, reference to temporary used
# pragma warning(disable:981) // operands are evaluted in unspecified order
# pragma warning(disable:1418) // external function definition with no prior declaration (raised for all non-static function templates)
# pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
# pragma warning(disable:1786) // function is deprecated (disabling 4996 isn't sufficient)
# pragma warning(disable:1684) // conversion from pointer to same-sized integral type
# pragma warning(disable:2415) // variable of static storage duration was declared but never referenced (raised by Boost)
# endif
// must come before any STL headers are included
#if MSC_VERSION && defined(NDEBUG)
# define _SECURE_SCL 0
#endif
// disable some common and annoying warnings
// must come after compiler.h, but as soon as possible so that
// headers below are covered
#include "lib/pch/pch_warnings.h"
#if ICC_VERSION
#include <mathimf.h> // (must come before <cmath> or <math.h> (replaces them))
double __cdecl abs(double x); // not declared by mathimf
@ -96,38 +72,7 @@ long double __cdecl abs(long double x); // required for Eigen
#include "lib/lib.h"
#include "lib/secure_crt.h"
#include "lib/external_libraries/suppress_boost_warnings.h"
// Boost
// .. if this package isn't going to be statically linked, we're better off
// using Boost via DLL. (otherwise, we would have to ensure the exact same
// compiler is used, which is a pain because MSC8, MSC9 and ICC 10 are in use)
#ifndef LIB_STATIC_LINK
# define BOOST_ALL_DYN_LINK
#endif
// the following boost libraries have been included in TR1 and are
// thus deemed usable:
#define BOOST_FILESYSTEM_VERSION 2
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
// (these ones are used more rarely, so we don't enable them in minimal configurations)
#if !MINIMAL_PCH
#include <boost/array.hpp>
using boost::array;
#include <boost/mem_fn.hpp>
using boost::mem_fn;
#include <boost/function.hpp>
using boost::function;
#include <boost/bind.hpp>
using boost::bind;
#endif // !MINIMAL_PCH
#include "lib/pch/pch_boost.h"
// (must come after boost and common lib headers, but before re-enabling
// warnings to avoid boost spew)
@ -149,86 +94,7 @@ using boost::bind;
// anything placed here won't need to be compiled in each translation unit,
// but will cause a complete rebuild if they change.
#if !MINIMAL_PCH
// all new-form C library headers
#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
//#include <ciso646> // defines e.g. "and" to "&". unnecessary and causes trouble with asm.
#include <climits>
#include <clocale>
#include <cmath>
//#include <csetjmp> // incompatible with libpng on Debian/Ubuntu
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>
#endif // !MINIMAL_PCH
#if MINIMAL_PCH < 2
// common C++98 STL headers
#include <algorithm>
#include <vector>
#endif
#if MINIMAL_PCH < 3
// all other C++98 STL headers
#include <deque>
#include <functional>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <utility>
#endif
#if !MINIMAL_PCH
// all other C++98 headers
#include <bitset>
#include <complex>
#include <exception>
#include <fstream>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <limits>
#include <locale>
#include <new>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <sstream>
#include <typeinfo>
#include <valarray>
#endif // !MINIMAL_PCH
#if !MINIMAL_PCH
// STL extensions
#if GCC_VERSION >= 402 // (see comment in stl.h about GCC versions)
# include <tr1/unordered_map>
# include <tr1/unordered_set>
#elif GCC_VERSION
# include <ext/hash_map>
# include <ext/hash_set>
#else
# include <hash_map>
# include <hash_set>
#endif
#endif // !MINIMAL_PCH
#include "lib/pch/pch_stdlib.h"
#endif // #if CONFIG_ENABLE_PCH && HAVE_PCH

View File

@ -62,6 +62,9 @@ static size_t MaxCoresPerPackage()
if(x86_x64_cpuid(&regs))
maxCoresPerPackage = bits(regs.ecx, 0, 7)+1;
break;
default:
break;
}
return maxCoresPerPackage;

View File

@ -820,6 +820,10 @@ static LibError InitIdentifierString()
strcpy_s(identifierString, ARRAY_SIZE(identifierString), "Intel Pentium III");
}
break;
default:
strcpy_s(identifierString, ARRAY_SIZE(identifierString), "Unknown, non-Intel/AMD");
break;
}
}
// identifierString already holds a valid brand string; pretty it up.

View File

@ -54,17 +54,17 @@ void sys_display_msg(const wchar_t* caption, const wchar_t* msg)
}
#if OS_MACOSX
static ErrorReaction try_gui_display_error(const wchar_t* text, bool manual_break, bool allow_suppress, bool no_continue)
static ErrorReactionInternal try_gui_display_error(const wchar_t* text, bool manual_break, bool allow_suppress, bool no_continue)
{
// TODO: implement this, in a way that doesn't rely on X11
// and doesn't occasionally cause crazy errors like
// "The process has forked and you cannot use this
// CoreFoundation functionality safely. You MUST exec()."
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
}
#else
static ErrorReaction try_gui_display_error(const wchar_t* text, bool manual_break, bool allow_suppress, bool no_continue)
static ErrorReactionInternal try_gui_display_error(const wchar_t* text, bool manual_break, bool allow_suppress, bool no_continue)
{
// We'll run xmessage via fork/exec.
// To avoid bad interaction between fork and pthreads, the child process
@ -112,7 +112,7 @@ static ErrorReaction try_gui_display_error(const wchar_t* text, bool manual_brea
pid_t cpid = fork();
if(cpid == -1)
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
if(cpid == 0)
{
@ -153,7 +153,7 @@ static ErrorReaction try_gui_display_error(const wchar_t* text, bool manual_brea
// If it didn't exist successfully, fall back to the non-GUI prompt
if(!WIFEXITED(status))
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
switch(WEXITSTATUS(status))
{
@ -163,34 +163,34 @@ static ErrorReaction try_gui_display_error(const wchar_t* text, bool manual_brea
case 102: // Break
if(manual_break)
return ER_BREAK;
return ERI_BREAK;
debug_break();
return ER_CONTINUE;
return ERI_CONTINUE;
case 100: // Continue
if(!no_continue)
return ER_CONTINUE;
return ERI_CONTINUE;
// continue isn't allowed, so this was invalid input.
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
case 101: // Suppress
if(allow_suppress)
return ER_SUPPRESS;
return ERI_SUPPRESS;
// suppress isn't allowed, so this was invalid input.
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
case 104: // Exit
abort();
return ER_EXIT; // placebo; never reached
return ERI_EXIT; // placebo; never reached
}
// Unexpected return value - fall back to the non-GUI prompt
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
}
#endif
ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
ErrorReactionInternal sys_display_error(const wchar_t* text, size_t flags)
{
printf("%ls\n\n", text);
@ -199,8 +199,8 @@ ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
const bool no_continue = (flags & DE_NO_CONTINUE ) != 0;
// Try the GUI prompt if possible
ErrorReaction ret = try_gui_display_error(text, manual_break, allow_suppress, no_continue);
if (ret != ER_NOT_IMPLEMENTED)
ErrorReactionInternal ret = try_gui_display_error(text, manual_break, allow_suppress, no_continue);
if (ret != ERI_NOT_IMPLEMENTED)
return ret;
// Otherwise fall back to the terminal-based input
@ -227,24 +227,24 @@ ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
case 'b': case 'B':
if(manual_break)
return ER_BREAK;
return ERI_BREAK;
debug_break();
return ER_CONTINUE;
return ERI_CONTINUE;
case 'c': case 'C':
if(!no_continue)
return ER_CONTINUE;
return ERI_CONTINUE;
// continue isn't allowed, so this was invalid input. loop again.
break;
case 's': case 'S':
if(allow_suppress)
return ER_SUPPRESS;
return ERI_SUPPRESS;
// suppress isn't allowed, so this was invalid input. loop again.
break;
case 'e': case 'E':
abort();
return ER_EXIT; // placebo; never reached
return ERI_EXIT; // placebo; never reached
}
}
}

View File

@ -99,6 +99,9 @@ static bool IsThrottlingPossible()
return true;
}
break;
default:
break;
}
#endif

View File

@ -64,7 +64,10 @@ static bool fullscreen;
static bool is_quitting;
static HWND g_hWnd = (HWND)INVALID_HANDLE_VALUE;
static HDC g_hDC = (HDC)INVALID_HANDLE_VALUE; // needed by gamma code
// usable at any time (required by SDL_SetGamma); this is made
// mostly safe via CS_OWNDC.
static HDC g_hDC = (HDC)INVALID_HANDLE_VALUE;
//----------------------------------------------------------------------------
@ -78,13 +81,13 @@ public:
{
}
bool Change(float gamma_r, float gamma_g, float gamma_b)
bool Change(HDC hDC, float gamma_r, float gamma_g, float gamma_b)
{
// get current ramp (once) so we can later restore it.
if(!m_hasChanged)
{
debug_assert(wutil_IsValidHandle(g_hDC));
if(!GetDeviceGammaRamp(g_hDC, m_original))
debug_assert(wutil_IsValidHandle(hDC));
if(!GetDeviceGammaRamp(hDC, m_original))
return false;
}
@ -165,7 +168,7 @@ static GammaRamp gammaRamp;
// note: any component gamma = 0 is assumed to be identity.
int SDL_SetGamma(float r, float g, float b)
{
return gammaRamp.Change(r, g, b)? 0 : -1;
return gammaRamp.Change(g_hDC, r, g, b)? 0 : -1;
}
@ -213,7 +216,7 @@ static void wnd_UpdateWindowDimensions(DWORD windowStyle, int& w, int& h)
}
static LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK OnMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static HWND wnd_CreateWindow(int w, int h)
{
@ -227,14 +230,15 @@ static HWND wnd_CreateWindow(int w, int h)
// register window class
WNDCLASSW wc;
memset(&wc, 0, sizeof(wc));
wc.style = 0;
wc.lpfnWndProc = wndproc;
// no CS_VREDRAW and CS_HREDRAW - avoids redrawing when resized.
wc.style = CS_OWNDC; // (see g_hDC definition)
wc.lpfnWndProc = OnMessage;
wc.lpszClassName = L"WSDL";
wc.hInstance = hInst;
ATOM class_atom = RegisterClassW(&wc);
if(!class_atom)
{
debug_assert(0); // SDL_SetVideoMode: RegisterClass failed
debug_assert(0); // RegisterClassW failed
return 0;
}
@ -268,6 +272,10 @@ int SDL_GL_SetAttribute(SDL_GLattr attr, int value)
case SDL_GL_SWAP_CONTROL:
vsyncEnabled = value;
break;
case SDL_GL_DOUBLEBUFFER:
// (always enabled)
break;
}
return 0;
@ -1122,8 +1130,8 @@ static BOOL OnEraseBkgnd(HWND UNUSED(hWnd), HDC UNUSED(hDC))
ev.type = SDL_VIDEOEXPOSE;
QueueEvent(ev);
// indicate we erased the background; PAINTSTRUCT.fErase will
// later be FALSE.
// prevent GDI from erasing the background by claiming we did so.
// PAINTSTRUCT.fErase will later be FALSE.
return TRUE;
}
@ -1132,9 +1140,10 @@ static BOOL OnEraseBkgnd(HWND UNUSED(hWnd), HDC UNUSED(hDC))
static LRESULT OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
// BeginPaint/EndPaint is unnecessary (see http://opengl.czweb.org/ch04/082-084.html)
// however, we at least need to validate the window to prevent
// continuous WM_PAINT messages.
ValidateRect(hWnd, 0);
return 0;
}
@ -1186,7 +1195,7 @@ static DefWindowProcDisposition OnSysCommand(WPARAM wParam)
}
static LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static LRESULT CALLBACK OnMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(is_quitting)
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
@ -1357,30 +1366,6 @@ int SDL_SemWait(SDL_sem* sem)
}
// threads
// users don't need to allocate SDL_Thread variables, so type = void
// API returns SDL_Thread*, which is the HANDLE value itself.
//
// we go through hoops to avoid type cast warnings;
// a simple union { pthread_t; SDL_Thread* } yields "uninitialized"
// warnings in VC2005, so we coerce values directly.
cassert(sizeof(pthread_t) == sizeof(SDL_Thread*));
SDL_Thread* SDL_CreateThread(int (*func)(void*), void* param)
{
pthread_t thread = 0;
if(pthread_create(&thread, 0, (void* (*)(void*))func, param) < 0)
return 0;
return *(SDL_Thread**)&thread;
}
int SDL_KillThread(SDL_Thread* thread)
{
pthread_cancel(*(pthread_t*)&thread);
return 0;
}
//-----------------------------------------------------------------------------
// misc API

View File

@ -88,25 +88,31 @@ LIB_API void* SDL_GL_GetProcAddress(const char*);
LIB_API void SDL_GL_SwapBuffers();
LIB_API int SDL_SetGamma(float r, float g, float b);
//
// threads / sync
// semaphores
//
typedef void SDL_sem;
typedef void SDL_Thread;
LIB_API u32 SDL_GetTicks();
LIB_API void SDL_Delay(u32 ms);
LIB_API SDL_sem* SDL_CreateSemaphore(int cnt);
LIB_API void SDL_DestroySemaphore(SDL_sem*);
LIB_API int SDL_SemPost(SDL_sem*);
LIB_API int SDL_SemWait(SDL_sem* sem);
LIB_API SDL_Thread* SDL_CreateThread(int (*)(void*), void*);
LIB_API int SDL_KillThread(SDL_Thread*);
//
// time
//
LIB_API u32 SDL_GetTicks();
LIB_API void SDL_Delay(u32 ms);
//
// mouse
//
LIB_API void SDL_WarpMouse(int, int);
@ -118,8 +124,19 @@ enum ShowCursorToggle
};
LIB_API int SDL_ShowCursor(int toggle);
LIB_API Uint8 SDL_GetMouseState(int* x, int* y);
LIB_API int SDL_SetGamma(float r, float g, float b);
//
// keyboard
//
// from real SDL, but they're ignored anyway
#define SDL_DEFAULT_REPEAT_DELAY 500
#define SDL_DEFAULT_REPEAT_INTERVAL 30
#define SDL_EnableKeyRepeat(delay, interval)
LIB_API Uint8* SDL_GetKeyState(int* num_keys);
//
@ -286,17 +303,8 @@ LIB_API SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode);
#define SDL_GetError() ""
// from real SDL, but they're ignored anyway
#define SDL_DEFAULT_REPEAT_DELAY 500
#define SDL_DEFAULT_REPEAT_INTERVAL 30
#define SDL_EnableKeyRepeat(delay, interval)
LIB_API void SDL_WM_SetCaption(const char *title, const char *icon);
LIB_API Uint8* SDL_GetKeyState(int* num_keys);
LIB_API Uint8 SDL_GetMouseState(int* x, int* y);
LIB_API Uint8 SDL_GetAppState();
#endif // #ifndef INCLUDED_WSDL

View File

@ -31,6 +31,7 @@
#include <shlobj.h> // pick_dir
#include <shellapi.h> // open_url
#include <Wincrypt.h>
#include <WindowsX.h> // message crackers
#include "lib/sysdep/clipboard.h"
#include "lib/sysdep/os/win/error_dialog.h"
@ -53,26 +54,32 @@ void sys_display_msg(const wchar_t* caption, const wchar_t* msg)
// "program error" dialog (triggered by debug_assert and exception)
//-----------------------------------------------------------------------------
// support for resizing the dialog / its controls
// (have to do this manually - grr)
// support for resizing the dialog / its controls (must be done manually)
static POINTS dlg_clientOrigin;
static POINTS dlg_prevClientSize;
static void dlg_OnMove(HWND UNUSED(hDlg), int x, int y)
{
dlg_clientOrigin.x = x;
dlg_clientOrigin.y = y;
}
static POINTS dlg_client_origin;
static POINTS dlg_prev_client_size;
static const size_t ANCHOR_LEFT = 0x01;
static const size_t ANCHOR_RIGHT = 0x02;
static const size_t ANCHOR_TOP = 0x04;
static const size_t ANCHOR_BOTTOM = 0x08;
static const size_t ANCHOR_ALL = 0x0f;
static const size_t ANCHOR_ALL = 0x0F;
static void dlg_resize_control(HWND hDlg, int dlg_item, int dx,int dy, size_t anchors)
static void dlg_ResizeControl(HWND hDlg, int dlgItem, int dx, int dy, size_t anchors)
{
HWND hControl = GetDlgItem(hDlg, dlg_item);
HWND hControl = GetDlgItem(hDlg, dlgItem);
RECT r;
GetWindowRect(hControl, &r);
int w = r.right - r.left, h = r.bottom - r.top;
int x = r.left - dlg_client_origin.x, y = r.top - dlg_client_origin.y;
int x = r.left - dlg_clientOrigin.x, y = r.top - dlg_clientOrigin.y;
if(anchors & ANCHOR_RIGHT)
{
@ -98,37 +105,45 @@ static void dlg_resize_control(HWND hDlg, int dlg_item, int dx,int dy, size_t an
}
static void dlg_resize(HWND hDlg, WPARAM wParam, LPARAM lParam)
static void dlg_OnSize(HWND hDlg, UINT state, int clientSizeX, int clientSizeY)
{
// 'minimize' was clicked. we need to ignore this, otherwise
// dx/dy would reduce some control positions to less than 0.
// since Windows clips them, we wouldn't later be able to
// reconstruct the previous values when 'restoring'.
if(wParam == SIZE_MINIMIZED)
if(state == SIZE_MINIMIZED)
return;
// first call for this dialog instance. WM_MOVE hasn't been sent yet,
// so dlg_client_origin are invalid => must not call resize_control().
// we need to set dlg_prev_client_size for the next call before exiting.
bool first_call = (dlg_prev_client_size.y == 0);
// NB: origin might legitimately be 0, but we know it is invalid
// on the first call to this function, where dlg_prevClientSize is 0.
const bool isOriginValid = (dlg_prevClientSize.y != 0);
POINTS dlg_client_size = MAKEPOINTS(lParam);
int dx = dlg_client_size.x - dlg_prev_client_size.x;
int dy = dlg_client_size.y - dlg_prev_client_size.y;
dlg_prev_client_size = dlg_client_size;
const int dx = clientSizeX - dlg_prevClientSize.x;
const int dy = clientSizeY - dlg_prevClientSize.y;
dlg_prevClientSize.x = clientSizeX;
dlg_prevClientSize.y = clientSizeY;
if(first_call)
if(!isOriginValid) // must not call dlg_ResizeControl
return;
dlg_resize_control(hDlg, IDC_CONTINUE, dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_resize_control(hDlg, IDC_SUPPRESS, dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_resize_control(hDlg, IDC_BREAK , dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_resize_control(hDlg, IDC_EXIT , dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_resize_control(hDlg, IDC_COPY , dx,dy, ANCHOR_RIGHT|ANCHOR_BOTTOM);
dlg_resize_control(hDlg, IDC_EDIT1 , dx,dy, ANCHOR_ALL);
dlg_ResizeControl(hDlg, IDC_CONTINUE, dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_ResizeControl(hDlg, IDC_SUPPRESS, dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_ResizeControl(hDlg, IDC_BREAK , dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_ResizeControl(hDlg, IDC_EXIT , dx,dy, ANCHOR_LEFT|ANCHOR_BOTTOM);
dlg_ResizeControl(hDlg, IDC_COPY , dx,dy, ANCHOR_RIGHT|ANCHOR_BOTTOM);
dlg_ResizeControl(hDlg, IDC_EDIT1 , dx,dy, ANCHOR_ALL);
}
static void dlg_OnGetMinMaxInfo(HWND UNUSED(hDlg), LPMINMAXINFO mmi)
{
// we must make sure resize_control will never set negative coords -
// Windows would clip them, and its real position would be lost.
// restrict to a reasonable and good looking minimum size [pixels].
mmi->ptMinTrackSize.x = 407;
mmi->ptMinTrackSize.y = 159; // determined experimentally
}
struct DialogParams
{
@ -136,19 +151,14 @@ struct DialogParams
size_t flags;
};
static INT_PTR CALLBACK error_dialog_proc(HWND hDlg, unsigned int msg, WPARAM wParam, LPARAM lParam)
static BOOL dlg_OnInitDialog(HWND hDlg, HWND UNUSED(hWndFocus), LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
{
const DialogParams* params = (const DialogParams*)lParam;
HWND hWnd;
// need to reset for new instance of dialog
dlg_client_origin.x = dlg_client_origin.y = 0;
dlg_prev_client_size.x = dlg_prev_client_size.y = 0;
dlg_clientOrigin.x = dlg_clientOrigin.y = 0;
dlg_prevClientSize.x = dlg_prevClientSize.y = 0;
if(!(params->flags & DE_ALLOW_SUPPRESS))
{
@ -164,81 +174,85 @@ static INT_PTR CALLBACK error_dialog_proc(HWND hDlg, unsigned int msg, WPARAM wP
SetDlgItemTextW(hDlg, IDC_EDIT1, params->text);
return TRUE; // set default keyboard focus
}
case WM_SYSCOMMAND:
// close dialog if [X] is clicked (doesn't happen automatically)
// note: lower 4 bits are reserved
if((wParam & 0xFFF0) == SC_CLOSE)
{
EndDialog(hDlg, 0);
return 0; // processed
}
break;
// return 0 if processed, otherwise break
case WM_COMMAND:
switch(wParam)
{
case IDC_COPY:
{
// note: allocating on the stack would be easier+safer,
// but this is too big.
const size_t max_chars = 128*KiB;
wchar_t* buf = new wchar_t[max_chars];
GetDlgItemTextW(hDlg, IDC_EDIT1, buf, max_chars);
sys_clipboard_set(buf);
delete[] buf;
return 0;
}
case IDC_CONTINUE:
EndDialog(hDlg, ER_CONTINUE);
return 0;
case IDC_SUPPRESS:
EndDialog(hDlg, ER_SUPPRESS);
return 0;
case IDC_BREAK:
EndDialog(hDlg, ER_BREAK);
return 0;
case IDC_EXIT:
EndDialog(hDlg, ER_EXIT);
return 0;
default:
break;
}
break;
case WM_MOVE:
dlg_client_origin = MAKEPOINTS(lParam);
break;
case WM_GETMINMAXINFO:
{
// we must make sure resize_control will never set negative coords -
// Windows would clip them, and its real position would be lost.
// restrict to a reasonable and good looking minimum size [pixels].
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMinTrackSize.x = 407;
mmi->ptMinTrackSize.y = 159; // determined experimentally
return 0;
}
case WM_SIZE:
dlg_resize(hDlg, wParam, lParam);
break;
default:
break;
}
// we didn't process the message; caller will perform default action.
return FALSE;
}
ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
static void dlg_OnCommand(HWND hDlg, int id, HWND UNUSED(hWndCtl), UINT UNUSED(codeNotify))
{
switch(id)
{
case IDC_COPY:
{
std::vector<wchar_t> buf(128*KiB); // (too big for stack)
GetDlgItemTextW(hDlg, IDC_EDIT1, &buf[0], (int)buf.size());
sys_clipboard_set(&buf[0]);
break;
}
case IDC_CONTINUE:
EndDialog(hDlg, ERI_CONTINUE);
break;
case IDC_SUPPRESS:
EndDialog(hDlg, ERI_SUPPRESS);
break;
case IDC_BREAK:
EndDialog(hDlg, ERI_BREAK);
break;
case IDC_EXIT:
EndDialog(hDlg, ERI_EXIT);
break;
default:
break;
}
}
static void dlg_OnSysCommand(HWND hDlg, UINT cmd, int UNUSED(x), int UNUSED(y))
{
switch(cmd & 0xFFF0) // NB: lower 4 bits are reserved
{
// [X] clicked -> close dialog (doesn't happen automatically)
case SC_CLOSE:
EndDialog(hDlg, 0);
break;
default:
break;
}
}
static INT_PTR CALLBACK dlg_OnMessage(HWND hDlg, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return HANDLE_WM_INITDIALOG(hDlg, wParam, lParam, dlg_OnInitDialog);
case WM_SYSCOMMAND:
return HANDLE_WM_SYSCOMMAND(hDlg, wParam, lParam, dlg_OnSysCommand);
case WM_COMMAND:
return HANDLE_WM_COMMAND(hDlg, wParam, lParam, dlg_OnCommand);
case WM_MOVE:
return HANDLE_WM_MOVE(hDlg, wParam, lParam, dlg_OnMove);
case WM_GETMINMAXINFO:
return HANDLE_WM_GETMINMAXINFO(hDlg, wParam, lParam, dlg_OnGetMinMaxInfo);
case WM_SIZE:
return HANDLE_WM_SIZE(hDlg, wParam, lParam, dlg_OnSize);
default:
// we didn't process the message; caller will perform default action.
return FALSE;
}
}
ErrorReactionInternal sys_display_error(const wchar_t* text, size_t flags)
{
// note: other threads might still be running, crash and take down the
// process before we have a chance to display this error message.
@ -258,7 +272,7 @@ ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
// - by passing hWnd=0, we check all windows belonging to the current
// thread. there is no reason to use hWndParent below.
MSG msg;
BOOL quit_pending = PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE);
const BOOL isQuitPending = PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE);
const HINSTANCE hInstance = wutil_LibModuleHandle();
LPCWSTR lpTemplateName = MAKEINTRESOURCEW(IDD_DIALOG1);
@ -269,18 +283,18 @@ ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
// we've managed to show the dialog).
const HWND hWndParent = wutil_AppWindow();
INT_PTR ret = DialogBoxParamW(hInstance, lpTemplateName, hWndParent, error_dialog_proc, (LPARAM)&params);
INT_PTR ret = DialogBoxParamW(hInstance, lpTemplateName, hWndParent, dlg_OnMessage, (LPARAM)&params);
if(quit_pending)
if(isQuitPending)
PostQuitMessage((int)msg.wParam);
// failed; warn user and make sure we return an ErrorReaction.
// failed; warn user and make sure we return an ErrorReactionInternal.
if(ret == 0 || ret == -1)
{
debug_DisplayMessage(L"Error", L"Unable to display detailed error dialog.");
return ER_CONTINUE;
return ERI_CONTINUE;
}
return (ErrorReaction)ret;
return (ErrorReactionInternal)ret;
}

View File

@ -27,7 +27,7 @@
#ifndef INCLUDED_SYSDEP
#define INCLUDED_SYSDEP
#include "lib/debug.h" // ErrorReaction
#include "lib/debug.h" // ErrorReactionInternal
#include <cstdarg> // needed for sys_vswprintf
@ -52,12 +52,12 @@ extern void sys_display_msg(const wchar_t* caption, const wchar_t* msg);
*
* @param text to display (practically unlimited length)
* @param flags: see DebugDisplayErrorFlags.
* @return ErrorReaction (except ER_EXIT, which is acted on immediately)
* @return ErrorReactionInternal (except ERI_EXIT, which is acted on immediately)
*
* called from debug_DisplayError unless overridden by means of
* ah_display_error.
**/
extern ErrorReaction sys_display_error(const wchar_t* text, size_t flags);
extern ErrorReactionInternal sys_display_error(const wchar_t* text, size_t flags);
//

View File

@ -407,7 +407,7 @@ static size_t ChooseCacheSize()
}
#endif
ErrorReaction psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(flags))
ErrorReactionInternal psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(flags))
{
// If we're fullscreen, then sometimes (at least on some particular drivers on Linux)
// displaying the error dialog hangs the desktop since the dialog box is behind the
@ -425,7 +425,7 @@ ErrorReaction psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(flags))
}
// We don't actually implement the error display here, so return appropriately
return ER_NOT_IMPLEMENTED;
return ERI_NOT_IMPLEMENTED;
}
static void InitVfs(const CmdLineArgs& args)

View File

@ -25,6 +25,9 @@
#include "js/jsapi.h"
#include "lib/byte_order.h"
CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) :
m_ScriptInterface(scriptInterface), m_Stream(stream)
{

View File

@ -89,12 +89,12 @@ static const wchar_t* FindWindowName(const CmdLineArgs& UNUSED(args))
// (This is a bit pointless - there's no choice since we've deleted the ActorViewer)
}
static ErrorReaction AtlasDisplayError(const wchar_t* text, size_t flags)
static ErrorReactionInternal AtlasDisplayError(const wchar_t* text, size_t flags)
{
// TODO: after Atlas has been unloaded, don't do this
Atlas_DisplayError(text, flags);
return ER_CONTINUE;
return ERI_CONTINUE;
}
static void RendererIncrementalLoad()