apply misc fixes from Markus Fischer and Rambetter
[xonotic/netradiant.git] / radiant / error.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #define UNICODE
23 #include "stdafx.h"
24
25 #if defined (__linux__) || defined (__APPLE__)
26 #include <unistd.h>
27 #endif
28
29 /*
30 =================
31 Error
32
33 For abnormal program terminations
34 =================
35 */
36
37 /*!
38 \todo
39 FIXME the prompt wether to do prefs dialog, may not even be possible
40 if the crash happens before the game is loaded
41 */
42
43 void Error (const char *error, ...)
44 {
45   va_list argptr;
46   char  text[4096];
47
48   va_start (argptr,error);
49   vsprintf (text, error,argptr);
50   va_end (argptr);
51
52   strcat( text, "\n" );
53
54 #if defined (__linux__) || defined (__APPLE__)
55   if (errno != 0)
56   {
57     strcat( text, "errno: " );
58     strcat( text, strerror (errno));
59     strcat( text, "\n");
60   }
61 #endif
62
63 #ifdef _WIN32
64   if (GetLastError() != 0)
65   {
66     LPVOID lpMsgBuf;
67     FormatMessage(
68       FORMAT_MESSAGE_ALLOCATE_BUFFER |
69       FORMAT_MESSAGE_FROM_SYSTEM |
70       FORMAT_MESSAGE_IGNORE_INSERTS,
71       NULL,
72       GetLastError(),
73       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
74       (LPTSTR) &lpMsgBuf,
75       0,
76       NULL
77       );
78     strcat( text, "GetLastError: " );
79     /*
80     Gtk will only crunch 0<=char<=127
81     this is a bit hackish, but I didn't find useful functions in win32 API for this
82     */
83     TCHAR *scan, *next = (TCHAR*)lpMsgBuf;
84     do
85     {
86       scan = next;
87       text[strlen(text)+1] = '\0';
88       if ((scan[0] >= 0) && (scan[0] <= 127))
89         text[strlen(text)] = scan[0];
90       else
91         text[strlen(text)] = '?';
92       next = CharNext(scan);
93     } while (next != scan);
94     strcat( text, "\n");
95     LocalFree( lpMsgBuf );
96   }
97 #endif
98
99   // we need to have a current context to call glError()
100   if (g_qeglobals_gui.d_glBase != NULL)
101   {
102     // qglGetError .. can record several errors, clears after calling
103     //++timo TODO: be able to deal with several errors if necessary, for now I'm just warning about pending error messages
104     // NOTE: forget that, most boards don't seem to follow the OpenGL standard
105     GLenum iGLError = qglGetError();
106     if (iGLError != GL_NO_ERROR)
107     {
108       // use our own gluErrorString
109       strcat( text, "qgluErrorString: " );
110       strcat( text, (char*)qgluErrorString( iGLError ) );
111       strcat( text, "\n" );
112     }
113   }
114
115   strcat (text, "An unrecoverable error has occured.\n"
116           "Would you like to edit Preferences before exiting Radiant?");
117
118   Sys_Printf(text);
119
120   if (gtk_MessageBox(NULL, text, "Error", MB_YESNO) == IDYES)
121   {
122     Sys_Printf("Doing prefs..\n");
123     g_PrefsDlg.LoadPrefs ();
124     g_PrefsDlg.DoModal();
125   }
126
127   QGL_Shutdown();
128
129   g_PrefsDlg.Destroy ();
130   g_dlgSurface.Destroy ();
131   g_dlgFind.Destroy ();
132
133   // force close logging if necessary
134   g_PrefsDlg.mGamesDialog.m_bLogConsole = false;
135         Sys_LogFile();
136
137   _exit (1);
138 }
139
140 void WINAPI Error (char *error, ...)
141 {
142   va_list argptr;
143   char  text[1024];
144
145   va_start (argptr,error);
146   vsprintf (text, error,argptr);
147   va_end (argptr);
148
149         Error((const char *)text);
150 }