From 4c9284dcecc810a62846cd42e7f30df639f6d9c7 Mon Sep 17 00:00:00 2001 From: Phil Krylov Date: Mon, 7 Jun 2004 09:44:09 +0000 Subject: [PATCH] 2004-06-07 13:45 UTC+0300 Phil Krylov --- harbour/ChangeLog | 14 +++ harbour/source/debug/dbgtarr.prg | 4 + harbour/source/debug/dbgwa.prg | 44 ++++--- harbour/source/debug/debugger.prg | 196 +++++++++++++++++++----------- harbour/source/debug/tbrwtext.prg | 58 +++++---- 5 files changed, 203 insertions(+), 113 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 5ff462f89c..f72348febf 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,20 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2004-06-07 13:45 UTC+0300 Phil Krylov + * source/debug/dbgwa.prg + * source/debug/dbgtarr.prg + * source/debug/tbrwtext.prg + * source/debug/debugger.prg + ! Miscellaneous fixes borrowed from xHarbour: + ! Fixed support for monitoring work areas with non-contigous numbers. + ! Fixed monitoring empty subarrays. + ! Maintain separate "active" line and cursor line in the code window. + Support external initialization of TBrwText():lLineNumbers. + ! Fixed problems with breakpoints and source files stored in multiple + directories. The environment variable HB_DBG_PATH takes precedence + over PATH to search for source files. + 2004-06-03 11:00 UTC+0100 Ryszard Glab * source/compiler/harbour.c diff --git a/harbour/source/debug/dbgtarr.prg b/harbour/source/debug/dbgtarr.prg index 31c2b42c88..7f46072b58 100644 --- a/harbour/source/debug/dbgtarr.prg +++ b/harbour/source/debug/dbgtarr.prg @@ -158,6 +158,9 @@ method SetsKeyPressed( nKey, oBrwSets, nSets, oWnd ,cName,LenArr,aArray) Class T Case nKey == K_ENTER if valtype(aArray[nSet])=="A" + if Len( aArray[ nSet ] ) == 0 + Alert( "Array is empty" ) + else SetPos(ownd:nBottom,ownd:nLeft) ::aWindows[::nCurwindow]:lFocused:=.f. ::arrayname:= ::arrayname+"["+alltrim(cTemp)+"]" @@ -171,6 +174,7 @@ method SetsKeyPressed( nKey, oBrwSets, nSets, oWnd ,cName,LenArr,aArray) Class T else ::ncurwindow-- endif + endif elseif valtype(aArray[nSet])=="B" Alert("Value cannot be edited") else diff --git a/harbour/source/debug/dbgwa.prg b/harbour/source/debug/dbgwa.prg index b05925bff0..811619a8c9 100644 --- a/harbour/source/debug/dbgwa.prg +++ b/harbour/source/debug/dbgwa.prg @@ -4,7 +4,7 @@ /* * Harbour Project source code: - * The Debugger Array Inspector + * The Debugger Work Area Inspector * * Copyright 2001-2002 Ignacio Ortiz de Zuņiga * www - http://www.harbour-project.org @@ -58,21 +58,27 @@ function __dbgShowWorkAreas( oDebugger ) local oDlg, oCol local aAlias, aBrw, aStruc, aInfo local cColor - local n1, n2, n3 + local n1, n2, n3, cur_id aAlias := {} aBrw := Array(3) n1 := 1 n2 := 1 n3 := 1 + cur_id := 1 cColor := iif( __Dbg():lMonoDisplay, "N/W, W/N, W+/W, W+/N",; "N/W, N/BG, R/W, R/BG" ) - do while !Empty( Alias( n1 ) ) - Aadd(aAlias, Alias( n1 )) - n1++ - enddo + /* We can't determine the last used area, so use 512 here */ + for n1 := 1 to 512 + if ( n1 )->( Used() ) + AAdd(aAlias, { n1, Alias(n1) }) + if n1 == Select() + cur_id = Len(aAlias) + endif + endif + next if len( aAlias ) == 0 Alert( "No workareas in use") @@ -94,7 +100,7 @@ function __dbgShowWorkAreas( oDebugger ) aBrw[1] := TBrowseNew( oDlg:nTop + 1, oDlg:nLeft + 1, oDlg:nBottom - 1, oDlg:nLeft + 11 ) - aBrw[1]:Cargo := ( n1 := Select() ) + aBrw[1]:Cargo := ( n1 := cur_id ) aBrw[1]:ColorSpec := oDlg:cColor aBrw[1]:GoTopBlock := { || n1 := 1 } aBrw[1]:GoBottomBlock := { || n1 := Len( aAlias ) } @@ -102,15 +108,15 @@ function __dbgShowWorkAreas( oDebugger ) n1 := iif( nSkip > 0, Min( Len( aAlias ), n1 + nSkip ),; Max( 1, n1 + nSkip ) ), n1 - nPos } - aBrw[1]:AddColumn( oCol := TBColumnNew( "", { || PadR( aAlias[ n1 ], 11 ) } ) ) + aBrw[1]:AddColumn( oCol := TBColumnNew( "", { || PadR( aAlias[n1][2], 11 ) } ) ) - oCol:ColorBlock := { || iif( aAlias[ n1 ] == Alias(), {3, 4}, {1, 2} ) } + oCol:ColorBlock := { || iif( aAlias[n1][1] == Select(), {3, 4}, {1, 2} ) } /* Info Browse */ - aInfo := ( aAlias[n1] )->(DbfInfo()) + aInfo := ( aAlias[n1][1] )->( DbfInfo() ) aBrw[2] := TBrowseNew( oDlg:nTop + 7, oDlg:nLeft + 13, oDlg:nBottom - 1, oDlg:nLeft + 50 ) @@ -124,13 +130,13 @@ function __dbgShowWorkAreas( oDebugger ) aBrw[2]:AddColumn( oCol := TBColumnNew( "", { || Padr(aInfo[ n2 ], 38) } ) ) - oCol:ColorBlock := { || iif( aAlias[ n1 ] == Alias() .and. n2 == 1, {3, 4}, {1, 2} ) } + oCol:ColorBlock := { || iif( aAlias[n1][1] == Select() .and. n2 == 1, {3, 4}, {1, 2} ) } /* Struc browse */ - aStruc := ( aAlias[n1] )->(DbStruct()) + aStruc := ( aAlias[n1][1] )->( DbStruct() ) aBrw[3] := TBrowseNew( oDlg:nTop + 1, oDlg:nLeft + 52, oDlg:nBottom - 1, oDlg:nLeft + 70 ) @@ -241,7 +247,7 @@ static function DlgWorkAreaKey( nKey, oDlg, aBrw, aAlias, aStruc, aInfo ) aBrw[2]:GoTop() aBrw[2]:Invalidate() aBrw[2]:ForceStable() - aInfo := ( aAlias[aBrw[1]:Cargo] )->(DbfInfo( aInfo )) + aInfo := ( aAlias[aBrw[1]:Cargo][1] )->( DbfInfo(aInfo) ) aBrw[3]:Configure() aBrw[2]:Invalidate() aBrw[2]:RefreshAll() @@ -250,13 +256,13 @@ static function DlgWorkAreaKey( nKey, oDlg, aBrw, aAlias, aStruc, aInfo ) aBrw[3]:GoTop() aBrw[3]:Invalidate() aBrw[3]:ForceStable() - aStruc := ( aAlias[aBrw[1]:Cargo] )->(DbStruct()) + aStruc := ( aAlias[aBrw[1]:Cargo][1] )->( DbStruct() ) aBrw[3]:Configure() aBrw[3]:Invalidate() aBrw[3]:RefreshAll() aBrw[3]:ForceStable() aBrw[3]:Dehilite() - UpdateInfo( oDlg, aAlias[aBrw[1]:Cargo] ) + UpdateInfo( oDlg, aAlias[aBrw[1]:Cargo][2] ) endif case nFocus == 2 WorkAreasKeyPressed( nKey, aBrw[2], oDlg, len( aInfo ) ) @@ -350,7 +356,13 @@ return aInfo static function UpdateInfo( oDlg, cAlias ) - local cOldAlias := Alias() + local cOldAlias + + if empty(cAlias) + return NIL + endif + + cOldAlias := Alias() SELECT (cAlias) diff --git a/harbour/source/debug/debugger.prg b/harbour/source/debug/debugger.prg index 5c39a8245a..23f5daf23c 100644 --- a/harbour/source/debug/debugger.prg +++ b/harbour/source/debug/debugger.prg @@ -206,13 +206,13 @@ procedure __dbgEntry( nMode, uParam1, uParam2, uParam3 ) // debugger entry poin s_oDebugger:Activate() endif - case nMode == HB_DBG_MODULENAME + case nMode == HB_DBG_MODULENAME // called from hvm.c hb_vmModuleName() // add a call to the stack but don't try to show the code yet cProcName := ProcName( 1 ) if cProcName == "(_INITSTATICS)" //module wide static variable - AADD( __dbgStatics, { uParam1, {} } ) + AADD( __dbgStatics, { strip_path( uParam1 ), {} } ) return // We can not use s_oDebugger yet, so we return endif @@ -282,7 +282,7 @@ procedure __dbgEntry( nMode, uParam1, uParam2, uParam3 ) // debugger entry poin if s_oDebugger:lShowStatics if ( nAt := AScan( s_oDebugger:aVars,; // Is there another var with this name ? - { | aVar | aVar[ VAR_NAME ] == cVarName } ) ) != 0 + { | aVar | aVar[ VAR_NAME ] == cVarName } ) ) != 0 s_oDebugger:aVars[ nAt ] := ATAIL( s_oDebugger:aCallStack[ 1 ][ CSTACK_STATICS ] ) else AAdd( s_oDebugger:aVars, ATAIL( s_oDebugger:aCallStack[ 1 ][ CSTACK_STATICS ] ) ) @@ -325,6 +325,7 @@ CLASS TDebugger DATA oBrwPnt, oWndPnt DATA lppo INIT .F. //view preprocessed output DATA lRunAtStartup + DATA lLineNumbers INIT .T. METHOD New() METHOD Activate() @@ -470,7 +471,10 @@ METHOD New() CLASS TDebugger // 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 := getenv( "PATH" ) + ::cPathForFiles := getenv( "HB_DBG_PATH" ) + if empty( ::cPathForFiles ) + ::cPathForFiles := getenv( "PATH" ) + endif ::nTabWidth := 4 ::nSpeed := 0 ::lShowCallStack := .f. @@ -506,14 +510,6 @@ METHOD New() CLASS TDebugger return Self -METHOD PathForFiles() CLASS TDebugger - - ::cPathForFiles := ::InputBox( "Search path for source files:", ::cPathForFiles ) - IF ! RIGHT(::cPathForFiles,1) $ HB_OSPATHDELIMITERS() - ::cPathForFiles:=::cPathForFiles + HB_OSPATHSEPARATOR() - ENDIF - -return Self METHOD Activate() CLASS TDebugger @@ -1273,6 +1269,20 @@ METHOD NextWindow() CLASS TDebugger return nil + +METHOD PathForFiles( cPathForFiles ) CLASS TDebugger + + IF cPathForFiles == NIL + cPathForFiles := ::InputBox( "Search path for source files:", ::cPathForFiles ) + ENDIF + IF ! RIGHT(cPathForFiles, 1) $ HB_OSPATHDELIMITERS() + cPathForFiles += HB_OSPATHSEPARATOR() + ENDIF + ::cPathForFiles := cPathForFiles + +RETURN Self + + METHOD PrevWindow() CLASS TDebugger local oWnd @@ -1685,19 +1695,20 @@ return { | a | a[ 1 ] == Self:oBrwText:nRow } // it was nLine METHOD StackProc( cModuleName, nProcLevel ) CLASS TDebugger // always treat filename as lower case - we need it consistent for comparisons LOCAL nPos:=RAT( ":", cModuleName ) + LOCAL aEntry := { ; + IIF(::lCodeBlock,"(b)","")+SubStr( cModuleName, nPos + 1 ),; //function name + {},; //local vars + nil,; //line no, nil means that no line number is stored yet + lower( strip_path( LEFT( cModuleName, nPos - 1 ) ) ),; // and the module name + {}, ; // static vars + nProcLevel } ASize( ::aCallStack, Len( ::aCallStack ) + 1 ) AIns( ::aCallStack, 1 ) - - // nil means that no line number is stored yet - ::aCallStack[1]:= { IIF(::lCodeBlock,"(b)","")+SubStr( cModuleName, nPos + 1 ),; //function name - {},; //local vars - nil,; //line no - lower(LEFT( cModuleName, nPos - 1 )),; // and the module name - {},; // static vars - nProcLevel } + ::aCallStack[ 1 ] := aEntry return nil + //METHOD ShowCodeLine( nLine, cPrgName ) CLASS TDebugger METHOD ShowCodeLine( nProc ) CLASS TDebugger LOCAL nPos, nLevel @@ -1730,36 +1741,56 @@ LOCAL nLine, cPrgName cPrgName += cPrgName +".ppo" ENDIF endif - if( cPrgName != ::cPrgName .OR. ::oBrwText == NIL ) - if ! File( cPrgName ) .and. ! Empty( ::cPathForFiles ) - cPrgName := ::LocatePrgPath( cPrgName ) + + if ! empty( cPrgName ) + + if ( strip_path( cPrgName ) != strip_path( ::cPrgName ) .OR. ::oBrwText == NIL ) + + if ! File( cPrgName ) .and. !Empty( ::cPathForFiles ) + cPrgName := ::LocatePrgPath( cPrgName ) + endif + + ::cPrgName := cPrgName + + if ::oBrwText == nil + ::oBrwText := TBrwText():New( ::oWndCode:nTop + 1, ::oWndCode:nLeft + 1,; + ::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, cPrgName,; + __DbgColors()[ 2 ] + "," + __DbgColors()[ 5 ] + "," + ; + __DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ], ; + ::lLineNumbers ) + + ::oWndCode:Browser := ::oBrwText + + else + ::oBrwText:LoadFile(cPrgName) + endif + + ::oWndCode:bPainted := {|| IIF( ::oBrwText != nil, ::oBrwText:RefreshAll():ForceStable(), ::oWndCode:Clear() ) } + ::RedisplayBreakpoints() // check for breakpoints in this file and display them + ::oWndCode:SetCaption( ::cPrgName ) + ::oWndCode:Refresh() // to force the window caption to update endif - ::cPrgName := cPrgName - ::oBrwText := nil - ::oBrwText := TBrwText():New( ::oWndCode:nTop + 1, ::oWndCode:nLeft + 1,; - ::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, cPrgName,; - __DbgColors()[ 2 ] + "," + __DbgColors()[ 5 ] + "," + ; - __DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ] ) - - ::oWndCode:Browser := ::oBrwText - ::oWndCode:bPainted :={|| IIF(::oBrwText!=nil,::oBrwText:refreshAll():forceStable(),::oWndCode:Clear()) } - ::RedisplayBreakpoints() // check for breakpoints in this file and display them - ::oWndCode:SetCaption( ::cPrgName ) - ::oWndCode:Refresh() // to force the window caption to update + ::oBrwText:SetActiveLine( nLine ) + ::GotoLine( nLine ) endif - ::GoToLine( nLine ) endif return nil -METHOD Open() CLASS TDebugger -LOCAL cFileName := ::InputBox( "Please enter the filename", Space( 255 ) ) -LOCAL cPrgName - cFileName:= ALLTRIM( cFileName ) - if !EMPTY(cFileName) .AND. (cFileName != ::cPrgName .OR. valtype(::cPrgName)=='U') +METHOD Open() CLASS TDebugger + LOCAL cFileName := ::InputBox( "Please enter the filename", Space( 255 ) ) + LOCAL cPrgName + + cFileName:= ALLTRIM( cFileName ) + + if !EMPTY(cFileName) .AND. (cFileName != ::cPrgName .OR. valtype(::cPrgName)=='U') if ! File( cFileName ) .and. ! Empty( ::cPathForFiles ) - cFileName := ::LocatePrgPath( cFileName ) + cFileName := ::LocatePrgPath( cFileName ) + if Empty( cFileName ) + Alert( "File not found!" ) + return NIL + endif endif ::cPrgName := cFileName ::lppo := RAT(".PPO", UPPER(cFileName)) > 0 @@ -1768,15 +1799,16 @@ LOCAL cPrgName ::oBrwText := TBrwText():New( ::oWndCode:nTop + 1, ::oWndCode:nLeft + 1,; ::oWndCode:nBottom - 1, ::oWndCode:nRight - 1, cFileName,; __DbgColors()[ 2 ] + "," + __DbgColors()[ 5 ] + "," + ; - __DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ] ) + __DbgColors()[ 3 ] + "," + __DbgColors()[ 6 ], ; + ::lLineNumbers ) ::oWndCode:Browser := ::oBrwText ::RedisplayBreakpoints() // check for breakpoints in this file and display them ::oWndCode:SetCaption( ::cPrgName ) - ::oWndCode:Refresh() // to force the window caption to update + ::oWndCode:Refresh() // to force the window caption to update endif - return nil + METHOD OpenPPO() CLASS TDebugger LOCAL nPos LOCAL lSuccess:=.F. @@ -1816,7 +1848,7 @@ METHOD RedisplayBreakPoints() CLASS TDebugger local n for n := 1 to Len( ::aBreakpoints ) - if ::aBreakpoints[ n ] [ 2 ] == ::cPrgName + if ::aBreakpoints[ n ] [ 2 ] == strip_path( ::cPrgName ) ::oBrwText:ToggleBreakPoint(::aBreakpoints[ n ] [ 1 ], .T.) Endif next @@ -2214,36 +2246,44 @@ 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 - LOCAL cLine - - cLine := ::oBrwText:GetLine( ::oBrwText:nRow ) - IF( ::oBrwText:lLineNumbers ) - cLine := SUBSTR( cLine, AT(":",cLine)+1 ) - ENDIF - IF( IsValidStopLine( cLine ) ) - nAt := AScan( ::aBreakPoints, { | aBreak | aBreak[ 1 ] == ; - ::oBrwText:nRow ; - .AND. aBreak [ 2 ] == ::cPrgName} ) // it was nLine + // look for a breakpoint which matches both line number and program name + local nAt + LOCAL cLine + local cFileName - if nAt == 0 - AAdd( ::aBreakPoints, { ::oBrwText:nRow, ::cPrgName } ) // it was nLine - ::oBrwText:ToggleBreakPoint(::oBrwText:nRow, .T.) - else - ADel( ::aBreakPoints, nAt ) - ASize( ::aBreakPoints, Len( ::aBreakPoints ) - 1 ) - ::oBrwText:ToggleBreakPoint(::oBrwText:nRow, .F.) - endif + IF !::lActive + RETURN NIL + ENDIF - ::oBrwText:RefreshCurrent() - ENDIF + cLine := ::oBrwText:GetLine( ::oBrwText:nRow ) + IF ::oBrwText:lLineNumbers + cLine := SUBSTR( cLine, AT(":",cLine)+1 ) + ENDIF + IF IsValidStopLine( cLine ) + cFileName := strip_path( ::cPrgName ) + + nAt := AScan( ::aBreakPoints, { | aBreak | aBreak[ 1 ] == ::oBrwText:nRow ; + .AND. aBreak[ 2 ] == cFileName } ) // it was nLine + + if nAt == 0 + AAdd( ::aBreakPoints, { ::oBrwText:nRow, cFileName } ) // it was nLine + ::oBrwText:ToggleBreakPoint(::oBrwText:nRow, .T.) + else + ADel( ::aBreakPoints, nAt ) + ASize( ::aBreakPoints, Len( ::aBreakPoints ) - 1 ) + ::oBrwText:ToggleBreakPoint(::oBrwText:nRow, .F.) + endif + + ::oBrwText:RefreshCurrent() + ENDIF return nil + METHOD ViewSets() CLASS TDebugger local oWndSets := TDbWindow():New( 1, 8, MaxRow() - 2, MaxCol() - 8,; @@ -2519,7 +2559,7 @@ LOCAL cLine cLine := SUBSTR( cLine, AT(":",cLine)+1 ) ENDIF IF( IsValidStopLine( cLine ) ) - ::aToCursor := { ::oBrwText:nRow, ::cPrgName } + ::aToCursor := { ::oBrwText:nRow, strip_path( ::cPrgName ) } ::RestoreAppStatus() ::lToCursor := .t. ::Exit() @@ -3162,8 +3202,11 @@ static function PathToArray( cList ) local nPos local aList := {} local cSep + local cDirSep cSep := HB_OsPathListSeparator() + cDirSep := HB_OsPathDelimiters() + if ( cList <> NIL ) do while ( nPos := at( cSep, cList ) ) <> 0 @@ -3173,6 +3216,19 @@ static function PathToArray( cList ) aadd( aList, cList ) // Add final element + /* Strip ending delimiters */ + AEval(aList, {|x, i| if( Right( x, 1 ) $ cDirSep, aList[ i ] := Left( x, Len( x ) - 1 ), ) } ) endif - return aList +return aList + + +/* Strip path from filename */ +STATIC FUNCTION strip_path( cFileName ) + LOCAL cName := "", cExt := "" + DEFAULT cFileName TO "" + + HB_FNAMESPLIT( cFileName, NIL, @cName, @cExt ) +RETURN cName + cExt + + diff --git a/harbour/source/debug/tbrwtext.prg b/harbour/source/debug/tbrwtext.prg index ef63c9ad2b..928a791dcc 100644 --- a/harbour/source/debug/tbrwtext.prg +++ b/harbour/source/debug/tbrwtext.prg @@ -58,15 +58,15 @@ // Color definitions and positions inside ::cColorSpec #define CLR_CODE 0 // color of code -#define CLR_CURSOR 1 // color of hilighted line +#define CLR_CURSOR 1 // color of highlighted line (the line to be executed) #define CLR_BKPT 2 // color of breakpoint line -#define CLR_HIBKPT 3 // color of hilighted breakpoint line +#define CLR_HIBKPT 3 // color of highlighted breakpoint line CLASS TBrwText FROM HBEditor DATA cFileName // the name of the browsed file - DATA nActiveLine // Active line inside Code Window (last executed one) + DATA nActiveLine // Active line inside Code Window (the line to be executed) DATA aBreakPoints // Array with line numbers of active Break Points @@ -89,7 +89,8 @@ CLASS TBrwText FROM HBEditor METHOD RefreshCurrent() METHOD ForceStable() INLINE NIL - METHOD GotoLine(n) // Moves active line cursor, that is it hilights last executed line of code + METHOD GotoLine(n) // Moves active line cursor + METHOD SetActiveLine( n ) // Sets the line to be executed METHOD GetLine(nRow) // Redefine HBEditor method to add line number METHOD LineColor(nRow) // Redefine HBEditor method to handle line coloring @@ -98,19 +99,22 @@ CLASS TBrwText FROM HBEditor // if lSet is .F. BreakPoint at nRow has to be removed METHOD Search( cString, lCaseSensitive, nMode ) // 0 from Begining to end, 1 Forward, 2 Backwards + METHOD LoadFile(cFileName) + ENDCLASS -METHOD New(nTop, nLeft, nBottom, nRight, cFileName, cColor) CLASS TBrwText +METHOD New(nTop, nLeft, nBottom, nRight, cFileName, cColor, lLineNumbers) CLASS TBrwText DEFAULT cColor TO SetColor() + DEFAULT lLineNumbers TO .T. ::cFileName := cFileName ::nActiveLine := 1 ::aBreakPoints := {} - ::lLineNumbers := .T. + ::lLineNumbers := lLineNumbers Super:New("", nTop, nLeft, nBottom, nRight, .T.) Super:SetColor(cColor) @@ -120,6 +124,13 @@ METHOD New(nTop, nLeft, nBottom, nRight, cFileName, cColor) CLASS TBrwText return Self +METHOD LoadFile(cFileName) CLASS TBrwText + + Super:LoadFile(cFileName) + +return Self + + METHOD GoTop() CLASS TBrwText ::MoveCursor(K_CTRL_PGUP) return Self @@ -170,17 +181,15 @@ METHOD RefreshCurrent() CLASS TBrwText return Self +METHOD SetActiveLine( n ) CLASS TBrwText + ::nActiveLine := n + ::RefreshWindow() +return Self + + METHOD GotoLine(n) CLASS TBrwText - // We need to set active line before calling ::RefreshLine() since ::LineColor() - // uses nActiveLine to decide which color to use to paint line - ::nActiveLine := n - ::RefreshLine() - Super:GotoLine(n) - // I need to call ::RefreshLine() here because HBEditor does not repaint current line - // if it needs not to and without this explicit call I don't see ActiveLine cursor movement - ::RefreshLine() return Self @@ -192,24 +201,19 @@ return iif(::lLineNumbers, AllTrim(Str(nRow)) + ": ", "") + Super:GetLine(nRow) METHOD LineColor(nRow) CLASS TBrwText - local cColor, lHilited, lBreak + local cColor, lHilited, lBreak, nIndex := CLR_CODE lHilited := (nRow == ::nActiveLine) lBreak := AScan(::aBreakPoints, nRow) > 0 - if lHilited .AND. lBreak - cColor := hb_ColorIndex(::cColorSpec, CLR_HIBKPT) - - elseif lHilited - cColor := hb_ColorIndex(::cColorSpec, CLR_CURSOR) - - elseif lBreak - cColor := hb_ColorIndex(::cColorSpec, CLR_BKPT) - - else - cColor := hb_ColorIndex(::cColorSpec, CLR_CODE) - + if lHilited + nIndex += CLR_CURSOR endif + if lBreak + nIndex += CLR_BKPT + endif + + cColor := hb_ColorIndex(::cColorSpec, nIndex) return cColor