2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
2011-12-06 18:20:15 +00:00
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-11-22 21:28:15 +00:00
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
Doom 3 Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include "../../idlib/precompiled.h"
# pragma hdrstop
# include "../../sys/win32/rc/debugger_resource.h"
# include "DebuggerApp.h"
# include "../Common/OpenFileDialog.h"
# include "DebuggerQuickWatchDlg.h"
# include "DebuggerFindDlg.h"
# define DEBUGGERWINDOWCLASS "QUAKE4_DEBUGGER_WINDOW"
# define ID_DBG_WINDOWMIN 18900
# define ID_DBG_WINDOWMAX 19900
# define IDC_DBG_SCRIPT 31000
# define IDC_DBG_OUTPUT 31001
# define IDC_DBG_SPLITTER 31002
# define IDC_DBG_TABS 31003
# define IDC_DBG_BORDER 31004
# define IDC_DBG_CONSOLE 31005
# define IDC_DBG_CALLSTACK 31006
# define IDC_DBG_WATCH 31007
# define IDC_DBG_THREADS 31008
# define IDC_DBG_TOOLBAR 31009
# define ID_DBG_FILE_MRU1 10000
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : rvDebuggerWindow
Constructor
= = = = = = = = = = = = = = = =
*/
rvDebuggerWindow : : rvDebuggerWindow ( )
{
mWnd = NULL ;
mWndScript = NULL ;
mInstance = NULL ;
mZoomScaleNum = 0 ;
mZoomScaleDem = 0 ;
mWindowMenuPos = 0 ;
mActiveScript = 0 ;
mSplitterDrag = false ;
mLastActiveScript = - 1 ;
mCurrentStackDepth = 0 ;
mRecentFileInsertPos = 0 ;
mRecentFileMenu = NULL ;
mClient = NULL ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : ~ rvDebuggerWindow
Destructor
= = = = = = = = = = = = = = = =
*/
rvDebuggerWindow : : ~ rvDebuggerWindow ( )
{
int i ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mWnd )
{
DestroyWindow ( mWnd ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mImageList )
{
ImageList_Destroy ( mImageList ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( i = 0 ; i < mScripts . Num ( ) ; i + + )
{
delete mScripts [ i ] ;
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : RegisterClass
Registers the window class used by the debugger window . This is called when
the window is created .
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : RegisterClass ( void )
{
WNDCLASSEX wcex ;
2011-12-06 18:20:15 +00:00
wcex . cbSize = sizeof ( WNDCLASSEX ) ;
2011-11-22 21:28:15 +00:00
wcex . style = CS_HREDRAW | CS_VREDRAW ;
wcex . lpfnWndProc = ( WNDPROC ) WndProc ;
wcex . cbClsExtra = 0 ;
wcex . cbWndExtra = 0 ;
wcex . hInstance = mInstance ;
wcex . hIcon = NULL ;
wcex . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
wcex . hbrBackground = ( HBRUSH ) ( COLOR_APPWORKSPACE + 1 ) ;
wcex . lpszMenuName = MAKEINTRESOURCE ( IDR_DBG_MAIN ) ;
wcex . lpszClassName = DEBUGGERWINDOWCLASS ;
wcex . hIconSm = NULL ;
return RegisterClassEx ( & wcex ) ? true : false ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : Create
Creates the debugger window
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : Create ( HINSTANCE instance )
{
mInstance = instance ;
if ( ! RegisterClass ( ) )
{
return false ;
}
// Cache the client pointer for ease of use
mClient = & gDebuggerApp . GetClient ( ) ;
// Create the debugger window
2011-12-06 18:20:15 +00:00
mWnd = CreateWindow ( DEBUGGERWINDOWCLASS , " " ,
2011-11-22 21:28:15 +00:00
WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT , 0 , CW_USEDEFAULT , 0 , NULL , NULL , mInstance , this ) ;
if ( ! mWnd )
{
return false ;
}
// Determine where the window names will be added in the menus
mWindowMenu = GetSubMenu ( GetMenu ( mWnd ) , 2 ) ;
mWindowMenuPos = GetMenuItemCount ( mWindowMenu ) ;
UpdateTitle ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
Printf ( " Quake 4 Script Debugger v0.1 \n \n " ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
ShowWindow ( mWnd , SW_SHOW ) ;
2011-12-06 18:20:15 +00:00
UpdateWindow ( mWnd ) ;
2011-11-22 21:28:15 +00:00
return true ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : ScriptWordBreakProc
Determines where word breaks are in the script window . This is used for determining
the word that someone is over with their mouse cursor . Since the default windows one
doesnt understand the delimiters of the scripting language it had to be overridden .
= = = = = = = = = = = = = = = =
*/
int CALLBACK rvDebuggerWindow : : ScriptWordBreakProc ( LPTSTR text , int current , int max , int action )
{
static TCHAR delimiters [ ] = TEXT ( " !@#$%^&*()-+=[]{}| \\ ;:' \" /,.<>? \t \r \n " ) ;
2011-12-06 18:20:15 +00:00
switch ( action )
2011-11-22 21:28:15 +00:00
{
default :
break ;
2011-12-06 18:20:15 +00:00
case WB_ISDELIMITER :
2011-11-22 21:28:15 +00:00
return _tcschr ( delimiters , * ( text + current * 2 ) ) ? TRUE : FALSE ;
case WB_MOVEWORDLEFT :
case WB_LEFT :
current - - ;
// Run as long as the current index is valid.
while ( current > 0 )
{
// If we hit a delimiter then return the index + 1 since
// it was the last character we were on that was valid
if ( _tcschr ( delimiters , * ( text + current * 2 ) ) )
{
return current + 1 ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Going backwards
current - - ;
}
return current ;
case WB_MOVEWORDRIGHT :
2011-12-06 18:20:15 +00:00
case WB_RIGHT :
// If we are already on a delimiter then just return the current index
2011-11-22 21:28:15 +00:00
if ( _tcschr ( delimiters , * ( text + current * 2 ) ) )
{
return current ;
}
// Run until we hit the end of the control
while ( current < max )
{
// If we found a delimiter then return the index we are on
if ( _tcschr ( delimiters , * ( text + current * 2 ) ) )
{
return current ;
}
current + + ;
}
return current ;
2011-12-06 18:20:15 +00:00
}
return 0 ;
2011-11-22 21:28:15 +00:00
}
LRESULT CALLBACK rvDebuggerWindow : : ScriptWndProc ( HWND wnd , UINT msg , WPARAM wparam , LPARAM lparam )
{
static int lastStart = - 1 ;
static int lastEnd = - 1 ;
rvDebuggerWindow * window = ( rvDebuggerWindow * ) GetWindowLong ( wnd , GWL_USERDATA ) ;
WNDPROC wndproc = window - > mOldScriptProc ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( msg )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
case WM_RBUTTONUP :
return SendMessage ( wnd , WM_LBUTTONUP , wparam , lparam ) ;
case WM_RBUTTONDOWN :
{
2011-12-06 18:20:15 +00:00
POINT point = { LOWORD ( lparam ) , HIWORD ( lparam ) } ;
2011-11-22 21:28:15 +00:00
HMENU menu ;
SendMessage ( wnd , WM_LBUTTONDOWN , wparam , lparam ) ;
menu = LoadMenu ( window - > mInstance , MAKEINTRESOURCE ( IDR_DBG_SCRIPT_POPUP ) ) ;
ClientToScreen ( wnd , & point ) ;
TrackPopupMenu ( GetSubMenu ( menu , 0 ) , TPM_RIGHTBUTTON | TPM_LEFTALIGN , point . x , point . y , 0 , window - > mWnd , NULL ) ;
DestroyMenu ( menu ) ;
return 0 ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_MOUSEMOVE :
{
// Figure out the start and end of the mouse is over
POINTL pos = { LOWORD ( lparam ) , HIWORD ( lparam ) } ;
int c = SendMessage ( wnd , EM_CHARFROMPOS , 0 , ( WPARAM ) & pos ) ;
int start = SendMessage ( wnd , EM_FINDWORDBREAK , WB_LEFT , c ) ;
int end = SendMessage ( wnd , EM_FINDWORDBREAK , WB_RIGHT , c ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// If the start and the end of the word we are over havent changed
// then the word hasnt changed so no need to re-setup the tool tip
if ( lastStart = = start & & lastEnd = = end )
{
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Save the current start and end for the next mouse move
lastStart = start ;
lastEnd = end ;
// Get rid of the last tool tip if there is one
if ( window - > mTooltipVar . Length ( ) )
{
TOOLINFO ti ;
ti . cbSize = sizeof ( TOOLINFO ) ;
ti . hwnd = wnd ;
ti . uId = 0 ;
SendMessage ( window - > mWndToolTips , TTM_DELTOOL , 0 , ( LPARAM ) ( LPTOOLINFO ) & ti ) ;
window - > mTooltipVar . Empty ( ) ;
}
2011-12-06 18:20:15 +00:00
// If there is no word then ignore it
2011-11-22 21:28:15 +00:00
if ( start = = end )
{
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
TEXTRANGE range ;
TOOLINFO ti ;
// grab the actual word from the edit control
char * temp = new char [ end - start + 10 ] ;
range . chrg . cpMin = start ;
range . chrg . cpMax = end ;
range . lpstrText = temp ;
SendMessage ( wnd , EM_GETTEXTRANGE , 0 , ( LPARAM ) & range ) ;
window - > mTooltipVar = temp ;
delete [ ] temp ;
// Request the variable's value from the debugger server
window - > mClient - > InspectVariable ( window - > mTooltipVar . c_str ( ) , window - > mCurrentStackDepth ) ;
// Prepare to add the new tooltip
ti . cbSize = sizeof ( TOOLINFO ) ;
ti . uFlags = TTF_SUBCLASS ;
ti . hwnd = wnd ;
ti . hinst = ( HINSTANCE ) GetModuleHandle ( NULL ) ;
ti . uId = 0 ;
ti . lpszText = ( LPSTR ) window - > mTooltipVar . c_str ( ) ;
// Calculate the bounding box around the word we are over. We do this
// by getting to the top left from the start character and the right side
// from the end character. The bottom is the top from the start character
// plus the height of one line
SendMessage ( wnd , EM_POSFROMCHAR , ( WPARAM ) & pos , start ) ;
2011-12-06 18:20:15 +00:00
ti . rect . left = pos . x ;
2011-11-22 21:28:15 +00:00
ti . rect . top = pos . y ;
SendMessage ( wnd , EM_POSFROMCHAR , ( WPARAM ) & pos , end ) ;
ti . rect . right = pos . x ;
SendMessage ( wnd , EM_POSFROMCHAR , ( WPARAM ) & pos , SendMessage ( wnd , EM_LINEINDEX , 0 , 0 ) ) ;
ti . rect . bottom = ti . rect . top - pos . y ;
SendMessage ( wnd , EM_POSFROMCHAR , ( WPARAM ) & pos , SendMessage ( wnd , EM_LINEINDEX , 1 , 0 ) ) ;
ti . rect . bottom = ti . rect . bottom + pos . y ;
// Add the new tool tip to the control
SendMessage ( window - > mWndToolTips , TTM_ADDTOOL , 0 , ( LPARAM ) ( LPTOOLINFO ) & ti ) ;
SendMessage ( window - > mWndToolTips , TTM_UPDATE , 0 , 0 ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return CallWindowProc ( wndproc , wnd , msg , wparam , lparam ) ;
}
LRESULT CALLBACK rvDebuggerWindow : : MarginWndProc ( HWND wnd , UINT msg , WPARAM wparam , LPARAM lparam )
{
rvDebuggerWindow * window = ( rvDebuggerWindow * ) GetWindowLong ( wnd , GWL_USERDATA ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( msg )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
case WM_RBUTTONDOWN :
return SendMessage ( window - > mWndScript , WM_RBUTTONDOWN , wparam , lparam ) ;
case WM_RBUTTONUP :
return SendMessage ( window - > mWndScript , WM_RBUTTONUP , wparam , lparam ) ;
case WM_LBUTTONDBLCLK :
{
int result = SendMessage ( window - > mWndScript , WM_LBUTTONDBLCLK , wparam , lparam ) ;
window - > ToggleBreakpoint ( ) ;
return result ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_LBUTTONDOWN :
{
int result = SendMessage ( window - > mWndScript , WM_LBUTTONDOWN , wparam , lparam ) ;
window - > ToggleBreakpoint ( ) ;
return result ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_LBUTTONUP :
return SendMessage ( window - > mWndScript , WM_LBUTTONUP , wparam , lparam ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_PAINT :
{
HDC dc ;
int size = window - > mMarginSize - 2 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
PAINTSTRUCT ps ;
RECT rect ;
GetClientRect ( wnd , & rect ) ;
2011-12-06 18:20:15 +00:00
dc = BeginPaint ( wnd , & ps ) ;
2011-11-22 21:28:15 +00:00
FillRect ( dc , & rect , GetSysColorBrush ( COLOR_3DFACE ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( window - > mScripts . Num ( ) )
{
for ( int i = 0 ; i < window - > mClient - > GetBreakpointCount ( ) ; i + + )
{
rvDebuggerBreakpoint * bp = window - > mClient - > GetBreakpoint ( i ) ;
assert ( bp ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( ! idStr : : Icmp ( window - > mScripts [ window - > mActiveScript ] - > GetFilename ( ) , bp - > GetFilename ( ) ) )
{
int c ;
POINTL pos ;
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 ) ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( window - > mClient - > IsStopped ( ) )
{
if ( ! idStr : : Icmp ( window - > mClient - > GetBreakFilename ( ) ,
window - > mScripts [ window - > mActiveScript ] - > GetFilename ( ) ) )
{
int c ;
POINTL pos ;
c = SendMessage ( window - > mWndScript , EM_LINEINDEX , window - > mClient - > GetBreakLineNumber ( ) - 1 , 0 ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( window - > mWndScript , EM_POSFROMCHAR , ( WPARAM ) & pos , c ) ;
2011-11-22 21:28:15 +00:00
ImageList_DrawEx ( window - > mImageList , 3 , dc , rect . left , pos . y , size , size , CLR_NONE , CLR_NONE , ILD_NORMAL ) ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( window - > mCurrentStackDepth ! = 0 )
{
if ( ! window - > mClient - > GetCallstack ( ) [ window - > mCurrentStackDepth ] - > mFilename . Icmp ( window - > mScripts [ window - > mActiveScript ] - > GetFilename ( ) ) )
{
int c ;
POINTL pos ;
c = SendMessage ( window - > mWndScript , EM_LINEINDEX , window - > mClient - > GetCallstack ( ) [ window - > mCurrentStackDepth ] - > mLineNumber - 1 , 0 ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( window - > mWndScript , EM_POSFROMCHAR , ( WPARAM ) & pos , c ) ;
2011-11-22 21:28:15 +00:00
ImageList_DrawEx ( window - > mImageList , 1 , dc , rect . left , pos . y , size , size , CLR_NONE , CLR_NONE , ILD_NORMAL ) ;
}
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
rect . right - = 2 ;
rect . left = rect . right + 1 ;
HPEN pen = CreatePen ( PS_SOLID , 1 , GetSysColor ( COLOR_3DSHADOW ) ) ;
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 ) ;
break ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return DefWindowProc ( wnd , msg , wparam , lparam ) ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateTitle
Updates the window title of the script debugger to show a few states
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateTitle ( void )
{
idStr title ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
title = " Quake 4 Script Debugger - " ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mClient - > IsConnected ( ) )
{
if ( mClient - > IsStopped ( ) )
{
title + = " [break] " ;
}
else
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
title + = " [run] " ;
}
}
else
{
title + = " [disconnected] " ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mScripts . Num ( ) )
{
title + = " - [ " ;
title + = idStr ( mScripts [ mActiveScript ] - > GetFilename ( ) ) . StripPath ( ) ;
title + = " ] " ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SetWindowText ( mWnd , title ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateScript
Updates the edit window to contain the current script
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateScript ( void )
{
UpdateTitle ( ) ;
// Dont reupdate if the given active script is the one being displayed.
if ( mActiveScript = = mLastActiveScript )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
return ;
}
mLastActiveScript = mActiveScript ;
// Show and hide the script window depending on whether or not
// there are loaded scripts
if ( mScripts . Num ( ) < 1 )
{
ShowWindow ( mWndScript , SW_HIDE ) ;
return ;
}
else
{
ShowWindow ( mWndScript , SW_SHOW ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Update the script
SendMessage ( mWndScript , EM_SETSEL , 0 , - 1 ) ;
SendMessage ( mWndScript , EM_REPLACESEL , 0 , ( LPARAM ) " " ) ;
SendMessage ( mWndScript , EM_SETSEL , 0 , - 1 ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndScript , EM_REPLACESEL , 0 , ( LPARAM ) mScripts [ mActiveScript ] - > GetContents ( ) ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateWindowMenu
Updates the windows displayed in the window menu
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateWindowMenu ( void )
{
while ( GetMenuItemCount ( mWindowMenu ) > mWindowMenuPos )
{
DeleteMenu ( mWindowMenu , mWindowMenuPos , MF_BYPOSITION ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mScripts . Num ( ) )
{
AppendMenu ( mWindowMenu , MF_SEPARATOR , 0 , " " ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
int i ;
for ( i = 0 ; i < mScripts . Num ( ) ; i + + )
{
idStr name ;
name = mScripts [ i ] - > GetFilename ( ) ;
name . StripPath ( ) ;
name = idStr ( va ( " &%d " , i + 1 ) ) + name ;
AppendMenu ( mWindowMenu , MF_STRING , ID_DBG_WINDOWMIN + i , name ) ;
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateCallstack
Updates the contents of teh callastack
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateCallstack ( void )
{
LVITEM item ;
ListView_DeleteAllItems ( mWndCallstack ) ;
ZeroMemory ( & item , sizeof ( item ) ) ;
item . mask = LVIF_TEXT | LVIF_IMAGE ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( int i = 0 ; i < mClient - > GetCallstack ( ) . Num ( ) ; i + + )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
rvDebuggerCallstack * entry = mClient - > GetCallstack ( ) [ i ] ;
item . iItem = ListView_GetItemCount ( mWndCallstack ) ;
item . pszText = " " ;
item . iImage = ( i = = mCurrentStackDepth ) ? 1 : 0 ;
ListView_InsertItem ( mWndCallstack , & item ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
ListView_SetItemText ( mWndCallstack , item . iItem , 1 , ( LPSTR ) entry - > mFunction . c_str ( ) ) ;
ListView_SetItemText ( mWndCallstack , item . iItem , 2 , va ( " %d " , entry - > mLineNumber ) ) ;
ListView_SetItemText ( mWndCallstack , item . iItem , 3 , ( LPSTR ) entry - > mFilename . c_str ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateWatch
Updates the contents of the watch window
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateWatch ( void )
{
int i ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Inspect all the variables we are watching
for ( i = 0 ; i < mWatches . Num ( ) ; i + + )
{
mWatches [ i ] - > mModified = false ;
mClient - > InspectVariable ( mWatches [ i ] - > mVariable , mCurrentStackDepth ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
InvalidateRect ( mWndWatch , NULL , FALSE ) ;
UpdateWindow ( mWndWatch ) ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleInitMenu
Handles the initialization of the main menu
= = = = = = = = = = = = = = = =
*/
2011-12-06 18:20:15 +00:00
int rvDebuggerWindow : : HandleInitMenu ( WPARAM wParam , LPARAM lParam )
{
int cMenuItems = GetMenuItemCount ( ( HMENU ) wParam ) ;
int nPos ;
int id ;
UINT flags ;
HMENU hmenu ;
2011-11-22 21:28:15 +00:00
hmenu = ( HMENU ) wParam ;
// Run through all the menu items in the menu and see if any of them need
// modification in any way
2011-12-06 18:20:15 +00:00
for ( nPos = 0 ; nPos < cMenuItems ; nPos + + )
{
id = GetMenuItemID ( hmenu , nPos ) ;
flags = 0 ;
2011-11-22 21:28:15 +00:00
// Handle popup menus too
if ( id < 0 )
{
HMENU sub = GetSubMenu ( hmenu , nPos ) ;
if ( sub )
{
HandleInitMenu ( ( WPARAM ) sub , 0 ) ;
continue ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Handle the dynamic menu items specially
if ( id > = ID_DBG_WINDOWMIN & & id < = ID_DBG_WINDOWMAX )
{
if ( id - ID_DBG_WINDOWMIN = = mActiveScript )
{
CheckMenuItem ( hmenu , nPos , MF_BYPOSITION | MF_CHECKED ) ;
}
else
{
CheckMenuItem ( hmenu , nPos , MF_BYPOSITION | MF_UNCHECKED ) ;
}
continue ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Menu items that are completely unrelated to the workspace
switch ( id )
{
case ID_DBG_DEBUG_RUN :
{
MENUITEMINFO info ;
idStr run ;
info . cbSize = sizeof ( info ) ;
info . fMask = MIIM_TYPE | MIIM_STATE ;
2011-12-06 18:20:15 +00:00
info . fType = MFT_STRING ;
2011-11-22 21:28:15 +00:00
if ( ! mClient - > IsConnected ( ) )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
run = " Run " ;
info . fState = MFS_ENABLED ;
}
else
{
run = " Continue " ;
info . fState = mClient - > IsStopped ( ) ? MFS_ENABLED : MFS_GRAYED ;
}
info . dwTypeData = ( LPSTR ) run . c_str ( ) ;
info . cch = run . Length ( ) ;
SendMessage ( mWndToolbar , TB_ENABLEBUTTON , id , MAKELONG ( ( ( info . fState = = MFS_ENABLED ) ? TRUE : FALSE ) , 0 ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SetMenuItemInfo ( hmenu , id , FALSE , & info ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_BREAK :
if ( ! mClient - > IsConnected ( ) | | mClient - > IsStopped ( ) )
{
EnableMenuItem ( hmenu , nPos , MF_GRAYED | MF_BYPOSITION ) ;
SendMessage ( mWndToolbar , TB_ENABLEBUTTON , id , MAKELONG ( FALSE , 0 ) ) ;
}
else
{
EnableMenuItem ( hmenu , nPos , MF_ENABLED | MF_BYPOSITION ) ;
SendMessage ( mWndToolbar , TB_ENABLEBUTTON , id , MAKELONG ( TRUE , 0 ) ) ;
}
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_RUNTOCURSOR :
case ID_DBG_DEBUG_STEPOUT :
case ID_DBG_DEBUG_STEPOVER :
case ID_DBG_DEBUG_STEPINTO :
case ID_DBG_DEBUG_SHOWNEXTSTATEMENT :
// case ID_DBG_DEBUG_QUICKWATCH:
if ( ! mClient - > IsConnected ( ) | | ! mClient - > IsStopped ( ) )
{
2011-12-06 18:20:15 +00:00
EnableMenuItem ( hmenu , nPos , MF_GRAYED | MF_BYPOSITION ) ;
2011-11-22 21:28:15 +00:00
SendMessage ( mWndToolbar , TB_ENABLEBUTTON , id , MAKELONG ( FALSE , 0 ) ) ;
}
else
{
2011-12-06 18:20:15 +00:00
EnableMenuItem ( hmenu , nPos , MF_ENABLED | MF_BYPOSITION ) ;
2011-11-22 21:28:15 +00:00
SendMessage ( mWndToolbar , TB_ENABLEBUTTON , id , MAKELONG ( TRUE , 0 ) ) ;
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_WINDOW_CLOSEALL :
case ID_DBG_FILE_CLOSE :
case ID_DBG_DEBUG_TOGGLEBREAKPOINT :
case ID_DBG_EDIT_FIND :
EnableMenuItem ( hmenu , nPos , ( mScripts . Num ( ) ? MF_ENABLED : MF_GRAYED ) | MF_BYPOSITION ) ;
break ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return 0 ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleCreate
Handles the WM_CREATE command
= = = = = = = = = = = = = = = =
*/
2011-12-06 18:20:15 +00:00
int rvDebuggerWindow : : HandleCreate ( WPARAM wparam , LPARAM lparam )
2011-11-22 21:28:15 +00:00
{
UINT tabsize = 16 ;
TEXTMETRIC tm ;
HDC dc ;
LOGFONT lf ;
int i ;
gDebuggerApp . GetOptions ( ) . GetWindowPlacement ( " wp_main " , mWnd ) ;
// Create the main toolbar
CreateToolbar ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// 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_SETWORDBREAKPROC , 0 , ( LPARAM ) ScriptWordBreakProc ) ;
mOldScriptProc = ( WNDPROC ) GetWindowLong ( mWndScript , GWL_WNDPROC ) ;
SetWindowLong ( mWndScript , GWL_USERDATA , ( LONG ) this ) ;
SetWindowLong ( mWndScript , GWL_WNDPROC , ( LONG ) ScriptWndProc ) ;
SendMessage ( mWndScript , EM_SETTABSTOPS , 1 , ( LPARAM ) & tabsize ) ;
dc = GetDC ( mWndScript ) ;
GetTextMetrics ( dc , & tm ) ;
ZeroMemory ( & lf , sizeof ( lf ) ) ;
lf . lfHeight = tm . tmHeight ;
2011-12-06 18:20:15 +00:00
strcpy ( lf . lfFaceName , " Courier New " ) ;
2011-11-22 21:28:15 +00:00
SendMessage ( mWndScript , WM_SETFONT , ( WPARAM ) CreateFontIndirect ( & lf ) , 0 ) ;
SendMessage ( mWndScript , EM_SETMARGINS , EC_LEFTMARGIN | EC_RIGHTMARGIN , MAKELONG ( 18 , 10 ) ) ;
SendMessage ( mWndScript , EM_SETBKGNDCOLOR , 0 , GetSysColor ( COLOR_3DFACE ) ) ;
mWndOutput = CreateWindow ( " RichEdit20A " , " " , WS_CHILD | ES_READONLY | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE , 0 , 0 , 100 , 100 , mWnd , ( HMENU ) IDC_DBG_OUTPUT , mInstance , 0 ) ;
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 ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
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 ) ;
SendMessage ( mWndConsole , EM_SETMARGINS , EC_LEFTMARGIN | EC_RIGHTMARGIN , MAKELONG ( 18 , 10 ) ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndConsole , EM_SETBKGNDCOLOR , 0 , GetSysColor ( COLOR_3DFACE ) ) ;
2011-11-22 21:28:15 +00:00
mWndMargin = CreateWindow ( " STATIC " , " " , WS_VISIBLE | WS_CHILD , 0 , 0 , 0 , 0 , mWndScript , ( HMENU ) IDC_DBG_SPLITTER , mInstance , NULL ) ;
SetWindowLong ( mWndMargin , GWL_USERDATA , ( LONG ) this ) ;
SetWindowLong ( mWndMargin , GWL_WNDPROC , ( LONG ) MarginWndProc ) ;
mWndBorder = CreateWindow ( " STATIC " , " " , WS_VISIBLE | WS_CHILD | SS_GRAYFRAME , 0 , 0 , 0 , 0 , mWnd , ( HMENU ) IDC_DBG_BORDER , mInstance , NULL ) ;
GetClientRect ( mWnd , & mSplitterRect ) ;
mSplitterRect . top = ( mSplitterRect . bottom - mSplitterRect . top ) / 2 ;
mSplitterRect . bottom = mSplitterRect . top + 4 ;
mWndTabs = CreateWindow ( WC_TABCONTROL , " " , TCS_BOTTOM | WS_CHILD | WS_VISIBLE | TCS_FOCUSNEVER , 0 , 0 , 0 , 0 , mWnd , ( HMENU ) IDC_DBG_TABS , mInstance , NULL ) ;
lf . lfHeight = - MulDiv ( 8 , GetDeviceCaps ( dc , LOGPIXELSY ) , 72 ) ;
2011-12-06 18:20:15 +00:00
strcpy ( lf . lfFaceName , " Arial " ) ;
2011-11-22 21:28:15 +00:00
SendMessage ( mWndTabs , WM_SETFONT , ( WPARAM ) CreateFontIndirect ( & lf ) , 0 ) ;
ReleaseDC ( mWndScript , dc ) ;
TCITEM item ;
item . mask = TCIF_TEXT ;
item . pszText = " Output " ;
TabCtrl_InsertItem ( mWndTabs , 0 , & item ) ;
item . pszText = " Console " ;
TabCtrl_InsertItem ( mWndTabs , 1 , & item ) ;
item . pszText = " Call Stack " ;
TabCtrl_InsertItem ( mWndTabs , 2 , & item ) ;
item . pszText = " Watch " ;
TabCtrl_InsertItem ( mWndTabs , 3 , & item ) ;
item . pszText = " Threads " ;
TabCtrl_InsertItem ( mWndTabs , 4 , & 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 ) ;
LVCOLUMN col ;
col . mask = LVCF_WIDTH | LVCF_TEXT ;
col . cx = 20 ;
col . pszText = " " ;
ListView_InsertColumn ( mWndCallstack , 0 , & col ) ;
col . cx = 150 ;
col . pszText = " Function " ;
ListView_InsertColumn ( mWndCallstack , 1 , & col ) ;
col . cx = 150 ;
col . pszText = " Line " ;
ListView_InsertColumn ( mWndCallstack , 2 , & col ) ;
col . cx = 150 ;
col . pszText = " Filename " ;
ListView_InsertColumn ( mWndCallstack , 3 , & col ) ;
col . cx = 20 ;
col . pszText = " " ;
ListView_InsertColumn ( mWndThreads , 0 , & col ) ;
col . cx = 25 ;
col . pszText = " ID " ;
ListView_InsertColumn ( mWndThreads , 1 , & col ) ;
col . cx = 150 ;
col . pszText = " Name " ;
ListView_InsertColumn ( mWndThreads , 2 , & col ) ;
col . cx = 100 ;
col . pszText = " State " ;
ListView_InsertColumn ( mWndThreads , 3 , & col ) ;
col . cx = 150 ;
col . pszText = " Name " ;
ListView_InsertColumn ( mWndWatch , 0 , & col ) ;
col . cx = 200 ;
col . pszText = " Value " ;
ListView_InsertColumn ( mWndWatch , 1 , & col ) ;
2011-12-06 18:20:15 +00:00
// Create the image list that is used by the threads window, callstack window, and
2011-11-22 21:28:15 +00:00
// margin window
mImageList = ImageList_Create ( 16 , 16 , ILC_COLOR | ILC_MASK , 0 , 2 ) ;
ImageList_AddIcon ( mImageList , ( HICON ) LoadImage ( mInstance , MAKEINTRESOURCE ( IDI_DBG_EMPTY ) , IMAGE_ICON , 16 , 16 , LR_DEFAULTSIZE | LR_DEFAULTCOLOR ) ) ;
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 ) ) ;
ListView_SetImageList ( mWndThreads , mImageList , LVSIL_SMALL ) ;
ListView_SetImageList ( mWndCallstack , mImageList , LVSIL_SMALL ) ;
EnableWindows ( FALSE ) ;
ListView_SetExtendedListViewStyle ( mWndCallstack , LVS_EX_FULLROWSELECT ) ;
ListView_SetExtendedListViewStyle ( mWndThreads , LVS_EX_FULLROWSELECT ) ;
gDebuggerApp . GetOptions ( ) . GetColumnWidths ( " cw_callstack " , mWndCallstack ) ;
gDebuggerApp . GetOptions ( ) . GetColumnWidths ( " cw_threads " , mWndThreads ) ;
gDebuggerApp . GetOptions ( ) . GetColumnWidths ( " cw_watch " , mWndWatch ) ;
mWndToolTips = CreateWindowEx ( WS_EX_TOPMOST ,
2011-12-06 18:20:15 +00:00
TOOLTIPS_CLASS ,
2011-11-22 21:28:15 +00:00
NULL ,
2011-12-06 18:20:15 +00:00
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP ,
2011-11-22 21:28:15 +00:00
CW_USEDEFAULT ,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
mWnd ,
NULL ,
mInstance ,
NULL
) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SendMessage ( mWndToolTips , TTM_SETDELAYTIME , TTDT_INITIAL , MAKELONG ( 400 , 0 ) ) ;
SendMessage ( mWndToolTips , TTM_SETDELAYTIME , TTDT_RESHOW , MAKELONG ( 400 , 0 ) ) ;
SetWindowPos ( mWndToolTips , HWND_TOPMOST , 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
LVITEM lvItem ;
lvItem . iItem = 0 ;
lvItem . iSubItem = 0 ;
lvItem . mask = LVIF_TEXT ;
lvItem . pszText = " " ;
ListView_InsertItem ( mWndWatch , & lvItem ) ;
2011-12-06 18:20:15 +00:00
ListView_SetExtendedListViewStyle ( mWndWatch , LVS_EX_FULLROWSELECT ) ;
2011-11-22 21:28:15 +00:00
// Recent files
InitRecentFiles ( ) ;
UpdateRecentFiles ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
HandleInitMenu ( ( WPARAM ) GetMenu ( mWnd ) , 0 ) ;
// Read in the watches
for ( i = 0 ; ; i + + )
{
const char * s = gDebuggerApp . GetOptions ( ) . GetString ( va ( " watch%d " , i ) ) ;
if ( ! s | | ! s [ 0 ] )
{
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
AddWatch ( s ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return 0 ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleCommand
Handles the WM_COMMAND message for this window
= = = = = = = = = = = = = = = =
*/
2011-12-06 18:20:15 +00:00
int rvDebuggerWindow : : HandleCommand ( WPARAM wparam , LPARAM lparam )
{
2011-11-22 21:28:15 +00:00
int event = HIWORD ( wparam ) ;
int id = LOWORD ( wparam ) ;
2011-12-06 18:20:15 +00:00
// The window menu list needs to be handled specially
2011-11-22 21:28:15 +00:00
if ( id > = ID_DBG_WINDOWMIN & & id < = ID_DBG_WINDOWMAX )
{
mActiveScript = id - ID_DBG_WINDOWMIN ;
UpdateScript ( ) ;
return 0 ;
}
// The recent file list needs to be handled specially
if ( LOWORD ( wparam ) > = ID_DBG_FILE_MRU1 & & LOWORD ( wparam ) < ID_DBG_FILE_MRU1 + rvRegistryOptions : : MAX_MRU_SIZE )
{
idStr filename ;
filename = gDebuggerApp . GetOptions ( ) . GetRecentFile ( gDebuggerApp . GetOptions ( ) . GetRecentFileCount ( ) - ( LOWORD ( wparam ) - ID_DBG_FILE_MRU1 ) - 1 ) ;
if ( ! OpenScript ( filename ) )
{
MessageBox ( mWnd , va ( " Failed to open script '%s' " , filename . c_str ( ) ) , " Quake 4 Script Debugger " , MB_OK ) ;
}
return 0 ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( id )
{
case ID_DBG_EDIT_FINDSELECTED :
{
2011-12-06 18:20:15 +00:00
idStr text ;
GetSelectedText ( text ) ;
2011-11-22 21:28:15 +00:00
FindNext ( text ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_EDIT_FINDSELECTEDPREV :
{
2011-12-06 18:20:15 +00:00
idStr text ;
GetSelectedText ( text ) ;
2011-11-22 21:28:15 +00:00
FindPrev ( text ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_EDIT_FINDNEXT :
FindNext ( ) ;
break ;
case ID_DBG_EDIT_FINDPREV :
FindPrev ( ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_QUICKWATCH :
{
idStr text ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
GetSelectedText ( text ) ;
rvDebuggerQuickWatchDlg dlg ;
dlg . DoModal ( this , mCurrentStackDepth , text ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_HELP_ABOUT :
DialogBox ( mInstance , MAKEINTRESOURCE ( IDD_DBG_ABOUT ) , mWnd , AboutDlgProc ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_BREAK :
mClient - > Break ( ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_STEPOVER :
EnableWindows ( FALSE ) ;
mClient - > StepOver ( ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_STEPINTO :
EnableWindows ( FALSE ) ;
mClient - > StepInto ( ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_RUN :
// Run the game if its not running
if ( ! mClient - > IsConnected ( ) )
{
char exeFile [ MAX_PATH ] ;
char curDir [ MAX_PATH ] ;
STARTUPINFO startup ;
PROCESS_INFORMATION process ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
ZeroMemory ( & startup , sizeof ( startup ) ) ;
2011-12-06 18:20:15 +00:00
startup . cb = sizeof ( startup ) ;
2011-11-22 21:28:15 +00:00
GetCurrentDirectory ( MAX_PATH , curDir ) ;
GetModuleFileName ( NULL , exeFile , MAX_PATH ) ;
const char * s = va ( " %s +set fs_game %s +set fs_cdpath %s " , exeFile , cvarSystem - > GetCVarString ( " fs_game " ) , cvarSystem - > GetCVarString ( " fs_cdpath " ) ) ;
CreateProcess ( NULL , ( LPSTR ) s ,
NULL , NULL , FALSE , 0 , NULL , curDir , & startup , & process ) ;
CloseHandle ( process . hThread ) ;
CloseHandle ( process . hProcess ) ;
}
else if ( mClient - > IsStopped ( ) )
{
EnableWindows ( FALSE ) ;
mClient - > Resume ( ) ;
UpdateToolbar ( ) ;
UpdateTitle ( ) ;
InvalidateRect ( mWnd , NULL , FALSE ) ;
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case IDC_DBG_SCRIPT :
{
2011-12-06 18:20:15 +00:00
RECT t ;
2011-11-22 21:28:15 +00:00
LONG num ;
LONG dem ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SendMessage ( mWndScript , EM_GETZOOM , ( LONG ) & num , ( LONG ) & dem ) ;
if ( num ! = mZoomScaleNum | | dem ! = mZoomScaleDem )
{
mZoomScaleNum = num ;
mZoomScaleDem = dem ;
GetClientRect ( mWndScript , & t ) ;
SendMessage ( mWnd , WM_SIZE , 0 , MAKELPARAM ( t . right - t . left , t . bottom - t . top ) ) ;
}
else
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
InvalidateRect ( mWndMargin , NULL , TRUE ) ;
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_TOGGLEBREAKPOINT :
ToggleBreakpoint ( ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_FILE_EXIT :
PostMessage ( mWnd , WM_CLOSE , 0 , 0 ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_FILE_CLOSE :
if ( mScripts . Num ( ) )
{
delete mScripts [ mActiveScript ] ;
mScripts . RemoveIndex ( mActiveScript ) ;
if ( mActiveScript > = mScripts . Num ( ) )
{
mActiveScript - - ;
}
UpdateWindowMenu ( ) ;
UpdateScript ( ) ;
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_FILE_NEXT :
if ( mScripts . Num ( ) > 0 )
{
mActiveScript + + ;
if ( mActiveScript > = mScripts . Num ( ) )
{
mActiveScript = 0 ;
}
UpdateWindowMenu ( ) ;
2011-12-06 18:20:15 +00:00
UpdateScript ( ) ;
2011-11-22 21:28:15 +00:00
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_FILE_OPEN :
{
rvOpenFileDialog dlg ;
dlg . SetTitle ( " Open Script " ) ;
dlg . SetFilter ( " *.script; *.gui; *.state " ) ;
dlg . SetFlags ( OFD_MUSTEXIST ) ;
if ( dlg . DoModal ( mWnd ) )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
if ( ! OpenScript ( dlg . GetFilename ( ) ) )
{
MessageBox ( mWnd , va ( " Failed to open script '%s' " , dlg . GetFilename ( ) ) , " Quake 4 Script Debugger " , MB_OK ) ;
}
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_EDIT_FIND :
{
rvDebuggerFindDlg dlg ;
if ( dlg . DoModal ( this ) )
{
FindNext ( dlg . GetFindText ( ) ) ;
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_WINDOW_CLOSEALL :
{
for ( int i = 0 ; i < mScripts . Num ( ) ; i + + )
{
delete mScripts [ i ] ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mScripts . Clear ( ) ;
mActiveScript = - 1 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
UpdateWindowMenu ( ) ;
UpdateScript ( ) ;
break ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return 0 ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : WndProc
Window procedure for the deubgger window
= = = = = = = = = = = = = = = =
*/
LRESULT CALLBACK rvDebuggerWindow : : WndProc ( HWND wnd , UINT msg , WPARAM wparam , LPARAM lparam )
{
rvDebuggerWindow * window = ( rvDebuggerWindow * ) GetWindowLong ( wnd , GWL_USERDATA ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( msg )
{
case WM_INITMENUPOPUP :
window - > HandleInitMenu ( wparam , lparam ) ;
break ;
case WM_DESTROY :
{
gDebuggerApp . GetOptions ( ) . SetColumnWidths ( " cw_callstack " , window - > mWndCallstack ) ;
2011-12-06 18:20:15 +00:00
gDebuggerApp . GetOptions ( ) . SetColumnWidths ( " cw_threads " , window - > mWndThreads ) ;
2011-11-22 21:28:15 +00:00
gDebuggerApp . GetOptions ( ) . SetColumnWidths ( " cw_watch " , window - > mWndWatch ) ;
gDebuggerApp . GetOptions ( ) . SetWindowPlacement ( " wp_main " , wnd ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
int i ;
for ( i = 0 ; i < window - > mWatches . Num ( ) ; i + + )
{
gDebuggerApp . GetOptions ( ) . SetString ( va ( " watch%d " , i ) , window - > mWatches [ i ] - > mVariable ) ;
}
gDebuggerApp . GetOptions ( ) . SetString ( va ( " watch%d " , i ) , " " ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
window - > mWnd = NULL ;
2011-12-06 18:20:15 +00:00
SetWindowLong ( wnd , GWL_USERDATA , 0 ) ;
2011-11-22 21:28:15 +00:00
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_ERASEBKGND :
return 0 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_COMMAND :
window - > HandleCommand ( wparam , lparam ) ;
2011-12-06 18:20:15 +00:00
break ;
2011-11-22 21:28:15 +00:00
case WM_SETCURSOR :
{
POINT point ;
GetCursorPos ( & point ) ;
ScreenToClient ( wnd , & point ) ;
if ( PtInRect ( & window - > mSplitterRect , point ) )
{
SetCursor ( LoadCursor ( NULL , IDC_SIZENS ) ) ;
return true ;
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_SIZE :
{
RECT rect ;
window - > mMarginSize = window - > mZoomScaleDem ? ( ( long ) ( 18.0f * ( float ) window - > mZoomScaleNum / ( float ) window - > mZoomScaleDem ) ) : 18 ;
window - > mSplitterRect . left = 0 ;
window - > mSplitterRect . right = LOWORD ( lparam ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SendMessage ( window - > mWndToolbar , TB_AUTOSIZE , 0 , 0 ) ;
GetWindowRect ( window - > mWndToolbar , & rect ) ;
MoveWindow ( window - > mWndScript , 0 , rect . bottom - rect . top , LOWORD ( lparam ) , window - > mSplitterRect . top - ( rect . bottom - rect . top ) , TRUE ) ;
MoveWindow ( window - > mWndMargin , 0 , 0 , window - > mMarginSize , window - > mSplitterRect . top - ( rect . bottom - rect . top ) , TRUE ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
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 ;
MoveWindow ( window - > mWndBorder , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , TRUE ) ;
2011-12-06 18:20:15 +00:00
InflateRect ( & rect , - 1 , - 1 ) ;
2011-11-22 21:28:15 +00:00
MoveWindow ( window - > mWndOutput , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , TRUE ) ;
MoveWindow ( window - > mWndConsole , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , TRUE ) ;
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 ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_PAINT :
{
PAINTSTRUCT ps ;
2011-12-06 18:20:15 +00:00
HDC dc = BeginPaint ( wnd , & ps ) ;
2011-11-22 21:28:15 +00:00
FillRect ( dc , & window - > mSplitterRect , GetSysColorBrush ( COLOR_3DFACE ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( ! window - > mScripts . Num ( ) )
{
RECT rect ;
GetClientRect ( wnd , & rect ) ;
rect . bottom = window - > mSplitterRect . top ;
FillRect ( dc , & rect , GetSysColorBrush ( COLOR_APPWORKSPACE ) ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
EndPaint ( wnd , & ps ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_LBUTTONDOWN :
{
POINT pt = { LOWORD ( lparam ) , HIWORD ( lparam ) } ;
if ( PtInRect ( & window - > mSplitterRect , pt ) )
{
window - > mSplitterDrag = true ;
SetCapture ( wnd ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
HDC dc = GetDC ( wnd ) ;
DrawFocusRect ( dc , & window - > mSplitterRect ) ;
ReleaseDC ( wnd , dc ) ;
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_LBUTTONUP :
if ( window - > mSplitterDrag )
{
HDC dc = GetDC ( wnd ) ;
DrawFocusRect ( dc , & window - > mSplitterRect ) ;
ReleaseDC ( wnd , dc ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
window - > mSplitterDrag = false ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
RECT client ;
GetClientRect ( wnd , & client ) ;
SendMessage ( wnd , WM_SIZE , 0 , MAKELPARAM ( client . right - client . left , client . bottom - client . top ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
InvalidateRect ( wnd , NULL , TRUE ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
ReleaseCapture ( ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_MOUSEMOVE :
{
if ( window - > mSplitterDrag )
{
HDC dc = GetDC ( wnd ) ;
DrawFocusRect ( dc , & window - > mSplitterRect ) ;
ReleaseDC ( wnd , dc ) ;
if ( GetCapture ( ) ! = wnd )
{
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
RECT client ;
GetClientRect ( wnd , & client ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
window - > mSplitterRect . top = HIWORD ( lparam ) ;
if ( window - > mSplitterRect . top < client . top )
{
window - > mSplitterRect . top = client . top ;
}
else if ( window - > mSplitterRect . top + 4 > client . bottom )
{
window - > mSplitterRect . top = client . bottom - 4 ;
}
window - > mSplitterRect . bottom = window - > mSplitterRect . top + 4 ;
dc = GetDC ( wnd ) ;
DrawFocusRect ( dc , & window - > mSplitterRect ) ;
ReleaseDC ( wnd , dc ) ;
}
break ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
case WM_DRAWITEM :
window - > HandleDrawItem ( wparam , lparam ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_CREATE :
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
CREATESTRUCT * cs = ( CREATESTRUCT * ) lparam ;
window = ( rvDebuggerWindow * ) cs - > lpCreateParams ;
SetWindowLong ( wnd , GWL_USERDATA , ( LONG ) cs - > lpCreateParams ) ;
window - > mWnd = wnd ;
window - > HandleCreate ( wparam , lparam ) ;
break ;
}
2011-12-06 18:20:15 +00:00
case WM_ACTIVATE :
2011-11-22 21:28:15 +00:00
window - > HandleActivate ( wparam , lparam ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_NOTIFY :
{
NMHDR * hdr ;
hdr = ( NMHDR * ) lparam ;
// Tool tips
if ( hdr - > code = = TTN_GETDISPINFO )
{
window - > HandleTooltipGetDispInfo ( wparam , lparam ) ;
break ;
}
switch ( hdr - > idFrom )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
case IDC_DBG_WATCH :
switch ( hdr - > code )
{
case LVN_KEYDOWN :
{
NMLVKEYDOWN * key = ( NMLVKEYDOWN * ) hdr ;
switch ( key - > wVKey )
{
case VK_DELETE :
{
int sel = ListView_GetNextItem ( hdr - > hwndFrom , - 1 , LVNI_SELECTED ) ;
if ( sel ! = - 1 & & sel ! = ListView_GetItemCount ( hdr - > hwndFrom ) - 1 )
{
LVITEM item ;
item . iItem = sel ;
item . mask = LVIF_PARAM ;
ListView_GetItem ( hdr - > hwndFrom , & item ) ;
ListView_DeleteItem ( hdr - > hwndFrom , sel ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
window - > mWatches . Remove ( ( rvDebuggerWatch * ) item . lParam ) ;
delete ( rvDebuggerWatch * ) item . lParam ;
2011-12-06 18:20:15 +00:00
ListView_SetItemState ( hdr - > hwndFrom ,
sel ,
LVIS_SELECTED , LVIS_SELECTED ) ;
2011-11-22 21:28:15 +00:00
if ( ListView_GetNextItem ( hdr - > hwndFrom , - 1 , LVNI_SELECTED ) = = - 1 )
{
2011-12-06 18:20:15 +00:00
ListView_SetItemState ( hdr - > hwndFrom ,
ListView_GetItemCount ( hdr - > hwndFrom ) - 1 ,
LVIS_SELECTED , LVIS_SELECTED ) ;
2011-11-22 21:28:15 +00:00
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case VK_RETURN :
{
int sel = ListView_GetNextItem ( hdr - > hwndFrom , - 1 , LVNI_SELECTED ) ;
if ( sel ! = - 1 )
{
ListView_EditLabel ( hdr - > hwndFrom , sel ) ;
}
break ;
}
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case LVN_BEGINLABELEDIT :
{
NMLVDISPINFO * di = ( NMLVDISPINFO * ) hdr ;
DWORD style = GetWindowLong ( ListView_GetEditControl ( hdr - > hwndFrom ) , GWL_STYLE ) ;
SetWindowLong ( ListView_GetEditControl ( hdr - > hwndFrom ) , GWL_STYLE , style & ( ~ WS_BORDER ) ) ;
2011-12-06 18:20:15 +00:00
rvDebuggerWatch * watch = ( rvDebuggerWatch * ) di - > item . lParam ;
2011-11-22 21:28:15 +00:00
if ( watch )
{
SetWindowText ( ListView_GetEditControl ( hdr - > hwndFrom ) , watch - > mVariable ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return FALSE ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case LVN_ENDLABELEDIT :
{
NMLVDISPINFO * di = ( NMLVDISPINFO * ) hdr ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( di - > item . iItem = = ListView_GetItemCount ( hdr - > hwndFrom ) - 1 )
{
if ( ! di - > item . pszText | | ! di - > item . pszText [ 0 ] )
{
return FALSE ;
}
2011-12-06 18:20:15 +00:00
window - > AddWatch ( ( ( NMLVDISPINFO * ) hdr ) - > item . pszText ) ;
2011-11-22 21:28:15 +00:00
window - > UpdateWatch ( ) ;
return FALSE ;
}
else
{
rvDebuggerWatch * watch = ( rvDebuggerWatch * ) di - > item . lParam ;
if ( watch & & di - > item . pszText & & di - > item . pszText [ 0 ] )
{
watch - > mVariable = di - > item . pszText ;
}
}
return TRUE ;
}
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case IDC_DBG_CALLSTACK :
if ( hdr - > code = = NM_DBLCLK )
{
int sel = ListView_GetNextItem ( hdr - > hwndFrom , - 1 , LVNI_SELECTED ) ;
if ( sel ! = - 1 )
{
window - > mCurrentStackDepth = sel ;
window - > UpdateCallstack ( ) ;
window - > UpdateWatch ( ) ;
window - > OpenScript ( window - > mClient - > GetCallstack ( ) [ window - > mCurrentStackDepth ] - > mFilename ,
window - > mClient - > GetCallstack ( ) [ window - > mCurrentStackDepth ] - > mLineNumber ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
break ;
case IDC_DBG_TABS :
if ( hdr - > code = = TCN_SELCHANGE )
{
ShowWindow ( window - > mWndOutput , SW_HIDE ) ;
ShowWindow ( window - > mWndConsole , SW_HIDE ) ;
ShowWindow ( window - > mWndCallstack , SW_HIDE ) ;
ShowWindow ( window - > mWndWatch , SW_HIDE ) ;
ShowWindow ( window - > mWndThreads , SW_HIDE ) ;
switch ( TabCtrl_GetCurSel ( hdr - > hwndFrom ) )
{
case 0 :
ShowWindow ( window - > mWndOutput , SW_SHOW ) ;
break ;
case 1 :
ShowWindow ( window - > mWndConsole , SW_SHOW ) ;
break ;
case 2 :
ShowWindow ( window - > mWndCallstack , SW_SHOW ) ;
break ;
case 3 :
ShowWindow ( window - > mWndWatch , SW_SHOW ) ;
break ;
case 4 :
ShowWindow ( window - > mWndThreads , SW_SHOW ) ;
break ;
}
}
break ;
}
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case WM_CLOSE :
if ( window - > mClient - > IsConnected ( ) )
{
if ( IDNO = = MessageBox ( wnd , " The debugger is currently connected to a running version of the game. Are you sure you want to close now? " , " Quake 4 Script Debugger " , MB_YESNO | MB_ICONQUESTION ) )
{
return 0 ;
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
PostQuitMessage ( 0 ) ;
break ;
}
return DefWindowProc ( wnd , msg , wparam , lparam ) ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : Activate
Static method that will activate the currently running debugger . If one is found
and activated then true will be returned .
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : Activate ( void )
{
HWND find ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
find = FindWindow ( DEBUGGERWINDOWCLASS , NULL ) ;
if ( ! find )
{
return false ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SetForegroundWindow ( find ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : ProcessNetMessage
Process an incoming network message
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : ProcessNetMessage ( msg_t * msg )
{
unsigned short command ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
command = ( unsigned short ) MSG_ReadShort ( msg ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( command )
{
case DBMSG_RESUMED :
UpdateTitle ( ) ;
UpdateToolbar ( ) ;
break ;
case DBMSG_INSPECTVARIABLE :
{
char temp [ 1024 ] ;
char temp2 [ 1024 ] ;
int i ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
MSG_ReadShort ( msg ) ;
MSG_ReadString ( msg , temp , 1024 ) ;
MSG_ReadString ( msg , temp2 , 1024 ) ;
if ( mTooltipVar . Icmp ( temp ) = = 0 )
{
mTooltipValue = temp2 ;
TOOLINFO info ;
info . cbSize = sizeof ( info ) ;
info . hwnd = mWndScript ;
info . uId = 0 ;
info . hinst = mInstance ;
info . lpszText = va ( " %s=%s " , mTooltipVar . c_str ( ) , mTooltipValue . c_str ( ) ) ;
SendMessage ( mWndToolTips , TTM_UPDATETIPTEXT , 0 , ( LPARAM ) & info ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndToolTips , TTM_UPDATE , 0 , 0 ) ;
2011-11-22 21:28:15 +00:00
}
// See if any of the watches were updated by this inspect
for ( i = 0 ; i < mWatches . Num ( ) ; i + + )
{
rvDebuggerWatch * watch = mWatches [ i ] ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// See if the name matches the variable
if ( watch - > mVariable . Cmp ( temp ) )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
continue ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Has the value changed?
if ( ! watch - > mValue . Cmp ( temp2 ) )
{
continue ;
}
2011-12-06 18:20:15 +00:00
watch - > mModified = true ;
watch - > mValue = temp2 ;
2011-11-22 21:28:15 +00:00
// Find the list view item that is storing this watch info and redraw it
for ( int l = 0 ; l < ListView_GetItemCount ( mWndWatch ) ; l + + )
{
LVITEM item ;
item . mask = LVIF_PARAM ;
item . iItem = l ;
ListView_GetItem ( mWndWatch , & item ) ;
2011-12-06 18:20:15 +00:00
if ( item . lParam = = ( LPARAM ) watch )
{
2011-11-22 21:28:15 +00:00
ListView_RedrawItems ( mWndWatch , l , l ) ;
UpdateWindow ( mWndWatch ) ;
break ;
}
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
break ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
case DBMSG_CONNECT :
case DBMSG_CONNECTED :
UpdateTitle ( ) ;
UpdateToolbar ( ) ;
2011-12-06 18:20:15 +00:00
Printf ( " Connected... \n " ) ;
2011-11-22 21:28:15 +00:00
break ;
case DBMSG_DISCONNECT :
UpdateTitle ( ) ;
UpdateToolbar ( ) ;
Printf ( " Disconnected... \n " ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case DBMSG_PRINT :
SendMessage ( mWndConsole , EM_SETSEL , - 1 , - 1 ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndConsole , EM_REPLACESEL , 0 , ( LPARAM ) ( const char * ) ( msg - > data ) + msg - > readcount ) ;
SendMessage ( mWndConsole , EM_SCROLLCARET , 0 , 0 ) ;
2011-11-22 21:28:15 +00:00
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case DBMSG_BREAK :
{
Printf ( " Break: line=%d file='%s' \n " , mClient - > GetBreakLineNumber ( ) , mClient - > GetBreakFilename ( ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mCurrentStackDepth = 0 ;
mClient - > InspectVariable ( mTooltipVar , mCurrentStackDepth ) ;
2011-12-06 18:20:15 +00:00
UpdateWatch ( ) ;
2011-11-22 21:28:15 +00:00
EnableWindows ( TRUE ) ;
OpenScript ( mClient - > GetBreakFilename ( ) , mClient - > GetBreakLineNumber ( ) - 1 ) ;
UpdateTitle ( ) ;
UpdateToolbar ( ) ;
SetForegroundWindow ( mWnd ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case DBMSG_INSPECTCALLSTACK :
{
UpdateCallstack ( ) ;
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case DBMSG_INSPECTTHREADS :
{
LVITEM item ;
ListView_DeleteAllItems ( mWndThreads ) ;
ZeroMemory ( & item , sizeof ( item ) ) ;
item . mask = LVIF_TEXT | LVIF_IMAGE ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( int i = 0 ; i < mClient - > GetThreads ( ) . Num ( ) ; i + + )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
rvDebuggerThread * entry = mClient - > GetThreads ( ) [ i ] ;
item . iItem = ListView_GetItemCount ( mWndThreads ) ;
item . pszText = " " ;
item . iImage = entry - > mCurrent ? 1 : 0 ;
2011-12-06 18:20:15 +00:00
ListView_InsertItem ( mWndThreads , & item ) ;
2011-11-22 21:28:15 +00:00
ListView_SetItemText ( mWndThreads , item . iItem , 1 , ( LPSTR ) va ( " %d " , entry - > mID ) ) ;
ListView_SetItemText ( mWndThreads , item . iItem , 2 , ( LPSTR ) entry - > mName . c_str ( ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( entry - > mDying )
{
ListView_SetItemText ( mWndThreads , item . iItem , 3 , " Dying " ) ;
}
else if ( entry - > mWaiting )
{
ListView_SetItemText ( mWndThreads , item . iItem , 3 , " Waiting " ) ;
}
else if ( entry - > mDoneProcessing )
{
ListView_SetItemText ( mWndThreads , item . iItem , 3 , " Stopped " ) ;
}
2011-12-06 18:20:15 +00:00
else
2011-11-22 21:28:15 +00:00
{
ListView_SetItemText ( mWndThreads , item . iItem , 3 , " Running " ) ;
}
}
break ;
}
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : Printf
Sends a formatted message to the output window
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : Printf ( const char * fmt , . . . )
{
va_list argptr ;
char msg [ 4096 ] ;
va_start ( argptr , fmt ) ;
vsprintf ( msg , fmt , argptr ) ;
va_end ( argptr ) ;
SendMessage ( mWndOutput , EM_SETSEL , - 1 , - 1 ) ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndOutput , EM_REPLACESEL , 0 , ( LPARAM ) msg ) ;
SendMessage ( mWndOutput , EM_SCROLLCARET , 0 , 0 ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : OpenScript
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 )
{
int i ;
SetCursor ( LoadCursor ( NULL , IDC_WAIT ) ) ;
mActiveScript = - 1 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// See if the script is already loaded
for ( i = 0 ; i < mScripts . Num ( ) ; i + + )
{
if ( ! idStr : : Icmp ( mScripts [ i ] - > GetFilename ( ) , filename ) )
{
if ( mActiveScript ! = i )
{
mActiveScript = i ;
break ;
}
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// If the script isnt open already then open it
if ( mActiveScript = = - 1 )
{
rvDebuggerScript * script = new rvDebuggerScript ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Load the script
if ( ! script - > Load ( filename ) )
{
delete script ;
SetCursor ( LoadCursor ( NULL , IDC_ARROW ) ) ;
return false ;
}
gDebuggerApp . GetOptions ( ) . AddRecentFile ( filename ) ;
UpdateRecentFiles ( ) ;
mActiveScript = mScripts . Append ( script ) ;
}
// Test code that will place a breakpoint on all valid lines of code
#if 0
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( i = 0 ; i < mScripts [ mActiveScript ] - > GetProgram ( ) . NumStatements ( ) ; i + + )
{
dstatement_t * st = & mScripts [ mActiveScript ] - > GetProgram ( ) . GetStatement ( i ) ;
rvDebuggerBreakpoint * bp = new rvDebuggerBreakpoint ( filename , st - > linenumber ) ;
mBreakpoints . Append ( bp ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
# endif
2011-12-06 18:20:15 +00:00
UpdateScript ( ) ;
2011-11-22 21:28:15 +00:00
UpdateWindowMenu ( ) ;
// Move to a specific line number?
if ( lineNumber ! = - 1 )
{
int c ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Put the caret on the line number specified and scroll it into position.
2011-12-06 18:20:15 +00:00
// This is a bit of a hack since we set the selection twice, but setting the
2011-11-22 21:28:15 +00:00
// selection to (c,c) didnt work for scrolling the caret so we do (c,c+1)
// 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 ) ;
SendMessage ( mWndScript , EM_SETSEL , c , c + 1 ) ;
SendMessage ( mWndScript , EM_SCROLLCARET , 0 , 0 ) ;
c = SendMessage ( mWndScript , EM_LINEINDEX , lineNumber , 0 ) ;
SendMessage ( mWndScript , EM_SETSEL , c , c ) ;
}
else
{
SendMessage ( mWndScript , EM_SETSEL , 0 , 0 ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
// Make sure the script window is visible
ShowWindow ( mWndScript , SW_SHOW ) ;
2011-12-06 18:20:15 +00:00
UpdateWindow ( mWndScript ) ;
2011-11-22 21:28:15 +00:00
SetCursor ( LoadCursor ( NULL , IDC_ARROW ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : ToggleBreakpoint
Toggles the breakpoint on the current script line
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : ToggleBreakpoint ( void )
{
rvDebuggerBreakpoint * bp ;
DWORD sel ;
int line ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Find the currently selected line
SendMessage ( mWndScript , EM_GETSEL , ( WPARAM ) & sel , 0 ) ;
line = SendMessage ( mWndScript , EM_LINEFROMCHAR , sel , 0 ) + 1 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// If there is already a breakpoint there then just remove it, otherwise
// we need to create a new breakpoint
bp = mClient - > FindBreakpoint ( mScripts [ mActiveScript ] - > GetFilename ( ) , line ) ;
if ( ! bp )
2011-12-06 18:20:15 +00:00
{
// Make sure the line is code before letting them add a breakpoint there
2011-11-22 21:28:15 +00:00
if ( ! mScripts [ mActiveScript ] - > IsLineCode ( line ) )
{
MessageBeep ( MB_ICONEXCLAMATION ) ;
return ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mClient - > AddBreakpoint ( mScripts [ mActiveScript ] - > GetFilename ( ) , line ) ;
}
else
{
mClient - > RemoveBreakpoint ( bp - > GetID ( ) ) ;
}
// Force a repaint of the script window
InvalidateRect ( mWndScript , NULL , FALSE ) ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : AboutDlgProc
Dialog box procedure for the about box
= = = = = = = = = = = = = = = =
*/
INT_PTR CALLBACK rvDebuggerWindow : : AboutDlgProc ( HWND wnd , UINT msg , WPARAM wparam , LPARAM lparam )
{
switch ( msg )
{
case WM_COMMAND :
EndDialog ( wnd , 0 ) ;
break ;
}
return FALSE ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : CreateToolbar
Create the toolbar and and all of its buttons
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : CreateToolbar ( void )
{
// Create the toolbar control
mWndToolbar = CreateWindowEx ( 0 , TOOLBARCLASSNAME , " " , WS_CHILD | WS_VISIBLE , 0 , 0 , 0 , 0 , mWnd , ( HMENU ) IDC_DBG_TOOLBAR , mInstance , NULL ) ;
// Initialize the toolbar
2011-12-06 18:20:15 +00:00
SendMessage ( mWndToolbar , TB_BUTTONSTRUCTSIZE , ( WPARAM ) sizeof ( TBBUTTON ) , 0 ) ;
SendMessage ( mWndToolbar , TB_SETBUTTONSIZE , 0 , MAKELONG ( 16 , 16 ) ) ;
2011-11-22 21:28:15 +00:00
SendMessage ( mWndToolbar , TB_SETSTYLE , 0 , SendMessage ( mWndToolbar , TB_GETSTYLE , 0 , 0 ) | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
TBMETRICS tbmet ;
tbmet . cbSize = sizeof ( TBMETRICS ) ;
SendMessage ( mWndToolbar , TB_GETMETRICS , 0 , ( LPARAM ) & tbmet ) ;
tbmet . cyPad = 0 ;
tbmet . cyBarPad = 0 ;
SendMessage ( mWndToolbar , TB_SETMETRICS , 0 , ( LPARAM ) & tbmet ) ;
2011-12-06 18:20:15 +00:00
// Add the bitmap containing button images to the toolbar.
TBADDBITMAP tbab ;
tbab . hInst = mInstance ;
tbab . nID = IDB_DBG_TOOLBAR ;
SendMessage ( mWndToolbar , TB_ADDBITMAP , ( WPARAM ) 4 , ( LPARAM ) & tbab ) ;
2011-11-22 21:28:15 +00:00
// Add the buttons to the toolbar
TBBUTTON tbb [ ] = { { 0 , 0 , TBSTATE_ENABLED , BTNS_SEP , 0 , 0 , - 1 } ,
{ 8 , ID_DBG_FILE_OPEN , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 0 , 0 , TBSTATE_ENABLED , BTNS_SEP , 0 , 0 , - 1 } ,
{ 0 , ID_DBG_DEBUG_RUN , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 1 , ID_DBG_DEBUG_BREAK , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 0 , 0 , TBSTATE_ENABLED , BTNS_SEP , 0 , 0 , - 1 } ,
{ 4 , ID_DBG_DEBUG_STEPINTO , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 5 , ID_DBG_DEBUG_STEPOVER , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 6 , ID_DBG_DEBUG_STEPOUT , TBSTATE_ENABLED , BTNS_BUTTON , 0 , 0 , - 1 } ,
{ 0 , 0 , TBSTATE_ENABLED , BTNS_SEP , 0 , 0 , - 1 } } ;
2011-12-06 18:20:15 +00:00
SendMessage ( mWndToolbar , TB_ADDBUTTONS , ( WPARAM ) sizeof ( tbb ) / sizeof ( TBBUTTON ) , ( LPARAM ) tbb ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleTooltipGetDispInfo
Handle the getdispinfo notification message for tooltips by responding with the
tooptip text for the given toolbar button .
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : HandleTooltipGetDispInfo ( WPARAM wparam , LPARAM lparam )
{
NMTTDISPINFO * ttdi = ( NMTTDISPINFO * ) lparam ;
switch ( ttdi - > hdr . idFrom )
{
case ID_DBG_FILE_OPEN :
strcpy ( ttdi - > szText , " Open Script " ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_STEPINTO :
strcpy ( ttdi - > szText , " Step Into " ) ;
break ;
case ID_DBG_DEBUG_STEPOVER :
strcpy ( ttdi - > szText , " Step Over " ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_STEPOUT :
strcpy ( ttdi - > szText , " Step Out " ) ;
break ;
case ID_DBG_DEBUG_BREAK :
strcpy ( ttdi - > szText , " Break " ) ;
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
case ID_DBG_DEBUG_RUN :
if ( mClient - > IsConnected ( ) )
{
strcpy ( ttdi - > szText , " Continue " ) ;
}
else
{
strcpy ( ttdi - > szText , " Run " ) ;
}
break ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
default :
strcpy ( ttdi - > szText , " " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleActivate
When the main window is activated , check all the loaded scripts and see if any of them
have been modified since the last time they were loaded . If they have then reload
them and adjust all breakpoints that now fall on invalid lines .
= = = = = = = = = = = = = = = =
*/
int rvDebuggerWindow : : HandleActivate ( WPARAM wparam , LPARAM lparam )
{
int i ;
// We are only interested in the activation, not deactivation
if ( ! LOWORD ( wparam ) )
{
return 0 ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Run through all of the loaded scripts and see if any of them have been modified
for ( i = 0 ; i < mScripts . Num ( ) ; i + + )
{
if ( mScripts [ i ] - > IsFileModified ( true ) )
{
if ( IDYES = = MessageBox ( mWnd , va ( " %s \n \n This file has been modified outside of the debugger. \n Do you want to reload it? " , mScripts [ i ] - > GetFilename ( ) ) , " Quake 4 Script Debugger " , MB_YESNO | MB_ICONQUESTION ) )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
mScripts [ i ] - > Reload ( ) ;
2011-12-06 18:20:15 +00:00
// Update the script if it was the active one
2011-11-22 21:28:15 +00:00
if ( mActiveScript = = i )
{
mLastActiveScript = - 1 ;
UpdateScript ( ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// Loop through the breakpoints and see if any of them have
// moved to invalid lines within the script. If so then just remove
// them.
for ( int b = mClient - > GetBreakpointCount ( ) - 1 ; b > = 0 ; b - - )
{
rvDebuggerBreakpoint * bp = mClient - > GetBreakpoint ( b ) ;
assert ( bp ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( ! idStr : : Icmp ( bp - > GetFilename ( ) , mScripts [ i ] - > GetFilename ( ) ) )
{
if ( ! mScripts [ i ] - > IsLineCode ( bp - > GetLineNumber ( ) ) )
{
mClient - > RemoveBreakpoint ( bp - > GetID ( ) ) ;
2011-12-06 18:20:15 +00:00
}
}
2011-11-22 21:28:15 +00:00
}
}
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
return 1 ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : EnableWindows
Enables and disables all windows with a enable state dependent on the current
connected and paused state of the debugger .
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : EnableWindows ( bool state )
{
EnableWindow ( mWndCallstack , state ) ;
EnableWindow ( mWndThreads , state ) ;
EnableWindow ( mWndWatch , state ) ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : AddWatch
2011-12-06 18:20:15 +00:00
Add a variable to the watch window . If update is set to true then also query the
2011-11-22 21:28:15 +00:00
debugger client for the value
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : AddWatch ( const char * varname , bool update )
{
rvDebuggerWatch * watch ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
watch = new rvDebuggerWatch ;
watch - > mVariable = varname ;
watch - > mModified = false ;
watch - > mValue = " ??? " ;
mWatches . Append ( watch ) ;
// Add the variable to the watch control
LVITEM item ;
item . mask = LVIF_PARAM ;
item . iItem = ListView_GetItemCount ( mWndWatch ) - 1 ;
item . iSubItem = 0 ;
item . lParam = ( LPARAM ) watch ;
2011-12-06 18:20:15 +00:00
ListView_InsertItem ( mWndWatch , & item ) ;
2011-11-22 21:28:15 +00:00
// If update is set then request the value from the debugger client
if ( update )
{
mClient - > InspectVariable ( varname , mCurrentStackDepth ) ;
}
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : InitRecentFiles
Finds the file menu and the location within it where the MRU should
be added .
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : InitRecentFiles ( void )
{
int i ;
int count ;
mRecentFileMenu = GetSubMenu ( GetMenu ( mWnd ) , 0 ) ;
count = GetMenuItemCount ( mRecentFileMenu ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
for ( i = 0 ; i < count ; i + + )
{
if ( GetMenuItemID ( mRecentFileMenu , i ) = = ID_DBG_FILE_MRU )
{
mRecentFileInsertPos = i ;
DeleteMenu ( mRecentFileMenu , mRecentFileInsertPos , MF_BYPOSITION ) ;
return true ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : UpdateRecentFiles
Updates the mru in the menu
= = = = = = = = = = = = = = = =
*/
void rvDebuggerWindow : : UpdateRecentFiles ( void )
{
int i ;
int j ;
// Make sure everything is initialized
2011-12-06 18:20:15 +00:00
if ( ! mRecentFileMenu )
{
2011-11-22 21:28:15 +00:00
InitRecentFiles ( ) ;
}
// Delete all the old recent files from the menu's
for ( i = 0 ; i < rvRegistryOptions : : MAX_MRU_SIZE ; i + + )
{
DeleteMenu ( mRecentFileMenu , ID_DBG_FILE_MRU1 + i , MF_BYCOMMAND ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
// Make sure there is a separator after the recent files
if ( gDebuggerApp . GetOptions ( ) . GetRecentFileCount ( ) )
{
MENUITEMINFO info ;
ZeroMemory ( & info , sizeof ( info ) ) ;
info . cbSize = sizeof ( info ) ;
info . fMask = MIIM_FTYPE ;
GetMenuItemInfo ( mRecentFileMenu , mRecentFileInsertPos + 1 , TRUE , & info ) ;
if ( ! ( info . fType & MFT_SEPARATOR ) )
{
InsertMenu ( mRecentFileMenu , mRecentFileInsertPos , MF_BYPOSITION | MF_SEPARATOR | MF_ENABLED , 0 , NULL ) ;
}
}
// Add the recent files to the menu now
for ( j = 0 , i = gDebuggerApp . GetOptions ( ) . GetRecentFileCount ( ) - 1 ; i > = 0 ; i - - , j + + )
{
UINT id = ID_DBG_FILE_MRU1 + j ;
idStr str = va ( " &%d " , j + 1 ) ;
str . Append ( gDebuggerApp . GetOptions ( ) . GetRecentFile ( i ) ) ;
InsertMenu ( mRecentFileMenu , mRecentFileInsertPos + j + 1 , MF_BYPOSITION | MF_STRING | MF_ENABLED , id , str ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : GetSelectedText
2011-12-06 18:20:15 +00:00
Function to retrieve the text that is currently selected in the
2011-11-22 21:28:15 +00:00
script control
= = = = = = = = = = = = = = = =
*/
int rvDebuggerWindow : : GetSelectedText ( idStr & text )
{
TEXTRANGE range ;
int start ;
int end ;
char * temp ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
text . Empty ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( mScripts . Num ( ) )
{
SendMessage ( mWndScript , EM_GETSEL , ( WPARAM ) & start , ( LPARAM ) & end ) ;
if ( start = = end )
{
end = SendMessage ( mWndScript , EM_FINDWORDBREAK , WB_RIGHT , start ) ;
start = SendMessage ( mWndScript , EM_FINDWORDBREAK , WB_LEFT , start ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
temp = new char [ end - start + 10 ] ;
range . chrg . cpMin = start ;
range . chrg . cpMax = end ;
range . lpstrText = temp ;
SendMessage ( mWndScript , EM_GETTEXTRANGE , 0 , ( LPARAM ) & range ) ;
text = temp ;
delete [ ] temp ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return start ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return - 1 ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : FindNext
Finds the next match of the find text in the active script . The next is
always relative to the current selection . If the text parameter is NULL
2011-12-06 18:20:15 +00:00
then the last text used will be searched for .
2011-11-22 21:28:15 +00:00
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : FindNext ( const char * text )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
int start ;
FINDTEXT ft ;
if ( text )
{
mFind = text ;
}
if ( ! mFind . Length ( ) )
{
return false ;
}
SendMessage ( mWndScript , EM_GETSEL , ( WPARAM ) & start , ( LPARAM ) 0 ) ;
if ( start < 0 )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
start = 0 ;
}
ft . chrg . cpMin = start + 1 ;
ft . chrg . cpMax = - 1 ;
ft . lpstrText = mFind . c_str ( ) ;
start = SendMessage ( mWndScript , EM_FINDTEXT , FR_DOWN , ( LPARAM ) & ft ) ;
if ( start < 0 )
{
ft . chrg . cpMin = 0 ;
ft . chrg . cpMax = - 1 ;
ft . lpstrText = mFind . c_str ( ) ;
start = SendMessage ( mWndScript , EM_FINDTEXT , FR_DOWN , ( LPARAM ) & ft ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( start < 0 )
{
return false ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SendMessage ( mWndScript , EM_SETSEL , start , start + mFind . Length ( ) ) ;
SendMessage ( mWndScript , EM_SCROLLCARET , 0 , 0 ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : FindPrev
Finds the previous match of the find text in the active script . The previous is
always relative to the current selection . If the text parameter is NULL
2011-12-06 18:20:15 +00:00
then the last text used will be searched for .
2011-11-22 21:28:15 +00:00
= = = = = = = = = = = = = = = =
*/
bool rvDebuggerWindow : : FindPrev ( const char * text )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
int start ;
FINDTEXT ft ;
if ( text )
{
mFind = text ;
}
if ( ! mFind . Length ( ) )
{
return false ;
}
SendMessage ( mWndScript , EM_GETSEL , ( WPARAM ) & start , ( LPARAM ) 0 ) ;
if ( start < 0 )
2011-12-06 18:20:15 +00:00
{
2011-11-22 21:28:15 +00:00
start = 0 ;
}
ft . chrg . cpMin = start ;
ft . chrg . cpMax = - 1 ;
ft . lpstrText = mFind . c_str ( ) ;
start = SendMessage ( mWndScript , EM_FINDTEXT , 0 , ( LPARAM ) & ft ) ;
if ( start < 0 )
{
GETTEXTLENGTHEX gtl ;
gtl . flags = GTL_DEFAULT ;
gtl . codepage = CP_ACP ;
ft . chrg . cpMin = SendMessage ( mWndScript , EM_GETTEXTLENGTHEX , ( WPARAM ) & gtl , 0 ) ;
ft . chrg . cpMax = 0 ;
ft . lpstrText = mFind . c_str ( ) ;
start = SendMessage ( mWndScript , EM_FINDTEXT , 0 , ( LPARAM ) & ft ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( start < 0 )
{
return false ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
SendMessage ( mWndScript , EM_SETSEL , start , start + mFind . Length ( ) ) ;
SendMessage ( mWndScript , EM_SCROLLCARET , 0 , 0 ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
rvDebuggerWindow : : HandleDrawItem
Handled the WM_DRAWITEM message . The watch window is custom drawn so a grid can be displayed .
= = = = = = = = = = = = = = = =
*/
int rvDebuggerWindow : : HandleDrawItem ( WPARAM wparam , LPARAM lparam )
{
DRAWITEMSTRUCT * dis ;
LVCOLUMN col ;
int index ;
idStr widths ;
RECT rect ;
rvDebuggerWatch * watch ;
bool selected ;
2011-12-06 18:20:15 +00:00
dis = ( DRAWITEMSTRUCT * ) lparam ;
2011-11-22 21:28:15 +00:00
watch = ( rvDebuggerWatch * ) dis - > itemData ;
2011-12-06 18:20:15 +00:00
col . mask = LVCF_WIDTH ;
2011-11-22 21:28:15 +00:00
rect = dis - > rcItem ;
rect . left = rect . left - 1 ;
rect . right = rect . left ;
rect . bottom + + ;
selected = ( ( dis - > itemState & ODS_SELECTED ) & & GetFocus ( ) = = mWndWatch ) ;
// Set the colors based on the selected state and draw the item background
if ( selected )
{
FillRect ( dis - > hDC , & dis - > rcItem , GetSysColorBrush ( COLOR_HIGHLIGHT ) ) ;
}
else
{
2011-12-06 18:20:15 +00:00
FillRect ( dis - > hDC , & dis - > rcItem , GetSysColorBrush ( IsWindowEnabled ( mWndWatch ) ? COLOR_WINDOW : COLOR_3DFACE ) ) ;
2011-11-22 21:28:15 +00:00
}
2011-12-06 18:20:15 +00:00
// Run through the columns and draw each with a frame around it and the text
2011-11-22 21:28:15 +00:00
// vertically centered in it
for ( index = 0 ; ListView_GetColumn ( mWndWatch , index , & col ) ; index + + )
{
rect . right = rect . left + col . cx ;
2011-12-06 18:20:15 +00:00
FrameRect ( dis - > hDC , & rect , GetSysColorBrush ( COLOR_3DFACE ) ) ;
2011-11-22 21:28:15 +00:00
// Draw info on the watch if available
if ( watch )
{
RECT textrect ;
textrect = rect ;
textrect . left + = 5 ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
switch ( index )
{
case 0 :
SetTextColor ( dis - > hDC , GetSysColor ( selected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT ) ) ;
2011-12-06 18:20:15 +00:00
DrawText ( dis - > hDC , watch - > mVariable , - 1 , & textrect , DT_LEFT | DT_VCENTER ) ;
2011-11-22 21:28:15 +00:00
break ;
case 1 :
if ( watch & & watch - > mModified & & ( IsWindowEnabled ( mWndWatch ) ) )
{
SetTextColor ( dis - > hDC , RGB ( 255 , 50 , 50 ) ) ;
}
else
{
SetTextColor ( dis - > hDC , GetSysColor ( selected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT ) ) ;
}
2011-12-06 18:20:15 +00:00
DrawText ( dis - > hDC , watch - > mValue , - 1 , & textrect , DT_LEFT | DT_VCENTER ) ;
2011-11-22 21:28:15 +00:00
break ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
rect . left = rect . right - 1 ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
return 0 ;
}