* Sys_Dialog for more user friendly error reporting
* (bug #3932) Recovery from bad video settings
This commit is contained in:
parent
4876413217
commit
005f870ebe
13 changed files with 564 additions and 120 deletions
|
@ -68,6 +68,23 @@ char *Sys_DefaultHomePath(void)
|
|||
return homePath;
|
||||
}
|
||||
|
||||
#ifndef MACOS_X
|
||||
/*
|
||||
================
|
||||
Sys_TempPath
|
||||
================
|
||||
*/
|
||||
const char *Sys_TempPath( void )
|
||||
{
|
||||
const char *TMPDIR = getenv( "TMPDIR" );
|
||||
|
||||
if( TMPDIR == NULL || TMPDIR[ 0 ] == '\0' )
|
||||
return "/tmp";
|
||||
else
|
||||
return TMPDIR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
|
@ -428,35 +445,6 @@ void Sys_FreeFileList( char **list )
|
|||
Z_Free( list );
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
=================
|
||||
Sys_StripAppBundle
|
||||
|
||||
Discovers if passed dir is suffixed with the directory structure of a Mac OS X
|
||||
.app bundle. If it is, the .app directory structure is stripped off the end and
|
||||
the result is returned. If not, dir is returned untouched.
|
||||
=================
|
||||
*/
|
||||
char *Sys_StripAppBundle( char *dir )
|
||||
{
|
||||
static char cwd[MAX_OSPATH];
|
||||
|
||||
Q_strncpyz(cwd, dir, sizeof(cwd));
|
||||
if(strcmp(Sys_Basename(cwd), "MacOS"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
if(strcmp(Sys_Basename(cwd), "Contents"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
if(!strstr(Sys_Basename(cwd), ".app"))
|
||||
return dir;
|
||||
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
|
||||
return cwd;
|
||||
}
|
||||
#endif // MACOS_X
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_Sleep
|
||||
|
@ -517,40 +505,196 @@ void Sys_ErrorDialog( const char *error )
|
|||
|
||||
Sys_Print( va( "%s\n", error ) );
|
||||
|
||||
#if defined(MACOS_X) && !DEDICATED
|
||||
/* This function has to be in a separate file, compiled as Objective-C. */
|
||||
extern void Cocoa_MsgBox( const char *text );
|
||||
if (!com_dedicated || !com_dedicated->integer)
|
||||
Cocoa_MsgBox(error);
|
||||
#ifndef DEDICATED
|
||||
Sys_Dialog( DT_ERROR, va( "%s. See \"%s\" for details.", error, ospath ), "Error" );
|
||||
#endif
|
||||
|
||||
/* make sure the write path for the crashlog exists... */
|
||||
// Make sure the write path for the crashlog exists...
|
||||
if( FS_CreatePath( ospath ) ) {
|
||||
Com_Printf( "ERROR: couldn't create path '%s' for crash log.\n", ospath );
|
||||
return;
|
||||
}
|
||||
|
||||
/* we might be crashing because we maxed out the Quake MAX_FILE_HANDLES,
|
||||
which will come through here, so we don't want to recurse forever by
|
||||
calling FS_FOpenFileWrite()...use the Unix system APIs instead. */
|
||||
f = open(ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640);
|
||||
// We might be crashing because we maxed out the Quake MAX_FILE_HANDLES,
|
||||
// which will come through here, so we don't want to recurse forever by
|
||||
// calling FS_FOpenFileWrite()...use the Unix system APIs instead.
|
||||
f = open( ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640 );
|
||||
if( f == -1 )
|
||||
{
|
||||
Com_Printf( "ERROR: couldn't open %s\n", fileName );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're crashing, so we don't care much if write() or close() fails. */
|
||||
// We're crashing, so we don't care much if write() or close() fails.
|
||||
while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) {
|
||||
if (write( f, buffer, size ) != size) {
|
||||
if( write( f, buffer, size ) != size ) {
|
||||
Com_Printf( "ERROR: couldn't fully write to %s\n", fileName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(f);
|
||||
close( f );
|
||||
}
|
||||
|
||||
#ifndef MACOS_X
|
||||
/*
|
||||
==============
|
||||
Sys_ZenityCommand
|
||||
==============
|
||||
*/
|
||||
static int Sys_ZenityCommand( dialogType_t type, const char *message, const char *title )
|
||||
{
|
||||
const char *options = "";
|
||||
char command[ 1024 ];
|
||||
|
||||
switch( type )
|
||||
{
|
||||
default:
|
||||
case DT_INFO: options = "--info"; break;
|
||||
case DT_WARNING: options = "--warning"; break;
|
||||
case DT_ERROR: options = "--error"; break;
|
||||
case DT_YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break;
|
||||
case DT_OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break;
|
||||
}
|
||||
|
||||
Com_sprintf( command, sizeof( command ), "zenity %s --text=\"%s\" --title=\"%s\"",
|
||||
options, message, title );
|
||||
|
||||
return system( command );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_KdialogCommand
|
||||
==============
|
||||
*/
|
||||
static int Sys_KdialogCommand( dialogType_t type, const char *message, const char *title )
|
||||
{
|
||||
const char *options = "";
|
||||
char command[ 1024 ];
|
||||
|
||||
switch( type )
|
||||
{
|
||||
default:
|
||||
case DT_INFO: options = "--msgbox"; break;
|
||||
case DT_WARNING: options = "--sorry"; break;
|
||||
case DT_ERROR: options = "--error"; break;
|
||||
case DT_YES_NO: options = "--warningyesno"; break;
|
||||
case DT_OK_CANCEL: options = "--warningcontinuecancel"; break;
|
||||
}
|
||||
|
||||
Com_sprintf( command, sizeof( command ), "kdialog %s \"%s\" --title \"%s\"",
|
||||
options, message, title );
|
||||
|
||||
return system( command );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_XmessageCommand
|
||||
==============
|
||||
*/
|
||||
static int Sys_XmessageCommand( dialogType_t type, const char *message, const char *title )
|
||||
{
|
||||
const char *options = "";
|
||||
char command[ 1024 ];
|
||||
|
||||
switch( type )
|
||||
{
|
||||
default: options = "-buttons OK"; break;
|
||||
case DT_YES_NO: options = "-buttons Yes:0,No:1"; break;
|
||||
case DT_OK_CANCEL: options = "-buttons OK:0,Cancel:1"; break;
|
||||
}
|
||||
|
||||
Com_sprintf( command, sizeof( command ), "xmessage -center %s \"%s\"",
|
||||
options, message );
|
||||
|
||||
return system( command );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_Dialog
|
||||
|
||||
Display a *nix dialog box
|
||||
==============
|
||||
*/
|
||||
dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title )
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
NONE = 0,
|
||||
ZENITY,
|
||||
KDIALOG,
|
||||
XMESSAGE,
|
||||
NUM_DIALOG_PROGRAMS
|
||||
} dialogCommandType_t;
|
||||
typedef int (*dialogCommandBuilder_t)( dialogType_t, const char *, const char * );
|
||||
|
||||
const char *session = getenv( "DESKTOP_SESSION" );
|
||||
qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse };
|
||||
dialogCommandBuilder_t commands[ NUM_DIALOG_PROGRAMS ] = { NULL };
|
||||
dialogCommandType_t preferredCommandType = NONE;
|
||||
|
||||
commands[ ZENITY ] = &Sys_ZenityCommand;
|
||||
commands[ KDIALOG ] = &Sys_KdialogCommand;
|
||||
commands[ XMESSAGE ] = &Sys_XmessageCommand;
|
||||
|
||||
// This may not be the best way
|
||||
if( !Q_stricmp( session, "gnome" ) )
|
||||
preferredCommandType = ZENITY;
|
||||
else if( !Q_stricmp( session, "kde" ) )
|
||||
preferredCommandType = KDIALOG;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int i;
|
||||
int exitCode;
|
||||
|
||||
for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ )
|
||||
{
|
||||
if( preferredCommandType != NONE && preferredCommandType != i )
|
||||
continue;
|
||||
|
||||
if( !tried[ i ] )
|
||||
{
|
||||
exitCode = commands[ i ]( type, message, title );
|
||||
|
||||
if( exitCode >= 0 )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case DT_YES_NO: return exitCode ? DR_NO : DR_YES;
|
||||
case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK;
|
||||
default: return DR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
tried[ i ] = qtrue;
|
||||
|
||||
// The preference failed, so start again in order
|
||||
if( preferredCommandType != NONE )
|
||||
{
|
||||
preferredCommandType = NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ )
|
||||
{
|
||||
if( !tried[ i ] )
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Com_DPrintf( S_COLOR_YELLOW "WARNING: failed to show a dialog\n" );
|
||||
return DR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_GLimpSafeInit
|
||||
|
@ -611,3 +755,23 @@ void Sys_SetEnv(const char *name, const char *value)
|
|||
else
|
||||
unsetenv(name);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_PID
|
||||
==============
|
||||
*/
|
||||
int Sys_PID( void )
|
||||
{
|
||||
return getpid( );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_PIDIsRunning
|
||||
==============
|
||||
*/
|
||||
qboolean Sys_PIDIsRunning( int pid )
|
||||
{
|
||||
return kill( pid, 0 ) == 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue