Some enhancements by Ian Anderson, but modified as they were implemented on an older Harbour version source code.
Some improvements. Warning: Still a work in progress
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* Harbour Project source code:
|
||||
* The Debugger
|
||||
*
|
||||
* Copyright 1999 Antonio Linares <alinares@fivetech.com>
|
||||
* Copyright 1999 Antonio Linares <alinares@fivetechsoft.com>
|
||||
* www - http://www.harbour-project.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -60,7 +60,7 @@
|
||||
redirection, and is also slower. [vszakats] */
|
||||
|
||||
/* Information structure hold by DATA aCallStack
|
||||
aCallStack = { { cFunctionName, aLocalVariables, nStartLine }, ... } */
|
||||
aCallStack = { { cFunctionName, aLocalVariables, nStartLine , cPrgName }, ... } */
|
||||
|
||||
#pragma -es0
|
||||
|
||||
@@ -84,6 +84,7 @@ procedure AltD( nAction )
|
||||
case nAction == nil
|
||||
if SET( _SET_DEBUG )
|
||||
s_lExit := .f.
|
||||
s_oDebugger:lGo := .F.
|
||||
__dbgEntry( ProcLine( 1 ) )
|
||||
endif
|
||||
|
||||
@@ -111,16 +112,8 @@ procedure __dbgEntry( uParam1, uParam2, uParam3 ) // debugger entry point
|
||||
s_oDebugger := TDebugger():New()
|
||||
s_oDebugger:Activate( cModuleName )
|
||||
else
|
||||
if ! s_oDebugger:lTrace
|
||||
s_oDebugger:ShowCode( cModuleName )
|
||||
else
|
||||
ASize( s_oDebugger:aCallStack, Len( s_oDebugger:aCallStack ) + 1 )
|
||||
AIns( s_oDebugger:aCallStack, 1 )
|
||||
// same as aCallStack[ 1 ] = { cProcName, {} }
|
||||
s_oDebugger:aCallStack[ 1 ] = { SubStr( cModuleName,;
|
||||
RAt( ":", cModuleName ) + 1 ), {}, nil }
|
||||
// nil means no line number stored yet
|
||||
endif
|
||||
// add a call to the stack but don't try to show the code yet
|
||||
s_oDebugger:StackProc( cModuleName )
|
||||
s_oDebugger:LoadVars()
|
||||
endif
|
||||
endif
|
||||
@@ -166,7 +159,7 @@ procedure __dbgEntry( uParam1, uParam2, uParam3 ) // debugger entry point
|
||||
endif
|
||||
endif
|
||||
else // local variable
|
||||
cLocalName := uParam2
|
||||
cLocalName := IIF(valtype(uParam2)=='C',uParam2,'NIL')
|
||||
nLocalIndex := uParam1
|
||||
if s_oDebugger:lShowLocals
|
||||
if ( nAt := AScan( s_oDebugger:aVars,; // Is there another var with this name ?
|
||||
@@ -176,7 +169,9 @@ procedure __dbgEntry( uParam1, uParam2, uParam3 ) // debugger entry point
|
||||
AAdd( s_oDebugger:aVars, { cLocalName, nLocalIndex, "Local", cProcName } )
|
||||
endif
|
||||
endif
|
||||
AAdd( s_oDebugger:aCallStack[ 1 ][ 2 ], { cLocalName, nLocalIndex, "Local", cProcName } )
|
||||
IF Len( s_oDebugger:aCallStack )>0 .AND. valtype( s_oDebugger:aCallStack[ 1, 2 ])=='A'
|
||||
AAdd( s_oDebugger:aCallStack[ 1 ][ 2 ], { cLocalName, nLocalIndex, "Local", ProcName( 1 ) } )
|
||||
endif
|
||||
endif
|
||||
if s_oDebugger:oBrwVars != nil
|
||||
s_oDebugger:oBrwVars:RefreshAll()
|
||||
@@ -192,15 +187,15 @@ procedure __dbgEntry( uParam1, uParam2, uParam3 ) // debugger entry point
|
||||
endif
|
||||
endif
|
||||
|
||||
s_oDebugger:aCallStack [1] [3] := uParam1 // set the current line number on the CallStack
|
||||
if s_oDebugger:lGo
|
||||
s_oDebugger:lGo := ! s_oDebugger:IsBreakPoint( uParam1 )
|
||||
s_oDebugger:lGo := ! s_oDebugger:IsBreakPoint( uParam1, s_oDebugger:aCallStack [1] [4] )
|
||||
endif
|
||||
|
||||
if ! s_oDebugger:lGo .or. InvokeDebug() .or. ;
|
||||
ProcName( 1 ) == "ALTD" // debugger invoked from AltD( 1 )
|
||||
if !s_oDebugger:lGo .or. InvokeDebug()
|
||||
s_oDebugger:lGo := .F.
|
||||
s_oDebugger:SaveAppStatus()
|
||||
s_oDebugger:GoToLine( uParam1 )
|
||||
// new function ShowCodeLine( nline, cFilename)
|
||||
s_oDebugger:ShowCodeLine( uParam1, s_oDebugger:aCallStack [1] [4])
|
||||
s_oDebugger:HandleEvent()
|
||||
endif
|
||||
endif
|
||||
@@ -247,6 +242,7 @@ CLASS TDebugger
|
||||
|
||||
METHOD BarDisplay()
|
||||
METHOD BuildCommandWindow()
|
||||
METHOD BuildBrowseStack()
|
||||
|
||||
METHOD CallStackProcessKey( nKey )
|
||||
METHOD ClrModal() INLINE iif( ::lMonoDisplay, "N/W, W+/W, W/N, W+/N",;
|
||||
@@ -268,7 +264,7 @@ CLASS TDebugger
|
||||
METHOD HideVars()
|
||||
METHOD InputBox( cMsg, uValue, bValid, lEditable )
|
||||
METHOD Inspect( uValue, cValueName )
|
||||
METHOD IsBreakPoint( nLine )
|
||||
METHOD IsBreakPoint( nLine, cPrgName)
|
||||
METHOD LoadSettings()
|
||||
METHOD LoadVars()
|
||||
|
||||
@@ -278,10 +274,7 @@ CLASS TDebugger
|
||||
METHOD NextWindow()
|
||||
METHOD Open()
|
||||
METHOD OSShell()
|
||||
|
||||
METHOD PathForFiles() INLINE ;
|
||||
::cPathForFiles := ::InputBox( "Search path for source files:",;
|
||||
::cPathForFiles )
|
||||
METHOD PathForFiles()
|
||||
|
||||
METHOD PrevWindow()
|
||||
METHOD Private()
|
||||
@@ -293,15 +286,15 @@ CLASS TDebugger
|
||||
METHOD Show()
|
||||
METHOD ShowAppScreen()
|
||||
METHOD ShowCallStack()
|
||||
METHOD ShowCode( cModuleName )
|
||||
METHOD ShowCodeLine( nLine, cPrgName )
|
||||
METHOD StackProc(cModuleName)
|
||||
METHOD ShowHelp( nTopic )
|
||||
METHOD ShowVars()
|
||||
|
||||
METHOD Sort() INLINE ASort( ::aVars,,, { | x, y | x[ 1 ] < y[ 1 ] } ),;
|
||||
METHOD RedisplayBreakpoints()
|
||||
METHOD Sort() INLINE ASort( ::aVars,,, {|x,y| x[1] < y[1] } ),;
|
||||
::lSortVars := .t.,;
|
||||
If( ::oBrwVars != nil, ::oBrwVars:RefreshAll(), nil ),;
|
||||
If( ::oWndVars != nil .and. ::oWndVars:lVisible,;
|
||||
If( ! ::lGo, ::oBrwVars:ForceStable(),),)
|
||||
iif( ::oBrwVars != nil, ::oBrwVars:RefreshAll(), nil ),;
|
||||
iif( ::oWndVars != nil .and. ::oWndVars:lVisible, iif(!::lGo,::oBrwVars:ForceStable(),),)
|
||||
|
||||
METHOD Speed() INLINE ;
|
||||
::nSpeed := ::InputBox( "Step delay (in tenths of a second)",;
|
||||
@@ -352,7 +345,11 @@ METHOD New() CLASS TDebugger
|
||||
::aVars := {}
|
||||
::lCaseSensitive := .f.
|
||||
::cSearchString := ""
|
||||
::cPathForFiles := ""
|
||||
|
||||
// default the search path for files to the current directory
|
||||
// that way if the source is in the same directory it will still be found even if the application
|
||||
// changes the current directory with the SET DEFAULT command
|
||||
::cPathForFiles := CURDRIVE() + ':\' + CURDIR() + '\'
|
||||
::nTabWidth := 4
|
||||
::nSpeed := 0
|
||||
::lShowCallStack := .f.
|
||||
@@ -377,23 +374,27 @@ METHOD New() CLASS TDebugger
|
||||
SetPos( ::oWndCode:Cargo[1],::oWndCode:Cargo[2] ) }
|
||||
::oWndCode:bLostFocus := { || ::oWndCode:Cargo[1] := Row(), ::oWndCode:Cargo[2] := Col(), ;
|
||||
SetCursor( SC_NONE ) }
|
||||
/*
|
||||
::oWndCode:bPainted := { || ::oBrwText:SetColor( __DbgColors()[ 2 ] + "," + ;
|
||||
__DbgColors()[ 5 ] + "," + __DbgColors()[ 3 ] + "," + ;
|
||||
__DbgColors()[ 6 ] ),;
|
||||
iif( ::oBrwText != nil, ::oBrwText:RefreshWindow(), nil ) }
|
||||
*/
|
||||
|
||||
AAdd( ::aWindows, ::oWndCode )
|
||||
|
||||
::BuildCommandWindow()
|
||||
::BuildBrowseStack()
|
||||
|
||||
return Self
|
||||
|
||||
METHOD PathForFiles() CLASS TDebugger
|
||||
|
||||
::cPathForFiles := ::InputBox( "Search path for source files:", ::cPathForFiles )
|
||||
IF RIGHT(::cPathForFiles,1)<>'\'
|
||||
::cPathForFiles:=::cPathForFiles+'\'
|
||||
ENDIF
|
||||
return Self
|
||||
|
||||
METHOD Activate( cModuleName ) CLASS TDebugger
|
||||
|
||||
::Show()
|
||||
::ShowCode( cModuleName )
|
||||
::StackProc(cModuleName)
|
||||
::ShowCodeLine( 1, cModuleName )
|
||||
if ::lShowCallStack
|
||||
::ShowCallStack()
|
||||
endif
|
||||
@@ -468,6 +469,26 @@ METHOD BuildCommandWindow() CLASS TDebugger
|
||||
|
||||
return nil
|
||||
|
||||
METHOD BuildBrowseStack() CLASS TDebugger
|
||||
|
||||
if ::oBrwStack == nil
|
||||
::oBrwStack := TBrowseNew( 2, MaxCol() - 14, MaxRow() - 7, MaxCol() - 1 )
|
||||
::oBrwStack:ColorSpec := ::aColors[ 3 ] + "," + ::aColors[ 4 ] + "," + ::aColors[ 5 ]
|
||||
::oBrwStack:GoTopBlock := { || ::oBrwStack:Cargo := 1 }
|
||||
::oBrwStack:GoBottomBlock := { || ::oBrwStack:Cargo := Len( ::aCallStack ) }
|
||||
::oBrwStack:SkipBlock = { | nSkip, nOld | nOld := ::oBrwStack:Cargo,;
|
||||
::oBrwStack:Cargo += nSkip,;
|
||||
::oBrwStack:Cargo := Min( Max( ::oBrwStack:Cargo, 1 ),;
|
||||
Len( ::aCallStack ) ), ::oBrwStack:Cargo - nOld }
|
||||
|
||||
::oBrwStack:Cargo := 1 // Actual highligthed row
|
||||
|
||||
::oBrwStack:AddColumn( TBColumnNew( "", { || If( Len( ::aCallStack ) > 0,;
|
||||
PadC( ::aCallStack[ ::oBrwStack:Cargo ][ 1 ], 14 ), Space( 14 ) ) } ) )
|
||||
endif
|
||||
|
||||
return nil
|
||||
|
||||
METHOD CallStackProcessKey( nKey ) CLASS TDebugger
|
||||
|
||||
local n, nSkip, lUpdate := .f.
|
||||
@@ -530,9 +551,9 @@ METHOD CallStackProcessKey( nKey ) CLASS TDebugger
|
||||
endcase
|
||||
|
||||
if lUpdate
|
||||
// source line for a function
|
||||
// jump to source line for a function
|
||||
if ::aCallStack[ ::oBrwStack:Cargo ][ 3 ] != nil
|
||||
::GotoLine( ::aCallStack[ ::oBrwStack:Cargo ][ 3 ] )
|
||||
::ShowCodeLine( ::aCallStack[ ::oBrwStack:Cargo ][ 3 ], ::aCallStack[ ::oBrwStack:Cargo ][ 4 ] )
|
||||
else
|
||||
::GotoLine( 1 )
|
||||
endif
|
||||
@@ -635,7 +656,8 @@ return nil
|
||||
|
||||
METHOD CommandWindowProcessKey( nKey ) CLASS TDebugger
|
||||
|
||||
local cCommand, cResult
|
||||
local cCommand, cResult, oE
|
||||
local bLastHandler
|
||||
local lDisplay
|
||||
|
||||
do case
|
||||
@@ -739,7 +761,7 @@ METHOD EditColor( nColor, oBrwColors ) CLASS TDebugger
|
||||
local lPrevScore := Set( _SET_SCOREBOARD, .f. )
|
||||
local lPrevExit := Set( _SET_EXIT, .t. )
|
||||
local cColor := PadR( '"' + ::aColors[ nColor ] + '"',;
|
||||
oBrwColors:aColumns[ 2 ]:Width )
|
||||
oBrwColors:aColumns[ 2,1 ]:Width )
|
||||
|
||||
oBrwColors:RefreshCurrent()
|
||||
oBrwColors:ForceStable()
|
||||
@@ -891,7 +913,7 @@ return nil
|
||||
|
||||
METHOD HandleEvent() CLASS TDebugger
|
||||
|
||||
local nPopup, oWnd, nCursor
|
||||
local nPopup, oWnd
|
||||
local nKey, nMRow, nMCol, n
|
||||
|
||||
if ::lAnimate
|
||||
@@ -919,7 +941,7 @@ METHOD HandleEvent() CLASS TDebugger
|
||||
case ::oPullDown:IsOpen()
|
||||
::oPullDown:ProcessKey( nKey )
|
||||
if ::oPullDown:nOpenPopup == 0 // Closed
|
||||
Eval( ::aWindows[ ::nCurrentWindow ]:bGotFocus )
|
||||
::aWindows[ ::nCurrentWindow ]:SetFocus( .t. )
|
||||
endif
|
||||
|
||||
case nKey == K_LDBLCLK
|
||||
@@ -938,7 +960,7 @@ METHOD HandleEvent() CLASS TDebugger
|
||||
::aWindows[ n ]:SetFocus( .t. )
|
||||
endif
|
||||
::aWindows[ n ]:LDblClick( nMRow, nMCol )
|
||||
n := Len( ::aWindows ) + 1
|
||||
exit
|
||||
endif
|
||||
next
|
||||
endif
|
||||
@@ -968,7 +990,7 @@ METHOD HandleEvent() CLASS TDebugger
|
||||
::aWindows[ n ]:SetFocus( .t. )
|
||||
endif
|
||||
::aWindows[ n ]:LButtonDown( nMRow, nMCol )
|
||||
n := Len( ::aWindows ) + 1
|
||||
exit
|
||||
endif
|
||||
next
|
||||
endif
|
||||
@@ -994,12 +1016,22 @@ METHOD HandleEvent() CLASS TDebugger
|
||||
::ShowAppScreen()
|
||||
|
||||
case nKey == K_F5
|
||||
// we are starting to run again so reset to the deepest call if
|
||||
// displaying stack
|
||||
if ! ::oBrwStack == nil
|
||||
::oBrwStack:GoTop()
|
||||
endif
|
||||
::Go()
|
||||
|
||||
case nKey == K_F6
|
||||
::ShowWorkAreas()
|
||||
|
||||
case nKey == K_F8 .or. nKey == 255
|
||||
// we are starting to run again so reset to the deepest call if
|
||||
// displaying stack
|
||||
if ! ::oBrwStack == nil
|
||||
::oBrwStack:GoTop()
|
||||
endif
|
||||
::Step()
|
||||
|
||||
case nKey == K_F9
|
||||
@@ -1020,7 +1052,7 @@ METHOD HandleEvent() CLASS TDebugger
|
||||
otherwise
|
||||
if ( nPopup := ::oPullDown:GetHotKeyPos( __dbgAltToKey( nKey ) ) ) != 0
|
||||
if ::oPullDown:nOpenPopup != nPopup
|
||||
nCursor = SetCursor( SC_NONE )
|
||||
SetCursor( SC_NONE )
|
||||
::oPullDown:ShowPopup( nPopup )
|
||||
endif
|
||||
endif
|
||||
@@ -1176,19 +1208,9 @@ METHOD ShowCallStack() CLASS TDebugger
|
||||
AAdd( ::aWindows, ::oWndStack )
|
||||
::nCurrentWindow = Len( ::aWindows )
|
||||
|
||||
::oBrwStack := TBrowseNew( 2, MaxCol() - 14, MaxRow() - 7, MaxCol() - 1 )
|
||||
::oBrwStack:ColorSpec := ::aColors[ 3 ] + "," + ::aColors[ 4 ] + "," + ::aColors[ 5 ]
|
||||
::oBrwStack:GoTopBlock := { || ::oBrwStack:Cargo := 1 }
|
||||
::oBrwStack:GoBottomBlock := { || ::oBrwStack:Cargo := Len( ::aCallStack ) }
|
||||
::oBrwStack:SkipBlock = { | nSkip, nOld | nOld := ::oBrwStack:Cargo,;
|
||||
::oBrwStack:Cargo += nSkip,;
|
||||
::oBrwStack:Cargo := Min( Max( ::oBrwStack:Cargo, 1 ),;
|
||||
Len( ::aCallStack ) ), ::oBrwStack:Cargo - nOld }
|
||||
|
||||
::oBrwStack:Cargo := 1 // Actual highligthed row
|
||||
|
||||
::oBrwStack:AddColumn( oCol := TBColumnNew( "",;
|
||||
{ || PadC( ::aCallStack[ ::oBrwStack:Cargo ][ 1 ], 14 ) } ) )
|
||||
if ::oBrwStack == nil
|
||||
::BuildBrowseStack()
|
||||
endif
|
||||
|
||||
::oWndStack:bPainted := { || ::oBrwStack:ColorSpec := __DbgColors()[ 2 ] + "," + ;
|
||||
__DbgColors()[ 5 ] + "," + __DbgColors()[ 4 ],;
|
||||
@@ -1334,6 +1356,7 @@ METHOD ShowVars() CLASS TDebugger
|
||||
|
||||
if ::oWndVars == nil
|
||||
|
||||
::LoadVars()
|
||||
::oWndVars := TDbWindow():New( 1, 0, Min( 7, Len( ::aVars ) + 2 ),;
|
||||
MaxCol() - iif( ::oWndStack != nil, ::oWndStack:nWidth(), 0 ),;
|
||||
"Monitor:" + iif( ::lShowLocals, " Local", "" ) + ;
|
||||
@@ -1349,82 +1372,85 @@ METHOD ShowVars() CLASS TDebugger
|
||||
AAdd( ::aWindows, ::oWndVars )
|
||||
::oWndVars:bLButtonDown := { | nMRow, nMCol | ::WndVarsLButtonDown( nMRow, nMCol ) }
|
||||
::oWndVars:bLDblClick := { | nMRow, nMCol | ::EditVar( ::oBrwVars:Cargo[ 1 ] ) }
|
||||
|
||||
::oBrwVars := TBrowseNew( 2, 1, ::oWndVars:nBottom - 1, MaxCol() - iif( ::oWndStack != nil,;
|
||||
::oWndStack:nWidth(), 0 ) - 1 )
|
||||
|
||||
::oBrwVars:Cargo :={ 1,{}} // Actual highligthed row
|
||||
::oBrwVars:ColorSpec := ::aColors[ 2 ] + "," + ::aColors[ 5 ] + "," + ::aColors[ 3 ]
|
||||
::oBrwVars:GOTOPBLOCK := { || ::oBrwVars:cargo[ 1 ] := Min( 1, Len( ::aVars ) ) }
|
||||
::oBrwVars:GoBottomBlock := { || ::oBrwVars:cargo[ 1 ] := Len( ::aVars ) }
|
||||
::oBrwVars:SkipBlock = { | nSkip, nOld | nOld := ::oBrwVars:Cargo[ 1 ],;
|
||||
::oBrwVars:Cargo[ 1 ] += nSkip,;
|
||||
::oBrwVars:Cargo[ 1 ] := Min( Max( ::oBrwVars:Cargo[ 1 ], 1 ),;
|
||||
Len( ::aVars ) ),;
|
||||
If( Len( ::aVars ) > 0, ::oBrwVars:Cargo[ 1 ] - nOld, 0 ) }
|
||||
|
||||
nWidth := ::oWndVars:nWidth() - 1
|
||||
::oBrwVars:AddColumn( oCol:=TBColumnNew( "", { || If( Len( ::aVars ) > 0, AllTrim( Str( ::oBrwVars:Cargo[1] -1 ) ) + ") " + ;
|
||||
PadR( GetVarInfo( ::aVars[ Max( ::oBrwVars:Cargo[1], 1 ) ] ),;
|
||||
::oWndVars:nWidth() - 5 ), "" ) } ) )
|
||||
AAdd(::oBrwVars:Cargo[2],::avars)
|
||||
oCol:DefColor:={1,2}
|
||||
if Len( ::aVars ) > 0
|
||||
::oBrwVars:ForceStable()
|
||||
endif
|
||||
|
||||
::oWndVars:bPainted := { || if(Len( ::aVars ) > 0, ( ::obrwVars:ForceStable(),RefreshVarsS(::oBrwVars) ),) }
|
||||
|
||||
::oWndVars:bKeyPressed := { | nKey | ( iif( nKey == K_DOWN ;
|
||||
, ::oBrwVars:Down(), nil ), iif( nKey == K_UP, ::oBrwVars:Up(), nil ) ;
|
||||
, iif( nKey == K_PGDN, ::oBrwVars:PageDown(), nil ) ;
|
||||
, iif( nKey == K_PGUP, ::oBrwVars:PageUp(), nil ) ;
|
||||
, iif( nKey == K_HOME, ::oBrwVars:GoTop(), nil ) ;
|
||||
, iif( nKey == K_END, ::oBrwVars:GoBottom(), nil ) ;
|
||||
, iif( nKey == K_ENTER, ::EditVar( ::oBrwVars:Cargo[1] ), nil ), ::oBrwVars:ForceStable() ) }
|
||||
|
||||
|
||||
else
|
||||
::LoadVars()
|
||||
|
||||
::oWndVars:cCaption := "Monitor:" + ;
|
||||
iif( ::lShowLocals, " Local", "" ) + ;
|
||||
iif( ::lShowStatics, " Static", "" ) + ;
|
||||
iif( ::lShowPrivates, " Private", "" ) + ;
|
||||
iif( ::lShowPublics, " Public", "" )
|
||||
endif
|
||||
|
||||
::LoadVars()
|
||||
|
||||
::oBrwVars := TBrowseNew( 2, 1, ::oWndVars:nBottom - 1, MaxCol() - iif( ::oWndStack != nil,;
|
||||
::oWndStack:nWidth(), 0 ) - 1 )
|
||||
::oBrwVars:Cargo :={ 1,{}} // Actual highligthed row
|
||||
::oBrwVars:ColorSpec := ::aColors[ 2 ] + "," + ::aColors[ 5 ] + "," + ::aColors[ 3 ]
|
||||
::oBrwVars:GOTOPBLOCK := { || ::oBrwVars:cargo[ 1 ] := Min( 1, Len( ::aVars ) ) }
|
||||
::oBrwVars:GoBottomBlock := { || ::oBrwVars:cargo[ 1 ] := Len( ::aVars ) }
|
||||
::oBrwVars:SkipBlock = { | nSkip, nOld | nOld := ::oBrwVars:Cargo[ 1 ],;
|
||||
::oBrwVars:Cargo[ 1 ] += nSkip,;
|
||||
::oBrwVars:Cargo[ 1 ] := Min( Max( ::oBrwVars:Cargo[ 1 ], 1 ),;
|
||||
Len( ::aVars ) ),;
|
||||
If( Len( ::aVars ) > 0, ::oBrwVars:Cargo[ 1 ] - nOld, 0 ) }
|
||||
|
||||
|
||||
::oWndVars:bKeyPressed := { | nKey | ( iif( nKey == K_DOWN ;
|
||||
, ::oBrwVars:Down(), nil ), iif( nKey == K_UP, ::oBrwVars:Up(), nil ) ;
|
||||
, iif( nKey == K_PGDN, ::oBrwVars:PageDown(), nil ) ;
|
||||
, iif( nKey == K_PGUP, ::oBrwVars:PageUp(), nil ) ;
|
||||
, iif( nKey == K_HOME, ::oBrwVars:GoTop(), nil ) ;
|
||||
, iif( nKey == K_END, ::oBrwVars:GoBottom(), nil ) ;
|
||||
, iif( nKey == K_ENTER, ::EditVar( ::oBrwVars:Cargo[1] ), nil ), ::oBrwVars:ForceStable() ) }
|
||||
|
||||
nWidth := ::oWndVars:nWidth() - 1
|
||||
::oBrwVars:AddColumn( oCol:=TBColumnNew( "", { || If( Len( ::aVars ) > 0, AllTrim( Str( ::oBrwVars:Cargo[1] -1 ) ) + ") " + ;
|
||||
PadR( GetVarInfo( ::aVars[ Max( ::oBrwVars:Cargo[1], 1 ) ] ),;
|
||||
::oWndVars:nWidth() - 5 ), "" ) } ) )
|
||||
|
||||
oCol:DefColor:={2,1}
|
||||
AAdd(::oBrwVars:Cargo[2],::aVars)
|
||||
// ::oBrwVars:ForceStable()
|
||||
|
||||
if Len( ::aVars ) == 0
|
||||
if ::oWndVars:nBottom - ::oWndVars:nTop > 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + 1
|
||||
if Len( ::aVars ) == 0
|
||||
if ::oWndVars:nBottom - ::oWndVars:nTop > 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + 1
|
||||
lRepaint := .t.
|
||||
endif
|
||||
endif
|
||||
if Len( ::aVars ) > ::oWndVars:nBottom - ::oWndVars:nTop - 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + Min( Len( ::aVars ) + 1, 7 )
|
||||
::oBrwVars:nBottom := ::oWndVars:nBottom - 1
|
||||
::oBrwVars:Configure()
|
||||
lRepaint := .t.
|
||||
endif
|
||||
endif
|
||||
if Len( ::aVars ) > ::oWndVars:nBottom - ::oWndVars:nTop - 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + Min( Len( ::aVars ) + 1, 7 )
|
||||
::oBrwVars:nBottom := ::oWndVars:nBottom - 1
|
||||
::oBrwVars:Configure()
|
||||
lRepaint := .t.
|
||||
endif
|
||||
if Len( ::aVars ) < ::oWndVars:nBottom - ::oWndVars:nTop - 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + Len( ::aVars ) + 1
|
||||
::oBrwVars:nBottom := ::oWndVars:nBottom - 1
|
||||
::oBrwVars:Configure()
|
||||
lRepaint := .t.
|
||||
endif
|
||||
if ! ::oWndVars:lVisible
|
||||
::oWndCode:nTop := ::oWndVars:nBottom + 1
|
||||
::oBrwText:Resize( ::oWndVars:nBottom + 2 )
|
||||
::oWndVars:Show()
|
||||
else
|
||||
if lRepaint
|
||||
::oWndCode:nTop := ::oWndVars:nBottom + 1
|
||||
::oBrwText:Resize( ::oWndCode:nTop + 1 )
|
||||
::oWndCode:Refresh()
|
||||
::oWndVars:Refresh()
|
||||
if Len( ::aVars ) < ::oWndVars:nBottom - ::oWndVars:nTop - 1
|
||||
::oWndVars:nBottom := ::oWndVars:nTop + Len( ::aVars ) + 1
|
||||
::oBrwVars:nBottom := ::oWndVars:nBottom - 1
|
||||
::oBrwVars:Configure()
|
||||
lRepaint := .t.
|
||||
endif
|
||||
if ! ::oWndVars:lVisible
|
||||
::oWndCode:nTop := ::oWndVars:nBottom + 1
|
||||
::oBrwText:Resize( ::oWndVars:nBottom + 2 )
|
||||
::oWndVars:Show()
|
||||
else
|
||||
if lRepaint
|
||||
::oWndCode:nTop := ::oWndVars:nBottom + 1
|
||||
::oBrwText:Resize( ::oWndCode:nTop + 1 )
|
||||
::oWndCode:Refresh()
|
||||
::oWndVars:Refresh()
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if Len( ::aVars ) > 0
|
||||
::oBrwVars:RefreshAll()
|
||||
::oBrwVars:ForceStable()
|
||||
if Len( ::aVars ) > 0
|
||||
::oBrwVars:RefreshAll()
|
||||
::oBrwVars:ForceStable()
|
||||
endif
|
||||
endif
|
||||
|
||||
return nil
|
||||
@@ -1457,46 +1483,75 @@ return ""
|
||||
static function CompareLine( Self )
|
||||
|
||||
return { | a | a[ 1 ] == Self:oBrwText:nRow } // it was nLine
|
||||
|
||||
METHOD ShowCode( cModuleName ) CLASS TDebugger
|
||||
|
||||
METHOD StackProc(cModuleName) CLASS TDebugger
|
||||
// always treat filename as lower case - we need it consistent for comparisons
|
||||
local cFunction := SubStr( cModuleName, RAt( ":", cModuleName ) + 1 )
|
||||
local cPrgName := SubStr( cModuleName, 1, RAt( ":", cModuleName ) - 1 )
|
||||
local cPrgName := lower(SubStr( cModuleName, 1, RAt( ":", cModuleName ) - 1 ))
|
||||
|
||||
ASize( ::aCallStack, Len( ::aCallStack ) + 1 )
|
||||
AIns( ::aCallStack, 1 )
|
||||
// nil means that no line number is stored yet
|
||||
::aCallStack[ 1 ] := { cFunction, {}, nil } // function name and locals array
|
||||
|
||||
if !::lGo
|
||||
// nil means that no line number is stored yet
|
||||
::aCallStack[1]:= { cFunction, {} , nil, cPrgName } // function name and locals array
|
||||
// and the function and program name
|
||||
return nil
|
||||
|
||||
METHOD ShowCodeLine( nLine, cPrgName ) CLASS TDebugger
|
||||
// we only update the stack window and up a new browse
|
||||
// to view the code if we have just broken execution
|
||||
if !::lGo .AND. !::lTrace
|
||||
if ::oWndStack != nil
|
||||
::oBrwStack:RefreshAll()
|
||||
endif
|
||||
|
||||
if cPrgName != ::cPrgName
|
||||
::cPrgName := cPrgName
|
||||
if ! File( cPrgName ) .and. ! Empty( ::cPathForFiles )
|
||||
if File( ::cPathForFiles + cPrgName )
|
||||
cPrgName = ::cPathForFiles + cPrgName
|
||||
endif
|
||||
endif
|
||||
::cPrgName := cPrgName
|
||||
::oBrwText := nil
|
||||
::oBrwText := TBrwText():New( ::oWndCode:nTop + 1, ::oWndCode:nLeft + 1,;
|
||||
::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, ::cPrgName,;
|
||||
::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, cPrgName,;
|
||||
__DbgColors()[ 2 ] + "," + __DbgColors()[ 5 ] + "," + ;
|
||||
__DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ] )
|
||||
|
||||
::RedisplayBreakpoints() // check for breakpoints in this file and display them
|
||||
::oWndCode:SetCaption( ::cPrgName )
|
||||
::oWndCode:Refresh() // to force the window caption to update
|
||||
endif
|
||||
::GoToLine( nLine )
|
||||
endif
|
||||
|
||||
return nil
|
||||
|
||||
METHOD Open() CLASS TDebugger
|
||||
|
||||
local cFileName := ::InputBox( "Please enter the filename", Space( 30 ) )
|
||||
if (cFileName != ::cPrgName .OR. valtype(::cPrgName)=='U')
|
||||
::cPrgName := cFileName
|
||||
::oBrwText := nil
|
||||
::oBrwText := TBrwText():New( ::oWndCode:nTop + 1, ::oWndCode:nLeft + 1,;
|
||||
::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, ::cPathForFiles+::cPrgName,;
|
||||
__DbgColors()[ 2 ] + "," + __DbgColors()[ 5 ] + "," + ;
|
||||
__DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ] )
|
||||
|
||||
::RedisplayBreakpoints() // check for breakpoints in this file and display them
|
||||
::oWndCode:SetCaption( ::cPrgName )
|
||||
::oWndCode:Refresh() // to force the window caption to update
|
||||
endif
|
||||
return nil
|
||||
|
||||
// check for breakpoints in the current file and display them
|
||||
METHOD RedisplayBreakPoints() CLASS TDebugger
|
||||
|
||||
local n
|
||||
for n := 1 to Len( ::aBreakpoints )
|
||||
if ::aBreakpoints[ n ] [ 2 ] == ::cPrgName
|
||||
::oBrwText:ToggleBreakPoint(::aBreakpoints[ n ] [ 1 ], .T.)
|
||||
Endif
|
||||
next
|
||||
return nil
|
||||
METHOD OSShell() CLASS TDebugger
|
||||
|
||||
local cImage := SaveScreen()
|
||||
@@ -1572,9 +1627,9 @@ return nil
|
||||
|
||||
METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS TDebugger
|
||||
|
||||
local nTop := ( MaxRow() / 2 ) - 8
|
||||
local nTop := ( MaxRow() / 2 ) - 5
|
||||
local nLeft := ( MaxCol() / 2 ) - 25
|
||||
local nBottom := ( MaxRow() / 2 ) - 6
|
||||
local nBottom := ( MaxRow() / 2 ) - 3
|
||||
local nRight := ( MaxCol() / 2 ) + 25
|
||||
local cType := ValType( uValue )
|
||||
local uTemp := PadR( uValue, nRight - nLeft - 1 )
|
||||
@@ -1588,7 +1643,7 @@ METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS TDebugger
|
||||
DEFAULT lEditable TO .t.
|
||||
|
||||
oWndInput:lShadow := .t.
|
||||
oWndInput:Show(.t.)
|
||||
oWndInput:Show()
|
||||
|
||||
if lEditable
|
||||
if bValid == nil
|
||||
@@ -1602,7 +1657,7 @@ METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS TDebugger
|
||||
READ
|
||||
SetCursor( nOldCursor )
|
||||
else
|
||||
@ nTop + 1, nLeft + 1 SAY ValToStr( uValue ) COLOR __DbgColors()[ 5 ]
|
||||
@ nTop + 1, nLeft + 1 SAY ValToStr( uValue ) COLOR "," + __DbgColors()[ 5 ]
|
||||
SetPos( nTop + 1, nLeft + 1 )
|
||||
nOldCursor := SetCursor( SC_NONE )
|
||||
|
||||
@@ -1638,6 +1693,9 @@ METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS TDebugger
|
||||
SetCursor( nOldCursor )
|
||||
endif
|
||||
|
||||
nOldCursor := SetCursor( SC_NORMAL )
|
||||
READ
|
||||
SetCursor( nOldCursor )
|
||||
oWndInput:Hide()
|
||||
Set( _SET_SCOREBOARD, lScoreBoard )
|
||||
|
||||
@@ -1661,9 +1719,9 @@ METHOD Inspect( uValue, cValueName ) CLASS TDebugger
|
||||
|
||||
return nil
|
||||
|
||||
METHOD IsBreakPoint( nLine ) CLASS TDebugger
|
||||
METHOD IsBreakPoint( nLine, cPrgName ) CLASS TDebugger
|
||||
|
||||
return AScan( ::aBreakPoints, { | aBreak | aBreak[ 1 ] == nLine } ) != 0
|
||||
return AScan( ::aBreakPoints, { | aBreak | (aBreak[ 1 ] == nLine) .AND. (aBreak [ 2 ] == cPrgName) } ) != 0
|
||||
|
||||
|
||||
METHOD GotoLine( nLine ) CLASS TDebugger
|
||||
@@ -1684,7 +1742,7 @@ METHOD GotoLine( nLine ) CLASS TDebugger
|
||||
::aCallStack[ ::oBrwStack:Cargo ][ 3 ] = nLine
|
||||
endif
|
||||
|
||||
if ::oBrwStack != nil .and. ! ::oBrwStack:Stable
|
||||
if ::oWndStack != nil .and. ! ::oBrwStack:Stable
|
||||
::oBrwStack:ForceStable()
|
||||
endif
|
||||
|
||||
@@ -1739,6 +1797,7 @@ METHOD RestoreAppStatus() CLASS TDebugger
|
||||
SetPos( ::nAppRow, ::nAppCol )
|
||||
SetColor( ::cAppColors )
|
||||
SetCursor( ::nAppCursor )
|
||||
DispEnd()
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1875,10 +1934,13 @@ METHOD Static() CLASS TDebugger
|
||||
|
||||
return nil
|
||||
|
||||
// Toggle a breakpoint at the cursor position in the currently viewed file
|
||||
// which may be different from the file in which execution was broken
|
||||
METHOD ToggleBreakPoint() CLASS TDebugger
|
||||
|
||||
// look for a breakpoint which matches both line number and program name
|
||||
local nAt := AScan( ::aBreakPoints, { | aBreak | aBreak[ 1 ] == ;
|
||||
::oBrwText:nRow } ) // it was nLine
|
||||
::oBrwText:nRow ;
|
||||
.AND. aBreak [ 2 ] == ::cPrgName} ) // it was nLine
|
||||
|
||||
if nAt == 0
|
||||
AAdd( ::aBreakPoints, { ::oBrwText:nRow, ::cPrgName } ) // it was nLine
|
||||
|
||||
Reference in New Issue
Block a user