mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-02-17 01:31:47 +00:00
debugger
This commit is contained in:
parent
a8ef0f67fe
commit
7a2ccee330
31 changed files with 1038 additions and 499 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@
|
|||
/neo/out*
|
||||
/neo/build*
|
||||
|
||||
/neo/CMakeSettings.json
|
||||
|
|
|
@ -862,6 +862,9 @@ if (TOOLS AND MFC_FOUND AND MSVC)
|
|||
# Script editor
|
||||
file(GLOB src_script_editor "tools/script/*.cpp")
|
||||
add_globbed_headers(src_script_editor "tools/script")
|
||||
# Script Debugger
|
||||
file(GLOB src_script_debugger "tools/debugger/*.cpp")
|
||||
add_globbed_headers(src_script_debugger "tools/debugger")
|
||||
# sound editor?
|
||||
file(GLOB src_sound_editor "tools/sound/*.cpp")
|
||||
add_globbed_headers(src_sound_editor "tools/sound")
|
||||
|
@ -881,6 +884,7 @@ if (TOOLS AND MFC_FOUND AND MSVC)
|
|||
${src_map_editor}
|
||||
${src_script_editor}
|
||||
${src_sound_editor}
|
||||
${src_script_debugger}
|
||||
"tools/edit_public.h"
|
||||
"tools/edit_gui_common.h"
|
||||
)
|
||||
|
|
|
@ -244,7 +244,7 @@ void idInternalCVar::UpdateValue( void ) {
|
|||
clamped = true;
|
||||
}
|
||||
}
|
||||
if ( clamped || !idStr::IsNumeric( value ) || idStr::FindChar( value, '.' ) ) {
|
||||
if ( clamped || !idStr::IsNumeric( value ) || (idStr::FindChar( value, '.' )!=-1) ) {
|
||||
valueString = idStr( integerValue );
|
||||
value = valueString.c_str();
|
||||
}
|
||||
|
|
|
@ -142,6 +142,7 @@ public:
|
|||
virtual void ActivateTool( bool active );
|
||||
virtual void WriteConfigToFile( const char *filename );
|
||||
virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd );
|
||||
virtual void DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer);
|
||||
virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) );
|
||||
virtual void EndRedirect( void );
|
||||
virtual void SetRefreshOnPrint( bool set );
|
||||
|
@ -382,12 +383,17 @@ void idCommonLocal::VPrintf( const char *fmt, va_list args ) {
|
|||
// remove any color codes
|
||||
idStr::RemoveColors( msg );
|
||||
|
||||
// echo to dedicated console and early console
|
||||
Sys_Printf( "%s", msg );
|
||||
|
||||
|
||||
#ifdef ID_ALLOW_TOOLS
|
||||
// print to script debugger server
|
||||
// DebuggerServerPrint( msg );
|
||||
|
||||
if (com_editors & EDITOR_DEBUGGER)
|
||||
DebuggerServerPrint(msg);
|
||||
else
|
||||
#endif
|
||||
// only echo to dedicated console and early console when debugger is not running so no
|
||||
// deadlocks occur if engine functions called from the debuggerthread trace stuff..
|
||||
Sys_Printf("%s", msg);
|
||||
#if 0 // !@#
|
||||
#if defined(_DEBUG) && defined(WIN32)
|
||||
if ( strlen( msg ) < 512 ) {
|
||||
|
@ -1134,8 +1140,7 @@ Com_ScriptDebugger_f
|
|||
static void Com_ScriptDebugger_f( const idCmdArgs &args ) {
|
||||
// Make sure it wasnt on the command line
|
||||
if ( !( com_editors & EDITOR_DEBUGGER ) ) {
|
||||
common->Printf( "Script debugger is currently disabled\n" );
|
||||
// DebuggerClientLaunch();
|
||||
DebuggerClientLaunch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2020,6 +2025,7 @@ void Com_LocalizeMaps_f( const idCmdArgs &args ) {
|
|||
strCount += LocalizeMap(args.Argv(2), strTable, listHash, excludeList, write);
|
||||
} else {
|
||||
idStrList files;
|
||||
//wow, what now? a hardcoded path?
|
||||
GetFileList("z:/d3xp/d3xp/maps/game", "*.map", files);
|
||||
for ( int i = 0; i < files.Num(); i++ ) {
|
||||
idStr file = fileSystem->OSPathToRelativePath(files[i]);
|
||||
|
@ -2666,7 +2672,7 @@ void idCommonLocal::LoadGameDLL( void ) {
|
|||
gameImport.AASFileManager = ::AASFileManager;
|
||||
gameImport.collisionModelManager = ::collisionModelManager;
|
||||
|
||||
gameExport = *GetGameAPI( &gameImport );
|
||||
gameExport = *GetGameAPI( &gameImport);
|
||||
|
||||
if ( gameExport.version != GAME_API_VERSION ) {
|
||||
Sys_DLL_Unload( gameDLL );
|
||||
|
@ -3164,8 +3170,10 @@ void idCommonLocal::InitGame( void ) {
|
|||
// initialize the user interfaces
|
||||
uiManager->Init();
|
||||
|
||||
#if defined(ID_ALLOW_TOOLS)
|
||||
// startup the script debugger
|
||||
// DebuggerServerInit();
|
||||
DebuggerServerInit();
|
||||
#endif;
|
||||
|
||||
PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04350" ) );
|
||||
|
||||
|
@ -3202,8 +3210,10 @@ void idCommonLocal::ShutdownGame( bool reloading ) {
|
|||
sw->StopAllSounds();
|
||||
}
|
||||
|
||||
#if defined(ID_ALLOW_TOOLS)
|
||||
// shutdown the script debugger
|
||||
// DebuggerServerShutdown();
|
||||
DebuggerServerShutdown();
|
||||
#endif
|
||||
|
||||
idAsyncNetwork::client.Shutdown();
|
||||
|
||||
|
@ -3298,6 +3308,10 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F
|
|||
}
|
||||
}
|
||||
|
||||
void idCommonLocal::DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer)
|
||||
{
|
||||
DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer);
|
||||
}
|
||||
|
||||
idGameCallbacks gameCallbacks;
|
||||
|
||||
|
|
|
@ -111,6 +111,8 @@ struct MemInfo_t {
|
|||
};
|
||||
|
||||
class idLangDict;
|
||||
class idInterpreter;
|
||||
class idProgram;
|
||||
|
||||
class idCommon {
|
||||
public:
|
||||
|
@ -158,6 +160,9 @@ public:
|
|||
// Writes cvars with the given flags to a file.
|
||||
virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) = 0;
|
||||
|
||||
// Debbugger hook to check if a breakpoint has been hit
|
||||
virtual void DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) = 0;
|
||||
|
||||
// Begins redirection of console output to the given buffer.
|
||||
virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ) = 0;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "idlib/BitMsg.h"
|
||||
#include "idlib/Dict.h"
|
||||
#include "idlib/containers/StrList.h"
|
||||
#include "framework/UsercmdGen.h"
|
||||
#include "renderer/RenderWorld.h"
|
||||
#include "sound/sound.h"
|
||||
|
@ -109,10 +110,10 @@ public:
|
|||
virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ) = 0;
|
||||
|
||||
// Loads a map and spawns all the entities.
|
||||
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) = 0;
|
||||
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors ) = 0;
|
||||
|
||||
// Loads a map from a savegame file.
|
||||
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) = 0;
|
||||
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) = 0;
|
||||
|
||||
// Saves the current game state, the session may have written some data to the file already.
|
||||
virtual void SaveGame( idFile *saveGameFile ) = 0;
|
||||
|
@ -127,7 +128,7 @@ public:
|
|||
virtual void SpawnPlayer( int clientNum ) = 0;
|
||||
|
||||
// Runs a game frame, may return a session command for level changing, etc
|
||||
virtual gameReturn_t RunFrame( const usercmd_t *clientCmds ) = 0;
|
||||
virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors) = 0;
|
||||
|
||||
// Makes rendering and sound system calls to display for a given clientNum.
|
||||
virtual bool Draw( int clientNum ) = 0;
|
||||
|
@ -232,6 +233,11 @@ enum {
|
|||
|
||||
class idEntity;
|
||||
class idMD5Anim;
|
||||
class idThread;
|
||||
class function_t;
|
||||
class idProgram;
|
||||
class idInterpreter;
|
||||
typedef struct prstack_s prstack_t;
|
||||
|
||||
// FIXME: this interface needs to be reworked but it properly separates code for the time being
|
||||
class idGameEdit {
|
||||
|
@ -294,7 +300,7 @@ public:
|
|||
virtual void EntitySetColor( idEntity *ent, const idVec3 color );
|
||||
|
||||
// Player methods.
|
||||
virtual bool PlayerIsValid() const;
|
||||
virtual bool PlayerIsValid( ) const;
|
||||
virtual void PlayerGetOrigin( idVec3 &org ) const;
|
||||
virtual void PlayerGetAxis( idMat3 &axis ) const;
|
||||
virtual void PlayerGetViewAngles( idAngles &angles ) const;
|
||||
|
@ -311,6 +317,35 @@ public:
|
|||
virtual void MapRemoveEntity( const char *name ) const;
|
||||
virtual void MapEntityTranslate( const char *name, const idVec3 &v ) const;
|
||||
|
||||
// In game script Debugging Support
|
||||
// IdProgram
|
||||
virtual void GetLoadedScripts( idStrList ** result );
|
||||
virtual bool IsLineCode( const char* filename, int linenumber) const;
|
||||
virtual const char * GetFilenameForStatement( idProgram* program, int index ) const;
|
||||
virtual int GetLineNumberForStatement( idProgram* program, int index ) const;
|
||||
|
||||
// idInterpreter
|
||||
virtual bool CheckForBreakPointHit( const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth ) const;
|
||||
virtual bool ReturnedFromFunction( const idProgram* program, const idInterpreter* interpreter, int index ) const;
|
||||
virtual bool GetRegisterValue( const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth ) const;
|
||||
virtual const idThread* GetThread( const idInterpreter* interpreter ) const;
|
||||
virtual int GetInterpreterCallStackDepth( const idInterpreter* interpreter );
|
||||
virtual const function_t* GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth = -1 );
|
||||
|
||||
// IdThread
|
||||
virtual const char * ThreadGetName( const idThread* thread ) const;
|
||||
virtual int ThreadGetNum( const idThread* thread ) const;
|
||||
virtual bool ThreadIsDoneProcessing( const idThread* thread ) const;
|
||||
virtual bool ThreadIsWaiting( const idThread* thread ) const;
|
||||
virtual bool ThreadIsDying( const idThread* thread ) const;
|
||||
virtual int GetTotalScriptThreads( ) const;
|
||||
virtual const idThread* GetThreadByIndex( int index ) const;
|
||||
|
||||
// MSG helpers
|
||||
virtual void MSG_WriteThreadInfo( idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter );
|
||||
virtual void MSG_WriteCallstackFunc( idBitMsg* msg, const prstack_t* stack, const idProgram* program, int instructionPtr );
|
||||
virtual void MSG_WriteInterpreterInfo( idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr );
|
||||
virtual void MSG_WriteScriptList( idBitMsg* msg );
|
||||
};
|
||||
|
||||
extern idGameEdit * gameEdit;
|
||||
|
|
|
@ -1646,7 +1646,7 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) {
|
|||
|
||||
// load and spawn all other entities ( from a savegame possibly )
|
||||
if ( loadingSaveGame && savegameFile ) {
|
||||
if ( game->InitFromSaveGame( fullMapName + ".map", rw, sw, savegameFile ) == false ) {
|
||||
if ( game->InitFromSaveGame( fullMapName + ".map", rw, sw, savegameFile, com_editors ) == false ) {
|
||||
// If the loadgame failed, restart the map with the player persistent data
|
||||
loadingSaveGame = false;
|
||||
fileSystem->CloseFile( savegameFile );
|
||||
|
@ -1655,11 +1655,11 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) {
|
|||
common->Warning( "WARNING: Loading savegame failed, will restart the map with the player persistent data!" );
|
||||
|
||||
game->SetServerInfo( mapSpawnData.serverInfo );
|
||||
game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds() );
|
||||
game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(),com_editors );
|
||||
}
|
||||
} else {
|
||||
game->SetServerInfo( mapSpawnData.serverInfo );
|
||||
game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds() );
|
||||
game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(), com_editors);
|
||||
}
|
||||
|
||||
if ( !idAsyncNetwork::IsActive() && !loadingSaveGame ) {
|
||||
|
@ -1681,7 +1681,7 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) {
|
|||
if ( !idAsyncNetwork::IsActive() && !loadingSaveGame ) {
|
||||
// run a few frames to allow everything to settle
|
||||
for ( i = 0; i < 10; i++ ) {
|
||||
game->RunFrame( mapSpawnData.mapSpawnUsercmd );
|
||||
game->RunFrame( mapSpawnData.mapSpawnUsercmd, com_editors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2785,7 +2785,7 @@ void idSessionLocal::RunGameTic() {
|
|||
|
||||
// run the game logic every player move
|
||||
int start = Sys_Milliseconds();
|
||||
gameReturn_t ret = game->RunFrame( &cmd );
|
||||
gameReturn_t ret = game->RunFrame( &cmd, com_editors);
|
||||
|
||||
int end = Sys_Milliseconds();
|
||||
time_gameFrame += end - start; // note time used for com_speeds
|
||||
|
|
|
@ -2442,7 +2442,7 @@ void idAsyncServer::RunFrame( void ) {
|
|||
DuplicateUsercmds( gameFrame, gameTime );
|
||||
|
||||
// advance game
|
||||
gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ] );
|
||||
gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ], com_editors );
|
||||
|
||||
idAsyncNetwork::ExecuteSessionCommand( ret.sessionCommand );
|
||||
|
||||
|
|
|
@ -1146,3 +1146,64 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Debugger
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
bool idGameEdit::IsLineCode(const char* filename, int linenumber) const
|
||||
{
|
||||
static idStr fileStr = idStr(MAX_PATH);
|
||||
idProgram* program = &gameLocal.program;
|
||||
for (int i = 0; i < program->NumStatements(); i++)
|
||||
{
|
||||
fileStr = program->GetFilename(program->GetStatement(i).file);
|
||||
fileStr.BackSlashesToSlashes();
|
||||
|
||||
if (strcmp(filename, fileStr.c_str()) == 0
|
||||
&& program->GetStatement(i).linenumber == linenumber
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void idGameEdit::GetLoadedScripts( idStrList** result )
|
||||
{
|
||||
(*result)->Clear();
|
||||
idProgram* program = &gameLocal.program;
|
||||
|
||||
for (int i = 0; i < program->NumFilenames(); i++)
|
||||
{
|
||||
(*result)->AddUnique( idStr(program->GetFilename( i )) );
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEdit::MSG_WriteScriptList( idBitMsg* msg)
|
||||
{
|
||||
idProgram* program = &gameLocal.program;
|
||||
|
||||
msg->WriteInt( program->NumFilenames() );
|
||||
for (int i = 0; i < program->NumFilenames(); i++)
|
||||
{
|
||||
idStr file = program->GetFilename(i);
|
||||
//fix this. it seams that scripts triggered by the runtime are stored with a wrong path
|
||||
//the use // instead of '\'
|
||||
file.BackSlashesToSlashes();
|
||||
msg->WriteString(file);
|
||||
}
|
||||
}
|
||||
|
||||
const char* idGameEdit::GetFilenameForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetFilenameForStatement(index);
|
||||
}
|
||||
|
||||
int idGameEdit::GetLineNumberForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetLineNumberForStatement(index);
|
||||
}
|
||||
|
|
|
@ -1192,7 +1192,7 @@ void idGameLocal::MapPopulate( void ) {
|
|||
idGameLocal::InitFromNewMap
|
||||
===================
|
||||
*/
|
||||
void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) {
|
||||
void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors) {
|
||||
|
||||
this->isServer = isServer;
|
||||
this->isClient = isClient;
|
||||
|
@ -1204,6 +1204,8 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl
|
|||
|
||||
Printf( "----- Game Map Init -----\n" );
|
||||
|
||||
//exposing editor flag so debugger does not miss any script calls during load/startup
|
||||
editors = activeEditors;
|
||||
gamestate = GAMESTATE_STARTUP;
|
||||
|
||||
gameRenderWorld = renderWorld;
|
||||
|
@ -1230,7 +1232,7 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl
|
|||
idGameLocal::InitFromSaveGame
|
||||
=================
|
||||
*/
|
||||
bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) {
|
||||
bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) {
|
||||
int i;
|
||||
int num;
|
||||
idEntity *ent;
|
||||
|
@ -1242,6 +1244,8 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo
|
|||
|
||||
Printf( "----- Game Map Init SaveGame -----\n" );
|
||||
|
||||
//exposing editor flag so debugger does not miss any script calls during load/startup
|
||||
editors = activeEditors;
|
||||
gamestate = GAMESTATE_STARTUP;
|
||||
|
||||
gameRenderWorld = renderWorld;
|
||||
|
@ -2215,14 +2219,17 @@ void idGameLocal::SortActiveEntityList( void ) {
|
|||
idGameLocal::RunFrame
|
||||
================
|
||||
*/
|
||||
gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds ) {
|
||||
idEntity * ent;
|
||||
int num;
|
||||
float ms;
|
||||
idTimer timer_think, timer_events, timer_singlethink;
|
||||
gameReturn_t ret;
|
||||
idPlayer *player;
|
||||
const renderView_t *view;
|
||||
gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds, int activeEditors ) {
|
||||
idEntity * ent;
|
||||
int num;
|
||||
float ms;
|
||||
idTimer timer_think, timer_events, timer_singlethink;
|
||||
gameReturn_t ret;
|
||||
idPlayer *player;
|
||||
const renderView_t *view;
|
||||
|
||||
//exposing editor flag so debugger does not miss any script calls during load/startup
|
||||
editors = activeEditors;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ( isMultiplayer ) {
|
||||
|
|
|
@ -293,7 +293,7 @@ public:
|
|||
|
||||
idEntityPtr<idEntity> lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f
|
||||
int lastGUI; // last GUI on the lastGUIEnt
|
||||
|
||||
int editors; // Mirrored editors flags from common to determine which editors are running
|
||||
// ---------------------- Public idGame Interface -------------------
|
||||
|
||||
idGameLocal();
|
||||
|
@ -308,13 +308,13 @@ public:
|
|||
|
||||
virtual const idDict & GetPersistentPlayerInfo( int clientNum );
|
||||
virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo );
|
||||
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed );
|
||||
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile );
|
||||
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed, int activeEditors);
|
||||
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors);
|
||||
virtual void SaveGame( idFile *saveGameFile );
|
||||
virtual void MapShutdown( void );
|
||||
virtual void CacheDictionaryMedia( const idDict *dict );
|
||||
virtual void SpawnPlayer( int clientNum );
|
||||
virtual gameReturn_t RunFrame( const usercmd_t *clientCmds );
|
||||
virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors);
|
||||
virtual bool Draw( int clientNum );
|
||||
virtual escReply_t HandleESC( idUserInterface **gui );
|
||||
virtual idUserInterface *StartMenu( void );
|
||||
|
|
|
@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "script/Script_Interpreter.h"
|
||||
|
||||
#include "framework/FileSystem.h"
|
||||
|
||||
/*
|
||||
================
|
||||
idInterpreter::idInterpreter()
|
||||
|
@ -183,7 +185,6 @@ idInterpreter::GetRegisterValue
|
|||
Returns a string representation of the value of the register. This is
|
||||
used primarily for the debugger and debugging
|
||||
|
||||
//FIXME: This is pretty much wrong. won't access data in most situations.
|
||||
================
|
||||
*/
|
||||
bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDepth ) {
|
||||
|
@ -191,17 +192,17 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep
|
|||
idVarDef *d;
|
||||
char funcObject[ 1024 ];
|
||||
char *funcName;
|
||||
const idVarDef *scope;
|
||||
const idVarDef *scope = NULL;
|
||||
const idVarDef *scopeObj;
|
||||
const idTypeDef *field;
|
||||
const idScriptObject *obj;
|
||||
const function_t *func;
|
||||
|
||||
out.Empty();
|
||||
|
||||
|
||||
if ( scopeDepth == -1 ) {
|
||||
scopeDepth = callStackDepth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( scopeDepth == callStackDepth ) {
|
||||
func = currentFunction;
|
||||
} else {
|
||||
|
@ -215,35 +216,44 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep
|
|||
funcName = strstr( funcObject, "::" );
|
||||
if ( funcName ) {
|
||||
*funcName = '\0';
|
||||
scope = gameLocal.program.GetDef( NULL, funcObject, &def_namespace );
|
||||
funcName += 2;
|
||||
scopeObj = gameLocal.program.GetDef( NULL, funcObject, &def_namespace );
|
||||
funcName += 2;
|
||||
if ( scopeObj )
|
||||
{
|
||||
scope = gameLocal.program.GetDef( NULL, funcName, scopeObj );
|
||||
}
|
||||
} else {
|
||||
funcName = funcObject;
|
||||
scope = &def_namespace;
|
||||
scope = gameLocal.program.GetDef( NULL, func->Name(), &def_namespace );
|
||||
scopeObj = NULL;
|
||||
}
|
||||
|
||||
// Get the function from the object
|
||||
d = gameLocal.program.GetDef( NULL, funcName, scope );
|
||||
if ( !d ) {
|
||||
if ( !scope )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the variable itself and check various namespaces
|
||||
d = gameLocal.program.GetDef( NULL, name, d );
|
||||
if ( !d ) {
|
||||
if ( scope == &def_namespace ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d = gameLocal.program.GetDef( NULL, name, scope );
|
||||
if ( !d ) {
|
||||
d = gameLocal.program.GetDef( NULL, name, &def_namespace );
|
||||
if ( !d ) {
|
||||
return false;
|
||||
d = gameLocal.program.GetDef( NULL, name, scope );
|
||||
|
||||
// Check the objects for it if it wasnt local to the function
|
||||
if ( !d )
|
||||
{
|
||||
for ( ; scopeObj && scopeObj->TypeDef()->SuperClass(); scopeObj = scopeObj->TypeDef()->SuperClass()->def )
|
||||
{
|
||||
d = gameLocal.program.GetDef( NULL, name, scopeObj );
|
||||
if ( d )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !d )
|
||||
{
|
||||
out = "???";
|
||||
return false;
|
||||
}
|
||||
|
||||
reg = GetVariable( d );
|
||||
switch( d->Type() ) {
|
||||
case ev_float:
|
||||
|
@ -256,7 +266,7 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep
|
|||
break;
|
||||
|
||||
case ev_vector:
|
||||
if ( reg.vectorPtr ) {
|
||||
if ( reg.vectorPtr ) {
|
||||
out = va( "%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z );
|
||||
} else {
|
||||
out = "0,0,0";
|
||||
|
@ -274,30 +284,55 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep
|
|||
break;
|
||||
|
||||
case ev_field:
|
||||
{
|
||||
idEntity* entity;
|
||||
idScriptObject* obj;
|
||||
|
||||
if ( scope == &def_namespace ) {
|
||||
// should never happen, but handle it safely anyway
|
||||
return false;
|
||||
}
|
||||
|
||||
field = scope->TypeDef()->GetParmType( reg.ptrOffset )->FieldType();
|
||||
obj = *reinterpret_cast<const idScriptObject **>( &localstack[ callStack[ callStackDepth ].stackbase ] );
|
||||
if ( !field || !obj ) {
|
||||
field = d->TypeDef()->FieldType();
|
||||
entity = GetEntity ( *((int*)&localstack[ localstackBase ]) );
|
||||
if ( !entity || !field )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
obj = &entity->scriptObject;
|
||||
if ( !obj ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ( field->Type() ) {
|
||||
case ev_boolean:
|
||||
out = va( "%d", *( reinterpret_cast<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_boolean:
|
||||
out = va( "%d", *( reinterpret_cast<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_string: {
|
||||
const char* str;
|
||||
str = reinterpret_cast<const char*>( &obj->data[ reg.ptrOffset ] );
|
||||
if ( !str ) {
|
||||
out = "\"\"";
|
||||
} else {
|
||||
out = "\"";
|
||||
out += str;
|
||||
out += "\"";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ev_string:
|
||||
if ( reg.stringPtr ) {
|
||||
|
@ -969,6 +1004,19 @@ bool idInterpreter::Execute( void ) {
|
|||
// next statement
|
||||
st = &gameLocal.program.GetStatement( instructionPointer );
|
||||
|
||||
if (gameLocal.editors & EDITOR_DEBUGGER ) {
|
||||
common->DebuggerCheckBreakpoint ( this, &gameLocal.program, instructionPointer );
|
||||
} else if ( g_debugScript.GetBool ( ) ) {
|
||||
static int lastLineNumber = -1;
|
||||
if ( lastLineNumber != gameLocal.program.GetStatement ( instructionPointer ).linenumber ) {
|
||||
gameLocal.Printf ( "%s (%d)\n",
|
||||
gameLocal.program.GetFilename ( gameLocal.program.GetStatement ( instructionPointer ).file ),
|
||||
gameLocal.program.GetStatement ( instructionPointer ).linenumber
|
||||
);
|
||||
lastLineNumber = gameLocal.program.GetStatement ( instructionPointer ).linenumber;
|
||||
}
|
||||
}
|
||||
|
||||
switch( st->op ) {
|
||||
case OP_RETURN:
|
||||
LeaveFunction( st->a );
|
||||
|
@ -1833,3 +1881,98 @@ bool idInterpreter::Execute( void ) {
|
|||
|
||||
return threadDying;
|
||||
}
|
||||
|
||||
bool idGameEdit::CheckForBreakPointHit(const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth) const
|
||||
{
|
||||
return ( ( interpreter->GetCurrentFunction ( ) == function1 ||
|
||||
interpreter->GetCurrentFunction ( ) == function2)&&
|
||||
( interpreter->GetCallstackDepth ( ) <= depth) );
|
||||
}
|
||||
|
||||
bool idGameEdit::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const
|
||||
{
|
||||
|
||||
return ( const_cast<idProgram*>(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 );
|
||||
}
|
||||
|
||||
bool idGameEdit::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const
|
||||
{
|
||||
return const_cast<idInterpreter*>(interpreter)->GetRegisterValue(name, out, scopeDepth);
|
||||
}
|
||||
|
||||
const idThread* idGameEdit::GetThread(const idInterpreter* interpreter) const
|
||||
{
|
||||
return interpreter->GetThread();
|
||||
}
|
||||
|
||||
void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram * program, int instructionPtr)
|
||||
{
|
||||
const statement_t* st;
|
||||
const function_t* func;
|
||||
|
||||
func = stack->f;
|
||||
|
||||
// If the function is unknown then just fill in with default data.
|
||||
if ( !func )
|
||||
{
|
||||
msg->WriteString ( "<UNKNOWN>" );
|
||||
msg->WriteString ( "<UNKNOWN>" );
|
||||
msg->WriteInt ( 0 );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->WriteString ( va("%s( )", func->Name() ) );
|
||||
}
|
||||
|
||||
if (stack->s == -1) //this is a fake stack created by debugger, use intruction pointer for retrieval.
|
||||
st = &const_cast<idProgram*>( program )->GetStatement( instructionPtr );
|
||||
else // Use the calling statement as the filename and linenumber where the call was made from
|
||||
st = &const_cast<idProgram*>( program )->GetStatement ( stack->s );
|
||||
|
||||
if ( st )
|
||||
{
|
||||
idStr qpath = const_cast<idProgram*>( program )->GetFilename( st->file );
|
||||
if (idStr::FindChar( qpath, ':' ) != -1)
|
||||
qpath = fileSystem->OSPathToRelativePath( qpath.c_str() );
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
msg->WriteString( qpath );
|
||||
msg->WriteInt( st->linenumber );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->WriteString ( "<UNKNOWN>" );
|
||||
msg->WriteInt ( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr)
|
||||
{
|
||||
int i;
|
||||
prstack_s temp;
|
||||
|
||||
msg->WriteShort((int)interpreter->GetCallstackDepth( ) );
|
||||
|
||||
// write out the current function
|
||||
temp.f = interpreter->GetCurrentFunction( );
|
||||
temp.s = -1;
|
||||
temp.stackbase = 0;
|
||||
MSG_WriteCallstackFunc( msg, &temp, program, instructionPtr);
|
||||
|
||||
// Run through all of the callstack and write each to the msg
|
||||
for (i = interpreter->GetCallstackDepth() - 1; i > 0; i--)
|
||||
{
|
||||
MSG_WriteCallstackFunc( msg, interpreter->GetCallstack( ) + i, program, instructionPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int idGameEdit::GetInterpreterCallStackDepth(const idInterpreter* interpreter)
|
||||
{
|
||||
return interpreter->GetCallstackDepth();
|
||||
}
|
||||
|
||||
const function_t* idGameEdit::GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth/* = -1*/)
|
||||
{
|
||||
return interpreter->GetCallstack( )[ stackDepth > -1 ? stackDepth :interpreter->GetCallstackDepth( ) ].f;
|
||||
}
|
|
@ -34,7 +34,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "idlib/containers/HashIndex.h"
|
||||
#include "idlib/math/Vector.h"
|
||||
|
||||
#include "GameBase.h"
|
||||
//#include "GameBase.h"
|
||||
|
||||
class idEventDef;
|
||||
class idVarDef;
|
||||
|
|
|
@ -28,11 +28,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "sys/platform.h"
|
||||
|
||||
#include "gamesys/SysCvar.h"
|
||||
#include "Player.h"
|
||||
#include "Camera.h"
|
||||
#include "game/gamesys/SysCvar.h"
|
||||
#include "game/Player.h"
|
||||
#include "game/Camera.h"
|
||||
|
||||
#include "script/Script_Thread.h"
|
||||
#include "Script_Thread.h"
|
||||
|
||||
const idEventDef EV_Thread_Execute( "<execute>", NULL );
|
||||
const idEventDef EV_Thread_SetCallback( "<script_setcallback>", NULL );
|
||||
|
@ -1841,3 +1841,49 @@ void idThread::Event_InfluenceActive( void ) {
|
|||
idThread::ReturnInt( false );
|
||||
}
|
||||
}
|
||||
|
||||
int idGameEdit::ThreadGetNum(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadNum();
|
||||
}
|
||||
|
||||
const char* idGameEdit::ThreadGetName(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadName();
|
||||
}
|
||||
|
||||
int idGameEdit::GetTotalScriptThreads() const
|
||||
{
|
||||
return idThread::GetThreads().Num();
|
||||
}
|
||||
|
||||
const idThread* idGameEdit::GetThreadByIndex(int index) const
|
||||
{
|
||||
return idThread::GetThreads()[index];
|
||||
}
|
||||
|
||||
bool idGameEdit::ThreadIsDoneProcessing(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDoneProcessing();
|
||||
}
|
||||
|
||||
bool idGameEdit::ThreadIsWaiting(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsWaiting();
|
||||
}
|
||||
|
||||
bool idGameEdit::ThreadIsDying(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDying();
|
||||
}
|
||||
|
||||
void idGameEdit::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter)
|
||||
{
|
||||
msg->WriteString(const_cast<idThread*>(thread)->GetThreadName());
|
||||
msg->WriteInt(const_cast<idThread*>(thread)->GetThreadNum());
|
||||
|
||||
msg->WriteBits((int)(thread == interpreter->GetThread()), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDoneProcessing(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsWaiting(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDying(), 1);
|
||||
}
|
|
@ -35,7 +35,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <SDL_endian.h>
|
||||
#include <SDL2\SDL_endian.h>
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "idlib/math/Vector.h"
|
||||
|
|
|
@ -149,17 +149,16 @@ END
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DBG_ABOUT DIALOGEX 0, 0, 222, 71
|
||||
IDD_DBG_ABOUT DIALOGEX 0, 0, 250, 80
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
|
||||
WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About Script Debugger"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Script Debugger",IDC_STATIC,35,7,81,8
|
||||
LTEXT "Version 0.01",IDC_STATIC,35,17,41,8
|
||||
LTEXT "Original version by Raven",IDC_STATIC,35,
|
||||
28,134,8
|
||||
DEFPUSHBUTTON "OK",IDOK,165,50,50,14
|
||||
LTEXT "Version 1.0",IDC_STATIC,35,17,41,8
|
||||
LTEXT "Dhewm3 version by Harrie van Ginneken", IDC_STATIC, 35, 38, 134, 8
|
||||
DEFPUSHBUTTON "OK",IDOK,165,60,50,14
|
||||
ICON 5098,IDC_STATIC,7,7,20,20
|
||||
END
|
||||
|
||||
|
|
|
@ -269,8 +269,6 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
|||
BEGIN
|
||||
LTEXT "GUI Editor",IDC_STATIC,35,7,62,8
|
||||
LTEXT "Version 0.15",IDC_STATIC,35,17,41,8
|
||||
LTEXT "Original version by Raven",IDC_STATIC,35,
|
||||
28,134,8
|
||||
DEFPUSHBUTTON "OK",IDOK,165,50,50,14
|
||||
ICON IDI_GUIED,IDC_STATIC,7,7,20,20
|
||||
END
|
||||
|
|
|
@ -629,7 +629,30 @@ Sys_DLL_GetProcAddress
|
|||
=====================
|
||||
*/
|
||||
void *Sys_DLL_GetProcAddress( uintptr_t dllHandle, const char *procName ) {
|
||||
return (void *)GetProcAddress( (HINSTANCE)dllHandle, procName );
|
||||
void * adr = (void*)GetProcAddress((HINSTANCE)dllHandle, procName);
|
||||
if (!adr)
|
||||
{
|
||||
DWORD e = GetLastError();
|
||||
LPVOID msgBuf = nullptr;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
e,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&msgBuf,
|
||||
0, NULL);
|
||||
|
||||
idStr errorStr = va("[%i (0x%X)]\t%s", e, e, msgBuf);
|
||||
|
||||
if (errorStr.Length())
|
||||
common->Warning("GetProcAddress( %i %s) Failed ! %s", dllHandle, procName, errorStr.c_str());
|
||||
|
||||
::LocalFree(msgBuf);
|
||||
}
|
||||
return adr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -969,7 +992,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// Launch the script debugger
|
||||
if ( strstr( GetCommandLine(), "+debugger" ) ) {
|
||||
// DebuggerClientInit( lpCmdLine );
|
||||
DebuggerClientInit(GetCommandLine());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -392,7 +392,8 @@ void rvOpenFileDialog::SetFilter ( const char* s )
|
|||
if ( semi != -1 )
|
||||
{
|
||||
filter = filters.Left ( semi );
|
||||
filters = filters.Right ( filters.Length ( ) - semi );
|
||||
filters = filters.Right ( filters.Length ( ) - (semi + 1));
|
||||
filters.Strip(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -37,8 +37,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
rvDebuggerApp::rvDebuggerApp
|
||||
================
|
||||
*/
|
||||
rvDebuggerApp::rvDebuggerApp ( ) :
|
||||
mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" )
|
||||
rvDebuggerApp::rvDebuggerApp ( ) //:
|
||||
//mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" )
|
||||
{
|
||||
mInstance = NULL;
|
||||
mDebuggerWindow = NULL;
|
||||
|
|
|
@ -29,7 +29,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define DEBUGGERAPP_H_
|
||||
|
||||
#include "../../sys/win32/win_local.h"
|
||||
#include "../../framework/sync/Msg.h"
|
||||
//#include "../../framework/sync/Msg.h"
|
||||
|
||||
#ifndef REGISTRYOPTIONS_H_
|
||||
#include "../common/RegistryOptions.h"
|
||||
|
@ -49,13 +49,15 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
// These were changed to static by ID so to make it easy we just throw them
|
||||
// in this header
|
||||
const int MAX_MSGLEN = 1400;
|
||||
// we need a lot to be able to list all threads in mars_city1
|
||||
const int MAX_MSGLEN = 8600;
|
||||
|
||||
class rvDebuggerApp
|
||||
{
|
||||
public:
|
||||
|
||||
rvDebuggerApp ( );
|
||||
~rvDebuggerApp();
|
||||
|
||||
bool Initialize ( HINSTANCE hInstance );
|
||||
int Run ( void );
|
||||
|
|
|
@ -28,6 +28,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#define DEBUGGERBREAKPOINT_H_
|
||||
|
||||
class idProgram;
|
||||
|
||||
class rvDebuggerBreakpoint
|
||||
{
|
||||
public:
|
||||
|
@ -46,7 +48,6 @@ protected:
|
|||
int mID;
|
||||
int mLineNumber;
|
||||
idStr mFilename;
|
||||
|
||||
private:
|
||||
|
||||
static int mNextID;
|
||||
|
|
|
@ -73,7 +73,7 @@ bool rvDebuggerClient::Initialize ( void )
|
|||
}
|
||||
|
||||
// Server must be running on the local host on port 28980
|
||||
Sys_StringToNetAdr ( "localhost", &mServerAdrt, true );
|
||||
Sys_StringToNetAdr ( "localhost", &mServerAdr, true );
|
||||
mServerAdr.port = 27980;
|
||||
|
||||
// Attempt to let the server know we are here. The server may not be running so this
|
||||
|
@ -110,25 +110,29 @@ Process all incomding messages from the debugger server
|
|||
bool rvDebuggerClient::ProcessMessages ( void )
|
||||
{
|
||||
netadr_t adrFrom;
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
msg.SetSize(MAX_MSGLEN);
|
||||
msg.BeginReading();
|
||||
|
||||
int msgSize;
|
||||
// Check for pending udp packets on the debugger port
|
||||
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
|
||||
while ( mPort.GetPacket ( adrFrom, buffer,msgSize, MAX_MSGLEN) )
|
||||
{
|
||||
unsigned short command;
|
||||
short command;
|
||||
msg.Init(buffer, sizeof(buffer));
|
||||
msg.SetSize(msgSize);
|
||||
msg.BeginReading();
|
||||
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase ( adrFrom, mServerAdr ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
command = msg.ReadShort ( );
|
||||
|
||||
command = (unsigned short) MSG_ReadShort ( &msg );
|
||||
|
||||
// Is this what we are waiting for?
|
||||
// Is this what we are waiting for?
|
||||
if ( command == mWaitFor )
|
||||
{
|
||||
mWaitFor = DBMSG_UNKNOWN;
|
||||
|
@ -168,17 +172,39 @@ bool rvDebuggerClient::ProcessMessages ( void )
|
|||
case DBMSG_INSPECTVARIABLE:
|
||||
HandleInspectVariable ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_REMOVEBREAKPOINT:
|
||||
HandleRemoveBreakpoint( &msg );
|
||||
break;
|
||||
case DBMSG_INSPECTSCRIPTS:
|
||||
HandleInspectScripts( &msg );
|
||||
break;
|
||||
}
|
||||
|
||||
// Give the window a chance to process the message
|
||||
msg.readcount = 0;
|
||||
msg.bit = 0;
|
||||
msg.SetReadCount(0);
|
||||
msg.SetReadBit(0);
|
||||
gDebuggerApp.GetWindow().ProcessNetMessage ( &msg );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rvDebuggerClient::HandleRemoveBreakpoint(idBitMsg* msg)
|
||||
{
|
||||
long lineNumber;
|
||||
char filename[MAX_PATH];
|
||||
|
||||
// Read the breakpoint info
|
||||
|
||||
lineNumber = msg->ReadInt();
|
||||
msg->ReadString(filename, MAX_PATH);
|
||||
|
||||
rvDebuggerBreakpoint* bp = FindBreakpoint(filename, lineNumber);
|
||||
if(bp)
|
||||
RemoveBreakpoint(bp->GetID());
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleBreak
|
||||
|
@ -187,19 +213,22 @@ Handle the DBMSG_BREAK message send from the server. This message is handled
|
|||
by caching the file and linenumber where the break occured.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleBreak ( msg_t* msg )
|
||||
void rvDebuggerClient::HandleBreak ( idBitMsg* msg )
|
||||
{
|
||||
char filename[MAX_PATH];
|
||||
|
||||
mBreak = true;
|
||||
|
||||
// Line number
|
||||
mBreakLineNumber = MSG_ReadInt ( msg );
|
||||
mBreakLineNumber = msg->ReadInt ( );
|
||||
|
||||
// Filename
|
||||
MSG_ReadString ( msg, filename, MAX_PATH );
|
||||
msg->ReadString ( filename, MAX_PATH );
|
||||
mBreakFilename = filename;
|
||||
|
||||
int ptr32b = msg->ReadInt();
|
||||
mBreakProgram = (idProgram*)ptr32b;
|
||||
|
||||
// Clear the variables
|
||||
mVariables.Clear ( );
|
||||
|
||||
|
@ -211,6 +240,26 @@ void rvDebuggerClient::HandleBreak ( msg_t* msg )
|
|||
WaitFor ( DBMSG_INSPECTTHREADS, 2000 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::InspectScripts
|
||||
|
||||
Instructs the client to inspect the loaded scripts
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::InspectScripts ( void )
|
||||
{
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
msg.Init(buffer, sizeof(buffer));
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort((short)DBMSG_INSPECTSCRIPTS);
|
||||
SendPacket(msg.GetData(), msg.GetSize());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::InspectVariable
|
||||
|
@ -222,15 +271,41 @@ will in turn respond back to the client with the variable value
|
|||
*/
|
||||
void rvDebuggerClient::InspectVariable ( const char* name, int callstackDepth )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
|
||||
MSG_WriteShort ( &msg, (short)(mCallstack.Num()-callstackDepth) );
|
||||
MSG_WriteString ( &msg, name );
|
||||
msg.Init( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort ( (short)DBMSG_INSPECTVARIABLE );
|
||||
msg.WriteShort ( (short)(mCallstack.Num()-callstackDepth) );
|
||||
msg.WriteString ( name );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize());
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::HandleInspectScripts
|
||||
|
||||
Handle the message DBMSG_INSPECTSCRIPTS being sent from the server. This message
|
||||
is handled by adding the script entries to a list for later lookup.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectScripts( idBitMsg* msg )
|
||||
{
|
||||
int totalScripts;
|
||||
|
||||
mServerScripts.Clear();
|
||||
|
||||
// Read all of the callstack entries specfied in the message
|
||||
for (totalScripts = msg->ReadInt(); totalScripts > 0; totalScripts--)
|
||||
{
|
||||
char temp[1024];
|
||||
|
||||
// Script Name
|
||||
msg->ReadString(temp, 1024);
|
||||
mServerScripts.Append(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -241,29 +316,29 @@ Handle the message DBMSG_INSPECTCALLSTACK being sent from the server. This mess
|
|||
is handled by adding the callstack entries to a list for later lookup.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectCallstack ( msg_t* msg )
|
||||
void rvDebuggerClient::HandleInspectCallstack ( idBitMsg* msg )
|
||||
{
|
||||
int depth;
|
||||
|
||||
ClearCallstack ( );
|
||||
|
||||
// Read all of the callstack entries specfied in the message
|
||||
for ( depth = (short)MSG_ReadShort ( msg ) ; depth > 0; depth -- )
|
||||
for ( depth = (short)msg->ReadShort ( ) ; depth > 0; depth -- )
|
||||
{
|
||||
rvDebuggerCallstack* entry = new rvDebuggerCallstack;
|
||||
|
||||
char temp[1024];
|
||||
|
||||
// Function name
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
entry->mFunction = temp;
|
||||
msg->ReadString ( temp, 1024 );
|
||||
entry->mFunction = idStr(temp);
|
||||
|
||||
// Filename
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
entry->mFilename = temp;
|
||||
msg->ReadString ( temp, 1024 );
|
||||
entry->mFilename = idStr(temp);
|
||||
|
||||
// Line Number
|
||||
entry->mLineNumber = MSG_ReadInt ( msg );
|
||||
entry->mLineNumber = msg->ReadInt ( );
|
||||
|
||||
// Add to list
|
||||
mCallstack.Append ( entry );
|
||||
|
@ -278,31 +353,31 @@ Handle the message DBMSG_INSPECTTHREADS being sent from the server. This messag
|
|||
is handled by adding the list of threads to a list for later lookup.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectThreads ( msg_t* msg )
|
||||
void rvDebuggerClient::HandleInspectThreads ( idBitMsg* msg )
|
||||
{
|
||||
int count;
|
||||
|
||||
ClearThreads ( );
|
||||
|
||||
// Loop over the number of threads in the message
|
||||
for ( count = (short)MSG_ReadShort ( msg ) ; count > 0; count -- )
|
||||
for ( count = (short)msg->ReadShort ( ) ; count > 0; count -- )
|
||||
{
|
||||
rvDebuggerThread* entry = new rvDebuggerThread;
|
||||
|
||||
char temp[1024];
|
||||
|
||||
// Thread name
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
msg->ReadString ( temp, 1024 );
|
||||
entry->mName = temp;
|
||||
|
||||
// Thread ID
|
||||
entry->mID = MSG_ReadInt ( msg );
|
||||
entry->mID = msg->ReadInt ( );
|
||||
|
||||
// Thread state
|
||||
entry->mCurrent = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mDoneProcessing = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mWaiting = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mDying = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
entry->mCurrent = msg->ReadBits ( 1 ) ? true : false;
|
||||
entry->mDoneProcessing = msg->ReadBits ( 1 ) ? true : false;
|
||||
entry->mWaiting = msg->ReadBits ( 1 ) ? true : false;
|
||||
entry->mDying = msg->ReadBits ( 1 ) ? true : false;
|
||||
|
||||
// Add thread to list
|
||||
mThreads.Append ( entry );
|
||||
|
@ -317,15 +392,15 @@ Handle the message DBMSG_INSPECTVARIABLE being sent from the server. This messa
|
|||
is handled by adding the inspected variable to a dictionary for later lookup
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::HandleInspectVariable ( msg_t* msg )
|
||||
void rvDebuggerClient::HandleInspectVariable ( idBitMsg* msg )
|
||||
{
|
||||
char var[1024];
|
||||
char value[1024];
|
||||
int callDepth;
|
||||
|
||||
callDepth = (short)MSG_ReadShort ( msg );
|
||||
MSG_ReadString ( msg, var, 1024 );
|
||||
MSG_ReadString ( msg, value, 1024 );
|
||||
callDepth = (short)msg->ReadShort ( );
|
||||
msg->ReadString ( var, 1024 );
|
||||
msg->ReadString ( value, 1024 );
|
||||
|
||||
mVariables.Set ( va("%d:%s", mCallstack.Num()-callDepth, var), value );
|
||||
}
|
||||
|
@ -463,13 +538,14 @@ Send a message with no data to the debugger server
|
|||
*/
|
||||
void rvDebuggerClient::SendMessage ( EDebuggerMessage dbmsg )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)dbmsg );
|
||||
msg.Init ( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting ( );
|
||||
msg.WriteShort ( (short)dbmsg );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -504,7 +580,7 @@ Send an individual breakpoint over to the debugger server
|
|||
*/
|
||||
void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
if ( !mConnected )
|
||||
|
@ -512,14 +588,15 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOn
|
|||
return;
|
||||
}
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_ADDBREAKPOINT );
|
||||
MSG_WriteBits ( &msg, onceOnly?1:0, 1 );
|
||||
MSG_WriteInt ( &msg, (unsigned long) bp.GetLineNumber ( ) );
|
||||
MSG_WriteInt ( &msg, bp.GetID ( ) );
|
||||
MSG_WriteString ( &msg, bp.GetFilename() );
|
||||
msg.Init( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort ( (short)DBMSG_ADDBREAKPOINT );
|
||||
msg.WriteBits ( onceOnly?1:0, 1 );
|
||||
msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) );
|
||||
msg.WriteInt ( bp.GetID ( ) );
|
||||
msg.WriteString ( bp.GetFilename() );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -531,7 +608,7 @@ Sends a remove breakpoint message to the debugger server
|
|||
*/
|
||||
void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
if ( !mConnected )
|
||||
|
@ -539,11 +616,12 @@ void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp )
|
|||
return;
|
||||
}
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_REMOVEBREAKPOINT );
|
||||
MSG_WriteInt ( &msg, bp.GetID() );
|
||||
msg.Init ( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting( );
|
||||
msg.WriteShort ( (short)DBMSG_REMOVEBREAKPOINT );
|
||||
msg.WriteInt ( bp.GetID() );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -28,6 +28,9 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#ifndef DEBUGGERCLIENT_H_
|
||||
#define DEBUGGERCLIENT_H_
|
||||
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#include "idlib/containers/StrList.h"
|
||||
|
||||
class rvDebuggerCallstack
|
||||
{
|
||||
public:
|
||||
|
@ -49,9 +52,6 @@ public:
|
|||
bool mDoneProcessing;
|
||||
};
|
||||
|
||||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#endif
|
||||
|
||||
typedef idList<rvDebuggerCallstack*> rvDebuggerCallstackList;
|
||||
typedef idList<rvDebuggerThread*> rvDebuggerThreadList;
|
||||
|
@ -75,12 +75,14 @@ public:
|
|||
int GetActiveBreakpointID ( void );
|
||||
const char* GetBreakFilename ( void );
|
||||
int GetBreakLineNumber ( void );
|
||||
idProgram* GetBreakProgram ( void );
|
||||
rvDebuggerCallstackList& GetCallstack ( void );
|
||||
rvDebuggerThreadList& GetThreads ( void );
|
||||
const char* GetVariableValue ( const char* name, int stackDepth );
|
||||
idStrList& GetServerScripts ( void );
|
||||
|
||||
void InspectVariable ( const char* name, int callstackDepth );
|
||||
|
||||
void InspectScripts ( void );
|
||||
void Break ( void );
|
||||
void Resume ( void );
|
||||
void StepInto ( void );
|
||||
|
@ -110,6 +112,7 @@ protected:
|
|||
int mBreakID;
|
||||
int mBreakLineNumber;
|
||||
idStr mBreakFilename;
|
||||
idProgram* mBreakProgram;
|
||||
|
||||
idDict mVariables;
|
||||
|
||||
|
@ -119,6 +122,8 @@ protected:
|
|||
|
||||
EDebuggerMessage mWaitFor;
|
||||
|
||||
idStrList mServerScripts;
|
||||
|
||||
private:
|
||||
|
||||
void ClearCallstack ( void );
|
||||
|
@ -127,10 +132,13 @@ private:
|
|||
void UpdateWatches ( void );
|
||||
|
||||
// Network message handlers
|
||||
void HandleBreak ( msg_t* msg );
|
||||
void HandleInspectCallstack ( msg_t* msg );
|
||||
void HandleInspectThreads ( msg_t* msg );
|
||||
void HandleInspectVariable ( msg_t* msg );
|
||||
void HandleBreak ( idBitMsg* msg );
|
||||
void HandleInspectScripts ( idBitMsg* msg );
|
||||
void HandleInspectCallstack ( idBitMsg* msg );
|
||||
void HandleInspectThreads ( idBitMsg* msg );
|
||||
void HandleInspectVariable ( idBitMsg* msg );
|
||||
void HandleGameDLLHandle ( idBitMsg* msg );
|
||||
void HandleRemoveBreakpoint ( idBitMsg* msg );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -183,6 +191,17 @@ ID_INLINE int rvDebuggerClient::GetBreakLineNumber ( void )
|
|||
return mBreakLineNumber;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetBreakProgram
|
||||
================
|
||||
*/
|
||||
ID_INLINE idProgram* rvDebuggerClient::GetBreakProgram(void)
|
||||
{
|
||||
return mBreakProgram;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetCallstack
|
||||
|
@ -286,4 +305,14 @@ ID_INLINE void rvDebuggerClient::SendPacket ( void* data, int size )
|
|||
mPort.SendPacket ( mServerAdr, data, size );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerClient::GetServerScripts
|
||||
================
|
||||
*/
|
||||
ID_INLINE idStrList& rvDebuggerClient::GetServerScripts( void )
|
||||
{
|
||||
return mServerScripts;
|
||||
}
|
||||
#endif // DEBUGGERCLIENT_H_
|
||||
|
|
|
@ -46,6 +46,7 @@ enum EDebuggerMessage
|
|||
DBMSG_INSPECTTHREADS,
|
||||
DBMSG_STEPOVER,
|
||||
DBMSG_STEPINTO,
|
||||
DBMSG_INSPECTSCRIPTS
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_MESSAGES_H_
|
|
@ -31,7 +31,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerScript.h"
|
||||
#include "../../game/script/Script_Program.h"
|
||||
#include "../../ui/Window.h"
|
||||
#include "../../ui/UserInterfaceLocal.h"
|
||||
|
||||
|
@ -57,6 +56,7 @@ rvDebuggerScript::~rvDebuggerScript ( void )
|
|||
Unload ( );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::Unload
|
||||
|
@ -72,10 +72,6 @@ void rvDebuggerScript::Unload ( void )
|
|||
{
|
||||
delete mInterface;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete mProgram;
|
||||
}
|
||||
|
||||
mContents = NULL;
|
||||
mProgram = NULL;
|
||||
|
@ -91,7 +87,7 @@ appropriate for the file being loaded. If the script cant be compiled
|
|||
the loading of the script fails
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerScript::Load ( const char* filename )
|
||||
bool rvDebuggerScript::Load ( const char* filename)
|
||||
{
|
||||
void* buffer;
|
||||
int size;
|
||||
|
@ -116,60 +112,7 @@ bool rvDebuggerScript::Load ( const char* filename )
|
|||
|
||||
// Cleanup
|
||||
fileSystem->FreeFile ( buffer );
|
||||
|
||||
// Now compile the script so we can tell what a valid line is, etc.. If its
|
||||
// a gui file then we need to parse it using the userinterface system rather
|
||||
// than the normal script compiler.
|
||||
try
|
||||
{
|
||||
// Parse the script using the script compiler
|
||||
mProgram = new idProgram;
|
||||
mProgram->BeginCompilation ( );
|
||||
mProgram->CompileFile ( SCRIPT_DEFAULT );
|
||||
|
||||
//BSM Nerve: Loads a game specific main script file
|
||||
idStr gamedir = cvarSystem->GetCVarString( "fs_game" );
|
||||
if(gamedir.Length() > 0) {
|
||||
|
||||
idStr scriptFile = va("script/%s_main.script", gamedir.c_str());
|
||||
if(fileSystem->ReadFile(scriptFile.c_str(), NULL) > 0) {
|
||||
mProgram.CompileFile(scriptFile.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make sure the file isnt already compiled before trying to compile it again
|
||||
for ( int f = mProgram->NumFilenames() - 1; f >= 0; f -- )
|
||||
{
|
||||
idStr qpath;
|
||||
qpath = fileSystem->OSPathToRelativePath ( mProgram->GetFilename ( f ) );
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
if ( !qpath.Cmp ( filename ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( f < 0 )
|
||||
{
|
||||
mProgram->CompileText ( filename, mContents, false );
|
||||
}
|
||||
|
||||
mProgram->FinishCompilation ( );
|
||||
}
|
||||
catch ( idException& )
|
||||
{
|
||||
// Failed to parse the script so fail to load the file
|
||||
delete mProgram;
|
||||
mProgram = NULL;
|
||||
delete[] mContents;
|
||||
mContents = NULL;
|
||||
|
||||
// TODO: Should cache the error for the dialog box
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -194,21 +137,8 @@ Determines whether or not the given line number within the script is a valid lin
|
|||
*/
|
||||
bool rvDebuggerScript::IsLineCode ( int linenumber )
|
||||
{
|
||||
int i;
|
||||
|
||||
assert ( mProgram );
|
||||
|
||||
// Run through all the statements in the program and see if any match the
|
||||
// linenumber that we are checking.
|
||||
for ( i = 0; i < mProgram->NumStatements ( ); i ++ )
|
||||
{
|
||||
if ( mProgram->GetStatement ( i ).linenumber == linenumber )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
//we let server decide.
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -43,21 +43,22 @@ public:
|
|||
|
||||
const char* GetFilename ( void );
|
||||
const char* GetContents ( void );
|
||||
|
||||
idProgram* GetProgram ( void );
|
||||
#if 0// Test code
|
||||
idProgram& GetProgram ( void );
|
||||
#endif
|
||||
|
||||
bool IsLineCode ( int linenumber );
|
||||
bool IsFileModified ( bool updateTime = false );
|
||||
|
||||
protected:
|
||||
|
||||
void Unload ( void );
|
||||
|
||||
idProgram* mProgram;
|
||||
idUserInterfaceLocal* mInterface;
|
||||
char* mContents;
|
||||
idStr mFilename;
|
||||
ID_TIME_T mModifiedTime;
|
||||
ID_TIME_T mModifiedTime;
|
||||
};
|
||||
|
||||
ID_INLINE const char* rvDebuggerScript::GetFilename ( void )
|
||||
|
@ -70,9 +71,10 @@ ID_INLINE const char* rvDebuggerScript::GetContents ( void )
|
|||
return mContents?mContents:"";
|
||||
}
|
||||
|
||||
ID_INLINE idProgram& rvDebuggerScript::GetProgram ( void )
|
||||
ID_INLINE idProgram* rvDebuggerScript::GetProgram ( void )
|
||||
{
|
||||
return *mProgram;
|
||||
return mProgram;
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUGGERSCRIPT_H_
|
|
@ -28,14 +28,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "tools/edit_gui_common.h"
|
||||
|
||||
|
||||
#include "../../game/gamesys/Event.h"
|
||||
#include "../../game/gamesys/Class.h"
|
||||
#include "../../game/script/Script_Program.h"
|
||||
#include "../../game/script/Script_Interpreter.h"
|
||||
#include "../../game/script/Script_Thread.h"
|
||||
#include "../../game/script/Script_Compiler.h"
|
||||
#include "../../framework/sync/Msg.h"
|
||||
#include "DebuggerApp.h"
|
||||
#include "DebuggerServer.h"
|
||||
|
||||
|
@ -144,15 +136,17 @@ Process all incoming network messages from the debugger client
|
|||
bool rvDebuggerServer::ProcessMessages ( void )
|
||||
{
|
||||
netadr_t adrFrom;
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
|
||||
// Check for pending udp packets on the debugger port
|
||||
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
|
||||
int msgSize;
|
||||
while ( mPort.GetPacket ( adrFrom, buffer, msgSize, MAX_MSGLEN) )
|
||||
{
|
||||
unsigned short command;
|
||||
short command;
|
||||
msg.Init(buffer, sizeof(buffer));
|
||||
msg.SetSize(msgSize);
|
||||
msg.BeginReading();
|
||||
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) )
|
||||
|
@ -160,23 +154,26 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
continue;
|
||||
}
|
||||
|
||||
command = (unsigned short) MSG_ReadShort ( &msg );
|
||||
command = msg.ReadShort( );
|
||||
|
||||
switch ( command )
|
||||
{
|
||||
case DBMSG_CONNECT:
|
||||
mConnected = true;
|
||||
SendMessage ( DBMSG_CONNECTED );
|
||||
|
||||
break;
|
||||
|
||||
case DBMSG_CONNECTED:
|
||||
mConnected = true;
|
||||
com_editors |= EDITOR_DEBUGGER;
|
||||
break;
|
||||
|
||||
case DBMSG_DISCONNECT:
|
||||
ClearBreakpoints ( );
|
||||
Resume ( );
|
||||
mConnected = false;
|
||||
com_editors &= ~EDITOR_DEBUGGER;
|
||||
break;
|
||||
|
||||
case DBMSG_ADDBREAKPOINT:
|
||||
|
@ -188,7 +185,7 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
break;
|
||||
|
||||
case DBMSG_RESUME:
|
||||
Resume ( );
|
||||
HandleResume ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_BREAK:
|
||||
|
@ -197,11 +194,11 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
|
||||
case DBMSG_STEPOVER:
|
||||
mBreakStepOver = true;
|
||||
mBreakStepOverDepth = mBreakInterpreter->GetCallstackDepth ( );
|
||||
mBreakStepOverFunc1 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()].f;
|
||||
if ( mBreakInterpreter->GetCallstackDepth() > 0 )
|
||||
mBreakStepOverDepth = gameEdit->GetInterpreterCallStackDepth(mBreakInterpreter);
|
||||
mBreakStepOverFunc1 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter);
|
||||
if (mBreakStepOverDepth)
|
||||
{
|
||||
mBreakStepOverFunc2 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()-1].f;
|
||||
mBreakStepOverFunc2 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter,mBreakStepOverDepth - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -226,6 +223,10 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
case DBMSG_INSPECTTHREADS:
|
||||
HandleInspectThreads ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTSCRIPTS:
|
||||
HandleInspectScripts( &msg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,13 +242,14 @@ Send a message with no data to the debugger server.
|
|||
*/
|
||||
void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)dbmsg );
|
||||
msg.Init( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort ( (short)dbmsg );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -255,11 +257,12 @@ void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg )
|
|||
rvDebuggerServer::HandleAddBreakpoint
|
||||
|
||||
Handle the DBMSG_ADDBREAKPOINT message being sent by the debugger client. This
|
||||
message is handled by adding a new breakpoint to the breakpoint list with the
|
||||
message is handled by first checking if it is valid
|
||||
and is added as a new breakpoint to the breakpoint list with the
|
||||
data supplied in the message.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg )
|
||||
void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg )
|
||||
{
|
||||
bool onceOnly = false;
|
||||
long lineNumber;
|
||||
|
@ -267,14 +270,28 @@ void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg )
|
|||
char filename[MAX_PATH];
|
||||
|
||||
// Read the breakpoint info
|
||||
onceOnly = MSG_ReadBits ( msg, 1 ) ? true : false;
|
||||
lineNumber = MSG_ReadInt ( msg );
|
||||
id = MSG_ReadInt ( msg );
|
||||
onceOnly = msg->ReadBits ( 1 ) ? true : false;
|
||||
lineNumber = msg->ReadInt ( );
|
||||
id = msg->ReadInt ( );
|
||||
|
||||
msg->ReadString ( filename, MAX_PATH );
|
||||
|
||||
//check for statement on requested breakpoint location
|
||||
if (!gameEdit->IsLineCode(filename, lineNumber))
|
||||
{
|
||||
idBitMsg msgOut;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
msgOut.Init(buffer, sizeof(buffer));
|
||||
msgOut.BeginWriting();
|
||||
msgOut.WriteShort((short)DBMSG_REMOVEBREAKPOINT);
|
||||
msgOut.WriteInt(lineNumber);
|
||||
msgOut.WriteString(filename);
|
||||
SendPacket(msgOut.GetData(), msgOut.GetSize());
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_ReadString ( msg, filename, MAX_PATH );
|
||||
|
||||
// Since breakpoints are used by both threads we need to
|
||||
// protect them with a crit section
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) );
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
|
@ -289,13 +306,13 @@ message is handled by removing the breakpoint that matches the given id from the
|
|||
list.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg )
|
||||
void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg )
|
||||
{
|
||||
int i;
|
||||
int id;
|
||||
|
||||
// ID that we are to remove
|
||||
id = MSG_ReadInt ( msg );
|
||||
id = msg->ReadInt ( );
|
||||
|
||||
// Since breakpoints are used by both threads we need to
|
||||
// protect them with a crit section
|
||||
|
@ -317,47 +334,16 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg )
|
|||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::MSG_WriteCallstackFunc
|
||||
rvDebuggerServer::HandleResume
|
||||
|
||||
Writes a single callstack entry to the given message
|
||||
Resume the game thread.
|
||||
================
|
||||
|
||||
*/
|
||||
void rvDebuggerServer::MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack )
|
||||
void rvDebuggerServer::HandleResume(idBitMsg* msg)
|
||||
{
|
||||
const statement_t* st;
|
||||
const function_t* func;
|
||||
|
||||
func = stack->f;
|
||||
|
||||
// If the function is unknown then just fill in with default data.
|
||||
if ( !func )
|
||||
{
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteInt ( msg, 0 );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteString ( msg, va("%s( ??? )", func->Name() ) );
|
||||
}
|
||||
|
||||
// Use the calling statement as the filename and linenumber where
|
||||
// the call was made from
|
||||
st = &mBreakProgram->GetStatement ( stack->s );
|
||||
if ( st )
|
||||
{
|
||||
idStr qpath;
|
||||
OSPathToRelativePath(mBreakProgram->GetFilename( st->file ), qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
MSG_WriteString ( msg, qpath );
|
||||
MSG_WriteInt ( msg, st->linenumber );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
MSG_WriteInt ( msg, 0 );
|
||||
}
|
||||
//Empty msg
|
||||
Resume();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -368,31 +354,18 @@ Handle an incoming inspect callstack message by sending a message
|
|||
back to the client with the callstack data.
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectCallstack ( msg_t* in_msg )
|
||||
void rvDebuggerServer::HandleInspectCallstack ( idBitMsg* msg )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msgOut;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
int i;
|
||||
prstack_t temp;
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTCALLSTACK );
|
||||
msgOut.Init(buffer, sizeof( buffer ) );
|
||||
msgOut.BeginWriting();
|
||||
msgOut.WriteShort ( (short)DBMSG_INSPECTCALLSTACK );
|
||||
|
||||
MSG_WriteShort ( &msg, (int)mBreakInterpreter->GetCallstackDepth ( ) );
|
||||
gameEdit->MSG_WriteInterpreterInfo(&msgOut, mBreakInterpreter, mBreakProgram, mBreakInstructionPointer);
|
||||
|
||||
// write out the current function
|
||||
temp.f = mBreakInterpreter->GetCurrentFunction ( );
|
||||
temp.s = 0;
|
||||
temp.stackbase = 0;
|
||||
MSG_WriteCallstackFunc ( &msg, &temp );
|
||||
|
||||
// Run through all of the callstack and write each to the msg
|
||||
for ( i = mBreakInterpreter->GetCallstackDepth ( ) - 1; i > 0; i -- )
|
||||
{
|
||||
MSG_WriteCallstackFunc ( &msg, mBreakInterpreter->GetCallstack ( ) + i );
|
||||
}
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket (msgOut.GetData(), msgOut.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -402,35 +375,51 @@ rvDebuggerServer::HandleInspectThreads
|
|||
Send the list of the current threads in the interpreter back to the debugger client
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectThreads ( msg_t* in_msg )
|
||||
void rvDebuggerServer::HandleInspectThreads ( idBitMsg* msg )
|
||||
{
|
||||
msg_t msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
int i;
|
||||
idBitMsg msgOut;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
int i;
|
||||
|
||||
// Initialize the message
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTTHREADS );
|
||||
msgOut.Init( buffer, sizeof( buffer ) );
|
||||
msgOut.SetAllowOverflow(true);
|
||||
msgOut.BeginWriting();
|
||||
msgOut.WriteShort ( (short)DBMSG_INSPECTTHREADS );
|
||||
|
||||
// Write the number of threads to the message
|
||||
MSG_WriteShort ( &msg, (int)idThread::GetThreads().Num() );
|
||||
msgOut.WriteShort ((short)gameEdit->GetTotalScriptThreads() );
|
||||
|
||||
// Loop through all of the threads and write their name and number to the message
|
||||
for ( i = 0; i < idThread::GetThreads().Num(); i ++ )
|
||||
for ( i = 0; i < gameEdit->GetTotalScriptThreads(); i ++ )
|
||||
{
|
||||
idThread* thread = idThread::GetThreads()[i];
|
||||
|
||||
MSG_WriteString ( &msg, thread->GetThreadName ( ) );
|
||||
MSG_WriteInt ( &msg, thread->GetThreadNum ( ) );
|
||||
|
||||
MSG_WriteBits ( &msg, (int)(thread == mBreakInterpreter->GetThread ( )), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsDoneProcessing(), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsWaiting(), 1 );
|
||||
MSG_WriteBits ( &msg, (int)thread->IsDying(), 1 );
|
||||
gameEdit->MSG_WriteThreadInfo(&msgOut,gameEdit->GetThreadByIndex(i), mBreakInterpreter);
|
||||
}
|
||||
|
||||
// Send off the inspect threads packet to the debugger client
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket (msgOut.GetData(), msgOut.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::HandleInspectScripts
|
||||
|
||||
Send the list of the current loaded scripts in the interpreter back to the debugger client
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectScripts( idBitMsg* msg )
|
||||
{
|
||||
idBitMsg msgOut;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
// Initialize the message
|
||||
msgOut.Init(buffer, sizeof(buffer));
|
||||
msgOut.BeginWriting();
|
||||
msgOut.WriteShort((short)DBMSG_INSPECTSCRIPTS);
|
||||
|
||||
gameEdit->MSG_WriteScriptList( &msgOut );
|
||||
|
||||
SendPacket(msgOut.GetData(), msgOut.GetSize());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -440,7 +429,7 @@ rvDebuggerServer::HandleInspectVariable
|
|||
Respondes to a request from the debugger client to inspect the value of a given variable
|
||||
================
|
||||
*/
|
||||
void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg )
|
||||
void rvDebuggerServer::HandleInspectVariable ( idBitMsg* msg )
|
||||
{
|
||||
char varname[256];
|
||||
int scopeDepth;
|
||||
|
@ -450,28 +439,29 @@ void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg )
|
|||
return;
|
||||
}
|
||||
|
||||
scopeDepth = (short)MSG_ReadShort ( in_msg );
|
||||
MSG_ReadString ( in_msg, varname, 256 );
|
||||
scopeDepth = (short)msg->ReadShort ( );
|
||||
msg->ReadString ( varname, 256 );
|
||||
|
||||
idStr varvalue;
|
||||
|
||||
msg_t msg;
|
||||
idBitMsg msgOut;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
// Initialize the message
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
|
||||
msgOut.Init( buffer, sizeof( buffer ) );
|
||||
msgOut.BeginWriting();
|
||||
msgOut.WriteShort ( (short)DBMSG_INSPECTVARIABLE );
|
||||
|
||||
if ( !mBreakInterpreter->GetRegisterValue ( varname, varvalue, scopeDepth ) )
|
||||
if (!gameEdit->GetRegisterValue(mBreakInterpreter, varname, varvalue, scopeDepth ) )
|
||||
{
|
||||
varvalue = "???";
|
||||
}
|
||||
|
||||
MSG_WriteShort ( &msg, (short)scopeDepth );
|
||||
MSG_WriteString ( &msg, varname );
|
||||
MSG_WriteString ( &msg, varvalue );
|
||||
msgOut.WriteShort ( (short)scopeDepth );
|
||||
msgOut.WriteString ( varname );
|
||||
msgOut.WriteString ( varvalue );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket (msgOut.GetData(), msgOut.GetSize() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -484,7 +474,6 @@ Check to see if any breakpoints have been hit. This includes "break next",
|
|||
*/
|
||||
void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
|
||||
{
|
||||
const statement_t* st;
|
||||
const char* filename;
|
||||
int i;
|
||||
|
||||
|
@ -492,23 +481,24 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// Grab the current statement and the filename that it came from
|
||||
st = &program->GetStatement ( instructionPointer );
|
||||
filename = program->GetFilename ( st->file );
|
||||
filename = gameEdit->GetFilenameForStatement(program, instructionPointer);
|
||||
int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer);
|
||||
|
||||
// Operate on lines, not statements
|
||||
if ( mLastStatementLine == st->linenumber && mLastStatementFile == st->file )
|
||||
if ( mLastStatementLine == linenumber && mLastStatementFile == filename)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Save the last visited line and file so we can prevent
|
||||
// double breaks on lines with more than one statement
|
||||
mLastStatementFile = idStr( st->file );
|
||||
mLastStatementLine = st->linenumber;
|
||||
mLastStatementFile = idStr(filename);
|
||||
mLastStatementLine = linenumber;
|
||||
|
||||
// Reset stepping when the last function on the callstack is returned from
|
||||
if ( st->op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 )
|
||||
if (gameEdit->ReturnedFromFunction(program, interpreter,instructionPointer))
|
||||
{
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
|
@ -517,6 +507,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
// See if we are supposed to break on the next script line
|
||||
if ( mBreakNext )
|
||||
{
|
||||
HandleInspectScripts(nullptr);
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
}
|
||||
|
@ -524,9 +515,8 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
// Only break on the same callstack depth and thread as the break over
|
||||
if ( mBreakStepOver )
|
||||
{
|
||||
if ( ( interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc1 ||
|
||||
interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc2 )&&
|
||||
( interpreter->GetCallstackDepth ( ) <= mBreakStepOverDepth ) )
|
||||
//virtual bool CheckForBreakpointHit(interpreter,function1,function2,depth)
|
||||
if (gameEdit->CheckForBreakPointHit(interpreter, mBreakStepOverFunc1, mBreakStepOverFunc2, mBreakStepOverDepth))
|
||||
{
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
|
@ -536,6 +526,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
// See if we are supposed to break on the next line
|
||||
if ( mBreakStepInto )
|
||||
{
|
||||
HandleInspectScripts(nullptr);
|
||||
// Break
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
|
@ -553,13 +544,13 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
rvDebuggerBreakpoint* bp = mBreakpoints[i];
|
||||
|
||||
// Skip if not match of the line number
|
||||
if ( st->linenumber != bp->GetLineNumber ( ) )
|
||||
if ( linenumber != bp->GetLineNumber ( ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if no match of the filename
|
||||
if ( idStr::Icmp ( bp->GetFilename(), qpath ) )
|
||||
if ( idStr::Icmp ( bp->GetFilename(), qpath.c_str() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -567,6 +558,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
// Pop out of the critical section so we dont get stuck
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
|
||||
HandleInspectScripts(nullptr);
|
||||
// We hit a breakpoint, so break
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
|
||||
|
@ -589,9 +581,8 @@ the game has been halted
|
|||
*/
|
||||
void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
|
||||
{
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
const statement_t* st;
|
||||
const char* filename;
|
||||
|
||||
// Clear all the break types
|
||||
|
@ -600,12 +591,10 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i
|
|||
mBreakNext = false;
|
||||
|
||||
// Grab the current statement and the filename that it came from
|
||||
st = &program->GetStatement ( instructionPointer );
|
||||
filename = program->GetFilename ( st->file );
|
||||
|
||||
idStr qpath;
|
||||
OSPathToRelativePath(filename, qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
filename = gameEdit->GetFilenameForStatement(program,instructionPointer);
|
||||
int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer);
|
||||
idStr fileStr = filename;
|
||||
fileStr.BackSlashesToSlashes();
|
||||
|
||||
// Give the mouse cursor back to the world
|
||||
Sys_GrabMouseCursor( false );
|
||||
|
@ -617,11 +606,13 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i
|
|||
mBreakInstructionPointer = instructionPointer;
|
||||
|
||||
// Inform the debugger of the breakpoint hit
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_BREAK );
|
||||
MSG_WriteInt ( &msg, st->linenumber );
|
||||
MSG_WriteString ( &msg, qpath );
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
msg.Init( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort ( (short)DBMSG_BREAK );
|
||||
msg.WriteInt ( linenumber );
|
||||
msg.WriteString ( fileStr.c_str() );
|
||||
msg.WriteInt( (int)mBreakProgram );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
|
||||
// Suspend the game thread. Since this will be called from within the main game thread
|
||||
// execution wont return until after the thread is resumed
|
||||
|
@ -642,6 +633,7 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i
|
|||
SetFocus ( win32.hWnd );
|
||||
|
||||
// Give the mouse cursor back to the game
|
||||
// HVG_Note : there be dragons here. somewhere.
|
||||
Sys_GrabMouseCursor( true );
|
||||
|
||||
// Clear all commands that were generated before we went into suspended mode. This is
|
||||
|
@ -703,12 +695,13 @@ void rvDebuggerServer::Print ( const char* text )
|
|||
return;
|
||||
}
|
||||
|
||||
msg_t msg;
|
||||
idBitMsg msg;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
|
||||
MSG_Init( &msg, buffer, sizeof( buffer ) );
|
||||
MSG_WriteShort ( &msg, (int)DBMSG_PRINT );
|
||||
MSG_WriteString ( &msg, text );
|
||||
msg.Init( buffer, sizeof( buffer ) );
|
||||
msg.BeginWriting();
|
||||
msg.WriteShort ( (short)DBMSG_PRINT );
|
||||
msg.WriteString ( text );
|
||||
|
||||
SendPacket ( msg.data, msg.cursize );
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
|
|
@ -28,20 +28,15 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#ifndef DEBUGGERSERVER_H_
|
||||
#define DEBUGGERSERVER_H_
|
||||
|
||||
#ifndef DEBUGGERMESSAGES_H_
|
||||
|
||||
#include "DebuggerMessages.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#endif
|
||||
#include "framework/Game.h"
|
||||
|
||||
#ifndef __GAME_LOCAL_H__
|
||||
#include "../../game/Game.h"
|
||||
#endif
|
||||
|
||||
class idInterpreter;
|
||||
class idProgram;
|
||||
|
||||
class function_t;
|
||||
typedef struct prstack_s prstack_t;
|
||||
|
||||
class rvDebuggerServer
|
||||
{
|
||||
|
@ -50,22 +45,40 @@ public:
|
|||
rvDebuggerServer ( );
|
||||
~rvDebuggerServer ( );
|
||||
|
||||
bool Initialize ( void );
|
||||
void Shutdown ( void );
|
||||
bool Initialize ( void );
|
||||
void Shutdown ( void );
|
||||
|
||||
bool ProcessMessages ( void );
|
||||
bool ProcessMessages ( void );
|
||||
|
||||
bool IsConnected ( void );
|
||||
bool IsConnected ( void );
|
||||
|
||||
void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
|
||||
void Print ( const char* text );
|
||||
void Print ( const char* text );
|
||||
|
||||
void OSPathToRelativePath( const char *osPath, idStr &qpath );
|
||||
void OSPathToRelativePath ( const char *osPath, idStr &qpath );
|
||||
|
||||
protected:
|
||||
bool GameSuspended ( void );
|
||||
private:
|
||||
|
||||
void ClearBreakpoints ( void );
|
||||
|
||||
void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
void Resume ( void );
|
||||
|
||||
void SendMessage ( EDebuggerMessage dbmsg );
|
||||
void SendPacket ( void* data, int datasize );
|
||||
|
||||
// Message handlers
|
||||
void HandleAddBreakpoint ( idBitMsg * msg );
|
||||
void HandleRemoveBreakpoint ( idBitMsg * msg );
|
||||
void HandleResume ( idBitMsg * msg );
|
||||
void HandleInspectVariable ( idBitMsg * msg );
|
||||
void HandleInspectCallstack ( idBitMsg * msg );
|
||||
void HandleInspectThreads ( idBitMsg * msg );
|
||||
void HandleInspectScripts ( idBitMsg * msg );
|
||||
////
|
||||
|
||||
// protected member variables
|
||||
bool mConnected;
|
||||
netadr_t mClientAdr;
|
||||
idPort mPort;
|
||||
|
@ -87,27 +100,9 @@ protected:
|
|||
|
||||
idStr mLastStatementFile;
|
||||
int mLastStatementLine;
|
||||
uintptr_t mGameDLLHandle;
|
||||
idStrList mScriptFileList;
|
||||
|
||||
private:
|
||||
|
||||
void ClearBreakpoints ( void );
|
||||
|
||||
void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
|
||||
void Resume ( void );
|
||||
|
||||
void SendMessage ( EDebuggerMessage dbmsg );
|
||||
void SendPacket ( void* data, int datasize );
|
||||
|
||||
// Message handlers
|
||||
void HandleAddBreakpoint ( msg_t* msg );
|
||||
void HandleRemoveBreakpoint ( msg_t* msg );
|
||||
void HandleResume ( msg_t* msg );
|
||||
void HandleInspectVariable ( msg_t* msg );
|
||||
void HandleInspectCallstack ( msg_t* msg );
|
||||
void HandleInspectThreads ( msg_t* msg );
|
||||
|
||||
// MSG helper routines
|
||||
void MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -130,4 +125,14 @@ ID_INLINE void rvDebuggerServer::SendPacket ( void* data, int size )
|
|||
mPort.SendPacket ( mClientAdr, data, size );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::GameSuspended
|
||||
================
|
||||
*/
|
||||
ID_INLINE bool rvDebuggerServer::GameSuspended( void )
|
||||
{
|
||||
return mBreak;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERSERVER_H_
|
||||
|
|
|
@ -35,7 +35,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "DebuggerQuickWatchDlg.h"
|
||||
#include "DebuggerFindDlg.h"
|
||||
|
||||
#define DEBUGGERWINDOWCLASS "QUAKE4_DEBUGGER_WINDOW"
|
||||
#define DEBUGGERWINDOWCLASS "DHEWM3_DEBUGGER_WINDOW"
|
||||
#define ID_DBG_WINDOWMIN 18900
|
||||
#define ID_DBG_WINDOWMAX 19900
|
||||
|
||||
|
@ -49,6 +49,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define IDC_DBG_WATCH 31007
|
||||
#define IDC_DBG_THREADS 31008
|
||||
#define IDC_DBG_TOOLBAR 31009
|
||||
#define IDC_DBG_SCRIPTLIST 31010
|
||||
|
||||
#define ID_DBG_FILE_MRU1 10000
|
||||
|
||||
|
@ -167,7 +168,7 @@ bool rvDebuggerWindow::Create ( HINSTANCE instance )
|
|||
|
||||
UpdateTitle ( );
|
||||
|
||||
Printf ( "Quake 4 Script Debugger v0.1\n\n" );
|
||||
Printf ( "Dhewm3 Script Debugger v1.0\n\n" );
|
||||
|
||||
ShowWindow ( mWnd, SW_SHOW );
|
||||
UpdateWindow ( mWnd );
|
||||
|
@ -347,6 +348,20 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp
|
|||
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
{
|
||||
float scaling_factor = Win_GetWindowScalingFactor(wnd);
|
||||
int s18 = int(18 * scaling_factor);
|
||||
int s10 = int(10 * scaling_factor);
|
||||
|
||||
RECT rect;
|
||||
window->mMarginSize = window->mZoomScaleDem ? ((long)(s18 * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)) : s18;
|
||||
|
||||
GetWindowRect(window->mWndToolbar, &rect);
|
||||
MoveWindow(window->mWndMargin, 0, 0, window->mMarginSize, window->mSplitterRect.top - (rect.bottom - rect.top), TRUE);
|
||||
SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return CallWindowProc ( wndproc, wnd, msg, wparam, lparam );
|
||||
|
@ -384,14 +399,20 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp
|
|||
case WM_PAINT:
|
||||
{
|
||||
HDC dc;
|
||||
float scaling_factor = Win_GetWindowScalingFactor(wnd);
|
||||
int s2 = int(2 * scaling_factor);
|
||||
int s4 = int(4 * scaling_factor);
|
||||
int s22 = int(22 * scaling_factor);
|
||||
int width,height;
|
||||
|
||||
int size = window->mMarginSize - 2;
|
||||
window->ResizeImageList(width,height);
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
RECT rect;
|
||||
GetClientRect ( wnd, &rect );
|
||||
|
||||
dc = BeginPaint ( wnd, &ps );
|
||||
FillRect ( dc, &rect, GetSysColorBrush ( COLOR_3DFACE ) );
|
||||
FillRect ( dc, &rect, GetSysColorBrush ( COLOR_3DSHADOW ) );
|
||||
|
||||
if ( window->mScripts.Num ( ) )
|
||||
{
|
||||
|
@ -407,7 +428,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp
|
|||
|
||||
c = SendMessage ( window->mWndScript, EM_LINEINDEX, bp->GetLineNumber ( ) - 1, 0 );
|
||||
SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c );
|
||||
ImageList_DrawEx ( window->mImageList, 2, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
ImageList_DrawEx ( window->mTmpImageList, 2, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,7 +442,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp
|
|||
|
||||
c = SendMessage ( window->mWndScript, EM_LINEINDEX, window->mClient->GetBreakLineNumber() - 1, 0 );
|
||||
SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c );
|
||||
ImageList_DrawEx ( window->mImageList, 3, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
ImageList_DrawEx ( window->mTmpImageList, 3, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -434,17 +455,19 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp
|
|||
|
||||
c = SendMessage ( window->mWndScript, EM_LINEINDEX, window->mClient->GetCallstack()[window->mCurrentStackDepth]->mLineNumber - 1, 0 );
|
||||
SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c );
|
||||
ImageList_DrawEx ( window->mImageList, 1, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
ImageList_DrawEx ( window->mTmpImageList, 1, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
RECT tmp = rect;
|
||||
|
||||
rect.right-=2;
|
||||
rect.left = rect.right + 1;
|
||||
HPEN pen = CreatePen ( PS_SOLID, 1, GetSysColor ( COLOR_3DSHADOW ) );
|
||||
rect.right -= s2;
|
||||
rect.left = rect.right + s2;
|
||||
HPEN pen = CreatePen ( PS_SOLID, s2, GetSysColor ( COLOR_BACKGROUND ) );
|
||||
HPEN old = (HPEN)SelectObject ( dc, pen );
|
||||
MoveToEx ( dc, rect.right, rect.top, NULL );
|
||||
LineTo ( dc, rect.right, rect.bottom );
|
||||
|
||||
SelectObject ( dc, old );
|
||||
DeleteObject ( pen );
|
||||
EndPaint ( wnd, &ps );
|
||||
|
@ -466,7 +489,7 @@ void rvDebuggerWindow::UpdateTitle ( void )
|
|||
{
|
||||
idStr title;
|
||||
|
||||
title = "Quake 4 Script Debugger - ";
|
||||
title = "Dhewm3 Script Debugger - ";
|
||||
|
||||
if ( mClient->IsConnected ( ) )
|
||||
{
|
||||
|
@ -487,7 +510,10 @@ void rvDebuggerWindow::UpdateTitle ( void )
|
|||
if ( mScripts.Num ( ) )
|
||||
{
|
||||
title += " - [";
|
||||
title += idStr( mScripts[mActiveScript]->GetFilename() ).StripPath ( );
|
||||
if (mActiveScript != -1)
|
||||
title += idStr( mScripts[mActiveScript]->GetFilename() ).StripPath ( );
|
||||
else
|
||||
title += "Load Error";
|
||||
title += "]";
|
||||
}
|
||||
|
||||
|
@ -590,6 +616,33 @@ void rvDebuggerWindow::UpdateCallstack ( void )
|
|||
}
|
||||
}
|
||||
|
||||
void rvDebuggerWindow::UpdateScriptList(void)
|
||||
{
|
||||
LVITEM item;
|
||||
ListView_DeleteAllItems(mWndScriptList);
|
||||
ZeroMemory(&item, sizeof(item));
|
||||
item.mask = LVIF_TEXT | LVIF_IMAGE;
|
||||
|
||||
idStrList& scripts = mClient->GetServerScripts();
|
||||
for (int i = 0; i < scripts.Num(); i++)
|
||||
{
|
||||
item.iItem = ListView_GetItemCount(mWndScriptList);
|
||||
item.pszText = "";
|
||||
//find in activeScripts
|
||||
item.iImage = 0;
|
||||
for (int j = 0; j < mScripts.Num(); j++)
|
||||
{
|
||||
if (!idStr::Icmp(mScripts[j]->GetFilename(), scripts[i]))
|
||||
{
|
||||
item.iImage = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ListView_InsertItem(mWndScriptList, &item);
|
||||
ListView_SetItemText(mWndScriptList, item.iItem, 1, (LPSTR)scripts[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerWindow::UpdateWatch
|
||||
|
@ -737,6 +790,32 @@ int rvDebuggerWindow::HandleInitMenu ( WPARAM wParam, LPARAM lParam )
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void rvDebuggerWindow::ResizeImageList(int& widthOut, int& heightOut)
|
||||
{
|
||||
//mTmpImageList
|
||||
float scaling_factor = Win_GetWindowScalingFactor(mWnd);
|
||||
int s16 = int(16 * scaling_factor);
|
||||
|
||||
TEXTMETRIC tm;
|
||||
HDC dc;
|
||||
dc = GetDC(mWndScript);
|
||||
|
||||
GetTextMetrics(dc, &tm);
|
||||
int height = mZoomScaleDem ? (tm.tmHeight * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16;
|
||||
int width = mZoomScaleDem ? (s16 * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16;
|
||||
|
||||
ImageList_Destroy(mTmpImageList);
|
||||
mTmpImageList = ImageList_Create(width, height, ILC_COLOR | ILC_MASK , 0, 2);
|
||||
ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_EMPTY), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR));
|
||||
ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENT), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR));
|
||||
ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_BREAKPOINT), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR));
|
||||
ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENTLINE), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR));
|
||||
|
||||
widthOut = width;
|
||||
heightOut = height;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerWindow::HandleCreate
|
||||
|
@ -760,7 +839,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam )
|
|||
// Create the script window
|
||||
LoadLibrary ( "Riched20.dll" );
|
||||
mWndScript = CreateWindow ( "RichEdit20A", "", WS_CHILD|WS_BORDER|ES_NOHIDESEL|ES_READONLY|ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL, 0, 0, 100, 100, mWnd, (HMENU) IDC_DBG_SCRIPT, mInstance, 0 );
|
||||
SendMessage ( mWndScript, EM_SETEVENTMASK, 0, ENM_SCROLL|ENM_CHANGE );
|
||||
SendMessage ( mWndScript, EM_SETEVENTMASK, 0, ENM_SCROLL | ENM_CHANGE | ENM_UPDATE | ENM_SCROLLEVENTS | ENM_REQUESTRESIZE) ;
|
||||
SendMessage ( mWndScript, EM_SETWORDBREAKPROC, 0, (LPARAM) ScriptWordBreakProc );
|
||||
mOldScriptProc = (WNDPROC)GetWindowLong ( mWndScript, GWL_WNDPROC );
|
||||
SetWindowLong ( mWndScript, GWL_USERDATA, (LONG)this );
|
||||
|
@ -782,6 +861,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam )
|
|||
SendMessage ( mWndOutput, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 );
|
||||
SendMessage ( mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(18,10) );
|
||||
SendMessage ( mWndOutput, EM_SETBKGNDCOLOR, 0, GetSysColor ( COLOR_3DFACE ) );
|
||||
SendMessage ( mWndOutput, EM_SETEVENTMASK, 0, ENM_SCROLL | ENM_CHANGE | ENM_UPDATE | ENM_SCROLLEVENTS);
|
||||
|
||||
mWndConsole = CreateWindow ( "RichEdit20A", "", WS_CHILD|ES_READONLY|ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL, 0, 0, 100, 100, mWnd, (HMENU) IDC_DBG_CONSOLE, mInstance, 0 );
|
||||
SendMessage ( mWndConsole, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 );
|
||||
|
@ -816,13 +896,24 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam )
|
|||
TabCtrl_InsertItem ( mWndTabs, 3, &item );
|
||||
item.pszText = "Threads";
|
||||
TabCtrl_InsertItem ( mWndTabs, 4, &item );
|
||||
item.pszText = "Scripts";
|
||||
TabCtrl_InsertItem ( mWndTabs, 5, &item );
|
||||
|
||||
mWndCallstack = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_CALLSTACK, mInstance, NULL );
|
||||
mWndWatch = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_EDITLABELS|LVS_OWNERDRAWFIXED, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_WATCH, mInstance, NULL );
|
||||
mWndThreads = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_THREADS, mInstance, NULL );
|
||||
mWndScriptList = CreateWindow( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_SCRIPTLIST, mInstance, NULL );
|
||||
|
||||
LVCOLUMN col;
|
||||
col.mask = LVCF_WIDTH|LVCF_TEXT;
|
||||
|
||||
col.cx = 20;
|
||||
col.pszText = "";
|
||||
ListView_InsertColumn ( mWndScriptList, 0, &col);
|
||||
col.cx = 150;
|
||||
col.pszText = "Filename";
|
||||
ListView_InsertColumn ( mWndScriptList, 1, &col );
|
||||
|
||||
col.cx = 20;
|
||||
col.pszText = "";
|
||||
ListView_InsertColumn ( mWndCallstack, 0, &col );
|
||||
|
@ -863,13 +954,19 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam )
|
|||
ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENT), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) );
|
||||
ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_BREAKPOINT), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) );
|
||||
ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENTLINE), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) );
|
||||
|
||||
int w, h;
|
||||
ResizeImageList(w, h);
|
||||
ListView_SetImageList ( mWndScriptList, mTmpImageList, LVSIL_SMALL );
|
||||
ListView_SetImageList ( mWndThreads, mImageList, LVSIL_SMALL );
|
||||
ListView_SetImageList ( mWndCallstack, mImageList, LVSIL_SMALL );
|
||||
|
||||
EnableWindows ( FALSE );
|
||||
|
||||
EnableWindow ( mWndScriptList, true );
|
||||
|
||||
ListView_SetExtendedListViewStyle ( mWndCallstack, LVS_EX_FULLROWSELECT );
|
||||
ListView_SetExtendedListViewStyle ( mWndThreads, LVS_EX_FULLROWSELECT );
|
||||
ListView_SetExtendedListViewStyle ( mWndScriptList, LVS_EX_FULLROWSELECT );
|
||||
|
||||
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_callstack", mWndCallstack );
|
||||
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_threads", mWndThreads );
|
||||
|
@ -920,6 +1017,10 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam )
|
|||
AddWatch ( s );
|
||||
}
|
||||
|
||||
RECT t;
|
||||
GetClientRect(mWndScript, &t);
|
||||
SendMessage(mWndScript, WM_SIZE, 0, MAKELPARAM(t.right - t.left, t.bottom - t.top));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1055,7 +1156,7 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam )
|
|||
mZoomScaleNum = num;
|
||||
mZoomScaleDem = dem;
|
||||
GetClientRect ( mWndScript, &t );
|
||||
SendMessage ( mWnd, WM_SIZE, 0, MAKELPARAM(t.right-t.left,t.bottom-t.top) );
|
||||
SendMessage ( mWndScript, WM_SIZE, 0, MAKELPARAM(t.right-t.left ,t.bottom-t.top) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1202,8 +1303,13 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
|
||||
case WM_SIZE:
|
||||
{
|
||||
float scaling_factor = Win_GetWindowScalingFactor(wnd);
|
||||
int s18 = int(18 * scaling_factor);
|
||||
int s4 = int(4 * scaling_factor);
|
||||
int s10 = int(10 * scaling_factor);
|
||||
|
||||
RECT rect;
|
||||
window->mMarginSize = window->mZoomScaleDem ? ((long)(18.0f * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)):18;
|
||||
window->mMarginSize = window->mZoomScaleDem ? ((long)(s18 * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)): s18;
|
||||
window->mSplitterRect.left = 0;
|
||||
window->mSplitterRect.right = LOWORD(lparam);
|
||||
|
||||
|
@ -1215,7 +1321,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
SetRect ( &rect, 0, window->mSplitterRect.bottom, LOWORD(lparam), HIWORD(lparam) );
|
||||
MoveWindow ( window->mWndTabs, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
SendMessage ( window->mWndTabs, TCM_ADJUSTRECT, FALSE, (LPARAM)&rect );
|
||||
rect.bottom -= 4 ;
|
||||
rect.bottom -= s4;
|
||||
MoveWindow ( window->mWndBorder, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
InflateRect ( &rect, -1, -1 );
|
||||
MoveWindow ( window->mWndOutput, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
|
@ -1223,6 +1329,13 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
MoveWindow ( window->mWndCallstack, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
MoveWindow ( window->mWndWatch, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
MoveWindow ( window->mWndThreads, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
MoveWindow ( window->mWndScriptList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE );
|
||||
|
||||
SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10));
|
||||
SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10));
|
||||
SendMessage(window->mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10));
|
||||
SendMessage(window->mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1258,7 +1371,17 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
HDC dc = GetDC(wnd);
|
||||
DrawFocusRect(dc, &window->mSplitterRect);
|
||||
ReleaseDC(wnd, dc);
|
||||
|
||||
RECT client;
|
||||
GetClientRect(wnd, &client);
|
||||
SendMessage(wnd, WM_SIZE, 0, MAKELPARAM(client.right - client.left, client.bottom - client.top));
|
||||
|
||||
}
|
||||
case WM_LBUTTONUP:
|
||||
if ( window->mSplitterDrag )
|
||||
{
|
||||
|
@ -1454,6 +1577,31 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case IDC_DBG_SCRIPTLIST:
|
||||
if ( hdr->code == NM_DBLCLK )
|
||||
{
|
||||
int sel = ListView_GetNextItem(hdr->hwndFrom, -1, LVNI_SELECTED);
|
||||
|
||||
if (sel != -1)
|
||||
{
|
||||
LVITEM item = { 0 };
|
||||
char temp[1024] = { 0 };
|
||||
item.mask = LVIF_TEXT;
|
||||
item.pszText = temp;
|
||||
item.cchTextMax = sizeof(temp) - 1;
|
||||
item.iSubItem = 1;
|
||||
item.iItem = sel;
|
||||
|
||||
ListView_GetItem(hdr->hwndFrom, &item);
|
||||
|
||||
if (strlen(item.pszText) > 0)
|
||||
{
|
||||
window->OpenScript(item.pszText);
|
||||
window->UpdateScriptList();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDC_DBG_TABS:
|
||||
if ( hdr->code == TCN_SELCHANGE )
|
||||
{
|
||||
|
@ -1462,6 +1610,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
ShowWindow ( window->mWndCallstack, SW_HIDE );
|
||||
ShowWindow ( window->mWndWatch, SW_HIDE );
|
||||
ShowWindow ( window->mWndThreads, SW_HIDE );
|
||||
ShowWindow ( window->mWndScriptList, SW_HIDE );
|
||||
switch ( TabCtrl_GetCurSel ( hdr->hwndFrom ) )
|
||||
{
|
||||
case 0:
|
||||
|
@ -1483,6 +1632,9 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
case 4:
|
||||
ShowWindow ( window->mWndThreads, SW_SHOW );
|
||||
break;
|
||||
case 5:
|
||||
ShowWindow(window->mWndScriptList, SW_SHOW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1535,14 +1687,19 @@ rvDebuggerWindow::ProcessNetMessage
|
|||
Process an incoming network message
|
||||
================
|
||||
*/
|
||||
void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
||||
void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg )
|
||||
{
|
||||
unsigned short command;
|
||||
short command;
|
||||
|
||||
command = (unsigned short)MSG_ReadShort ( msg );
|
||||
command = msg->ReadShort( );
|
||||
|
||||
switch ( command )
|
||||
{
|
||||
case DBMSG_REMOVEBREAKPOINT:
|
||||
MessageBeep(MB_ICONEXCLAMATION);
|
||||
InvalidateRect(mWndScript, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case DBMSG_RESUMED:
|
||||
UpdateTitle ( );
|
||||
UpdateToolbar ( );
|
||||
|
@ -1554,9 +1711,9 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
|||
char temp2[1024];
|
||||
int i;
|
||||
|
||||
MSG_ReadShort ( msg );
|
||||
MSG_ReadString ( msg, temp, 1024 );
|
||||
MSG_ReadString ( msg, temp2, 1024 );
|
||||
msg->ReadShort ( );
|
||||
msg->ReadString ( temp, 1024 );
|
||||
msg->ReadString ( temp2, 1024 );
|
||||
if ( mTooltipVar.Icmp ( temp ) == 0 )
|
||||
{
|
||||
mTooltipValue = temp2;
|
||||
|
@ -1625,7 +1782,7 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
|||
|
||||
case DBMSG_PRINT:
|
||||
SendMessage ( mWndConsole, EM_SETSEL, -1, -1 );
|
||||
SendMessage ( mWndConsole, EM_REPLACESEL, 0, (LPARAM)(const char*)(msg->data) + msg->readcount );
|
||||
SendMessage ( mWndConsole, EM_REPLACESEL, 0, (LPARAM)(const char*)(msg->GetData()) + msg->GetReadCount() );
|
||||
SendMessage ( mWndConsole, EM_SCROLLCARET, 0, 0 );
|
||||
break;
|
||||
|
||||
|
@ -1637,13 +1794,17 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
|||
mClient->InspectVariable ( mTooltipVar, mCurrentStackDepth );
|
||||
UpdateWatch ( );
|
||||
EnableWindows ( TRUE );
|
||||
OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1 );
|
||||
OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1, mClient->GetBreakProgram());
|
||||
UpdateTitle ( );
|
||||
UpdateToolbar ( );
|
||||
SetForegroundWindow ( mWnd );
|
||||
break;
|
||||
}
|
||||
|
||||
case DBMSG_INSPECTSCRIPTS:
|
||||
{
|
||||
UpdateScriptList ( );
|
||||
break;
|
||||
}
|
||||
case DBMSG_INSPECTCALLSTACK:
|
||||
{
|
||||
UpdateCallstack ( );
|
||||
|
@ -1719,7 +1880,7 @@ Opens the script with the given filename and will scroll to the given line
|
|||
number if one is specified
|
||||
================
|
||||
*/
|
||||
bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber )
|
||||
bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber, idProgram* program )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1748,7 +1909,6 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber )
|
|||
// Load the script
|
||||
if ( !script->Load ( filename ) )
|
||||
{
|
||||
delete script;
|
||||
SetCursor ( LoadCursor ( NULL, IDC_ARROW ) );
|
||||
return false;
|
||||
}
|
||||
|
@ -1777,7 +1937,7 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber )
|
|||
// Move to a specific line number?
|
||||
if ( lineNumber != -1 )
|
||||
{
|
||||
int c;
|
||||
long c;
|
||||
|
||||
// Put the caret on the line number specified and scroll it into position.
|
||||
// This is a bit of a hack since we set the selection twice, but setting the
|
||||
|
@ -1785,10 +1945,10 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber )
|
|||
// and then scroll before going back to (c,c).
|
||||
// NOTE: We scroll to the line before the one we want so its more visible
|
||||
SetFocus ( mWndScript );
|
||||
c = SendMessage ( mWndScript, EM_LINEINDEX, lineNumber - 1, 0 );
|
||||
c = SendMessage ( mWndScript, EM_LINEINDEX, (long)lineNumber - 1, 0 );
|
||||
SendMessage ( mWndScript, EM_SETSEL, c, c + 1 );
|
||||
SendMessage ( mWndScript, EM_SCROLLCARET, 0, 0 );
|
||||
c = SendMessage ( mWndScript, EM_LINEINDEX, lineNumber, 0 );
|
||||
c = SendMessage ( mWndScript, EM_LINEINDEX, (long)lineNumber, 0 );
|
||||
SendMessage ( mWndScript, EM_SETSEL, c, c );
|
||||
}
|
||||
else
|
||||
|
@ -2193,7 +2353,7 @@ then the last text used will be searched for.
|
|||
*/
|
||||
bool rvDebuggerWindow::FindNext ( const char* text )
|
||||
{
|
||||
int start;
|
||||
long start;
|
||||
FINDTEXT ft;
|
||||
|
||||
if ( text )
|
||||
|
@ -2230,7 +2390,7 @@ bool rvDebuggerWindow::FindNext ( const char* text )
|
|||
}
|
||||
}
|
||||
|
||||
SendMessage ( mWndScript, EM_SETSEL, start, start + mFind.Length() );
|
||||
SendMessage ( mWndScript, EM_SETSEL, start, start + (long)mFind.Length() );
|
||||
SendMessage ( mWndScript, EM_SCROLLCARET, 0, 0 );
|
||||
|
||||
return true;
|
||||
|
@ -2247,7 +2407,7 @@ then the last text used will be searched for.
|
|||
*/
|
||||
bool rvDebuggerWindow::FindPrev ( const char* text )
|
||||
{
|
||||
int start;
|
||||
long start;
|
||||
FINDTEXT ft;
|
||||
|
||||
if ( text )
|
||||
|
|
|
@ -52,38 +52,56 @@ public:
|
|||
rvDebuggerWindow ( );
|
||||
~rvDebuggerWindow ( );
|
||||
|
||||
bool Create ( HINSTANCE hInstance );
|
||||
bool Create ( HINSTANCE hInstance );
|
||||
|
||||
static bool Activate ( void );
|
||||
static bool Activate ( void );
|
||||
|
||||
void ProcessNetMessage ( msg_t* msg );
|
||||
void ProcessNetMessage ( idBitMsg * msg );
|
||||
|
||||
void Printf ( const char* format, ... );
|
||||
void Printf ( const char* format, ... );
|
||||
|
||||
HWND GetWindow ( void );
|
||||
HWND GetWindow ( void );
|
||||
|
||||
void AddWatch ( const char* name, bool update = true );
|
||||
void AddWatch ( const char* name, bool update = true );
|
||||
|
||||
HINSTANCE GetInstance ( void );
|
||||
HINSTANCE GetInstance ( void );
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool RegisterClass ( void );
|
||||
void CreateToolbar ( void );
|
||||
bool InitRecentFiles ( void );
|
||||
|
||||
bool FindPrev ( const char* text = NULL );
|
||||
bool FindNext ( const char* text = NULL );
|
||||
int HandleInitMenu ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCommand ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCreate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleActivate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleDrawItem ( WPARAM wparam, LPARAM lparam );
|
||||
void HandleTooltipGetDispInfo( WPARAM wparam, LPARAM lparam );
|
||||
|
||||
void UpdateWatch ( void );
|
||||
void UpdateWindowMenu ( void );
|
||||
void UpdateScript ( void );
|
||||
void UpdateToolbar ( void );
|
||||
void UpdateTitle ( void );
|
||||
void UpdateCallstack ( void );
|
||||
void UpdateRecentFiles ( void );
|
||||
bool OpenScript ( const char* filename, int lineNumber = -1 );
|
||||
void EnableWindows ( bool state );
|
||||
void ResizeImageList ( int& widthOut, int& heightOut);
|
||||
static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static int CALLBACK ScriptWordBreakProc( LPTSTR text, int current, int max, int action );
|
||||
|
||||
int GetSelectedText ( idStr& text );
|
||||
bool FindPrev ( const char* text = NULL );
|
||||
bool FindNext ( const char* text = NULL );
|
||||
|
||||
void ToggleBreakpoint ( void );
|
||||
void UpdateScriptList ( void );
|
||||
void UpdateWatch ( void );
|
||||
void UpdateWindowMenu ( void );
|
||||
void UpdateScript ( void );
|
||||
void UpdateToolbar ( void );
|
||||
void UpdateTitle ( void );
|
||||
void UpdateCallstack ( void );
|
||||
void UpdateRecentFiles ( void );
|
||||
bool OpenScript ( const char* filename, int lineNumber = -1, idProgram* program = nullptr );
|
||||
void EnableWindows ( bool state );
|
||||
|
||||
int GetSelectedText ( idStr& text );
|
||||
|
||||
void ToggleBreakpoint ( void );
|
||||
|
||||
HWND mWnd;
|
||||
HWND mWndScript;
|
||||
|
@ -93,6 +111,7 @@ protected:
|
|||
HWND mWndBorder;
|
||||
HWND mWndConsole;
|
||||
HWND mWndCallstack;
|
||||
HWND mWndScriptList;
|
||||
HWND mWndWatch;
|
||||
HWND mWndThreads;
|
||||
HWND mWndToolTips;
|
||||
|
@ -108,6 +127,7 @@ protected:
|
|||
|
||||
HINSTANCE mInstance;
|
||||
HIMAGELIST mImageList;
|
||||
HIMAGELIST mTmpImageList;
|
||||
|
||||
RECT mSplitterRect;
|
||||
bool mSplitterDrag;
|
||||
|
@ -129,25 +149,6 @@ protected:
|
|||
rvDebuggerClient* mClient;
|
||||
|
||||
rvDebuggerWatchList mWatches;
|
||||
|
||||
private:
|
||||
|
||||
bool RegisterClass ( void );
|
||||
void CreateToolbar ( void );
|
||||
bool InitRecentFiles ( void );
|
||||
|
||||
int HandleInitMenu ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCommand ( WPARAM wParam, LPARAM lParam );
|
||||
int HandleCreate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleActivate ( WPARAM wparam, LPARAM lparam );
|
||||
int HandleDrawItem ( WPARAM wparam, LPARAM lparam );
|
||||
void HandleTooltipGetDispInfo ( WPARAM wparam, LPARAM lparam );
|
||||
|
||||
static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
|
||||
static int CALLBACK ScriptWordBreakProc ( LPTSTR text, int current, int max, int action );
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue