dbgwfil.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 972 行 · 第 1/2 页

C
972
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Processing of pop-up menu for source file view.
*
****************************************************************************/


#include "dbgdefn.h"
#include "dbgio.h"
#include "dbgwind.h"
#include "dbgadget.h"
#include "dbginfo.h"
#include "dbgtoken.h"
#include "dbgerr.h"
#include "dbgmem.h"
#include "dbgtoggl.h"
#include "dbgitem.h"
#include "dbgbreak.h" //
#include "dbgstk.h"
#include <string.h>
#include <limits.h>

extern bool             ScanItem( bool, char **, unsigned int * );
extern void             ReqEOC( void );
extern bool             ScanSelectedExpr( char * );
extern void             BreakOnSelected( char *item );

extern char             *StrCopy( char *, char * );
extern a_window         *WndFileInspect( char *file, bool binary );
extern void             *OpenSrcFile( cue_handle * );
extern int              FReadLine( void *, int, int, char *, int );
extern void             FDoneSource( void * );
extern char             *ScanPos( void );
extern unsigned int     ScanCmd( char * );
extern void             Scan( void );
extern char             *ReScan( char * );
extern unsigned long    FSize( void * );
extern unsigned long    FLastOffset( void * );
extern brk              *FindBreakByLine( mod_handle, cue_file_id, unsigned );
extern void             WndFuncInspect( mod_handle mod );
extern void             *AddBreak( address );
extern bool             DlgBreak( address );
extern void             WndInspect( char * );
extern a_window         *WndAsmInspect( address );
extern int              DlgSearch( a_window *, void * );
extern bool             DlgLongExpr( char *title, long *value );
extern void             GoToAddr( address addr );
extern void             ToggleBreak( address );
extern void             SetCodeDot( address );
extern address          GetCodeDot( void );
extern a_window         *WndClassInspect( wnd_class class );
extern void             WndVarInspect( char * );
extern void             AsmMoveDot( a_window *, address );
extern void             AsmJoinSrc( a_window *, a_window * );
extern void             AsmFreeSrc( a_window * );
extern void             AsmNewSrcNotify( a_window *, mod_handle, bool track );
extern void             SkipToAddr( address );
extern void             StepIntoFunction( char * );
extern bool             FirstLinInfo( mod_handle, address *, unsigned * );
extern int              FCurrLine( struct browser *hndl );
extern int              FileIsRemote( struct browser *hndl );
extern unsigned         NewCurrRadix( unsigned int );
extern bool             DbgWndSearch( a_window *, bool, int );
extern char             *DupStr( char * );
extern char             *Format( char *, char *, ... );
extern bool             DlgCodeAddr( char *title, address *value );
extern void             WndSrcInspect( address addr );
extern bool             DlgModName( char *title, mod_handle *mod );
extern void             WndModInspect( mod_handle mod );
extern a_window         *AsmWndFind( a_window *asm, address addr, bool track );
extern a_window         *DoWndSrcOpen( cue_handle *, bool track );
extern unsigned         ExprSize( stack_entry * );
extern void             EvalLValExpr( int );
extern void             PopEntry( void );
extern char             *ModImageName( mod_handle handle );
extern char             *FGetName( void *viewhndl );
extern unsigned         ModName( mod_handle mh, char *result, unsigned max );
extern a_window         *WndNewSrcInspect( address addr );
extern int              AddrComp( address a, address b );
extern void             GoHome( void );
extern void             DbgUpdate( update_list );

extern char             *TxtBuff;
extern tokens           CurrToken;
extern debug_level      ActiveWindowLevel;
extern address          NilAddr;
extern mod_handle       ContextMod;
extern void             *SrchHistory;
extern stack_entry      *ExprSP;

#define MAX_LINE_LEN    255 // must not wrap a gui_ord

#include "menudef.h"

static gui_menu_struct FileShowMenu[] = {
    #define pick( a,b,c,d,e,f,g ) MENU_ITEM( a, b )
    #include "mfilshow.h"
};

static gui_menu_struct FileMenu[] = {
    #include "menufile.h"
};

typedef struct {
    void                *viewhndl;
    unsigned long       size;
    unsigned            active;
    mod_handle          mod;
    cue_file_id         file_id;
    wnd_row             rows;
    unsigned long       rows_offset;
    unsigned long       range;
    address             dotaddr;
    char                *name;
    a_window            *asm;
    unsigned            eof;
    unsigned            track : 1;
    unsigned            erase : 1;
    unsigned            toggled_break : 1;
} file_window;
#define WndFile( wnd ) ( (file_window *)WndExtra( wnd ) )

#define NOT_ACTIVE ((unsigned)-1)
enum {
    PIECE_BREAK,
    PIECE_SOURCE
};

extern  void    SrcJoinAsm( a_window *wnd, a_window *asm )
{
    WndFile( wnd )->asm = asm;
}

extern  void    SrcNewAsmNotify( a_window *asm, mod_handle mod, bool track )
{
    file_window *file;
    a_window    *wnd;

    for( wnd = WndNext( NULL ); wnd != NULL; wnd = WndNext( wnd ) ) {
        if( WndClass( wnd ) != WND_SOURCE ) continue;
        file = WndFile( wnd );
        if( track != file->track ) continue;
        if( mod != file->mod ) continue;
        if( file->asm != NULL ) continue;
        AsmJoinSrc( asm, wnd );
        SrcJoinAsm( wnd, asm );
        break;
    }
}

extern  void    SrcFreeAsm( a_window *wnd )
{
    if( wnd == NULL ) return;
    WndFile( wnd )->asm = NULL;
}

#ifdef DEADCODE
extern  bool    SrcIsTracking( a_window *wnd )
{
    return( WndFile( wnd )->track );
}
#endif

static address GetRowAddr( file_window *file, wnd_row row, bool exact )
{
    DIPHDL( cue, ch );

    if( file->mod == NO_MOD || row < 0 ) return( NilAddr );
    switch( LineCue( file->mod, file->file_id, row+1, 0, ch ) ) {
    case SR_NONE:
        return( NilAddr );
    case SR_CLOSEST:
        if( exact ) return( NilAddr );
        break;
    }
    return( CueAddr( ch ) );
}


static void Centre( a_window *wnd, unsigned line )
{
    WndZapped( wnd );
    WndScroll( wnd, line - ( WndRows( wnd ) / 2 ) - WndTop( wnd ) );
}


static void GotoLine( a_window *wnd )
{
    long        line;
    unsigned    old;
    wnd_row     row;
    int         piece;

    old = NewCurrRadix( 10 );
    WndGetCurrent( wnd, &row, &piece );
    if( row < 0 || row == WND_NO_ROW ) {
        line = WndTop( wnd );
    } else {
        line = row;
    }
    ++line;
    if( DlgLongExpr( LIT( New_Line ), &line ) ) {
        --line;
        WndDirtyCurr( wnd );
        Centre( wnd, line );
        WndNewCurrent( wnd, line, PIECE_SOURCE );
    }
    NewCurrRadix( old );
}


static  WNDMENU FileMenuItem;
static void     FileMenuItem( a_window *wnd, unsigned id, int row, int piece )
{
    address     addr;
    mod_handle  mod;
    bool        has_addr;
    bool        has_popitem;
    file_window *file = WndFile( wnd );

    piece=piece;
    addr = GetRowAddr( file, row, id != MENU_FILE_ASSEMBLY );
    has_addr = !IS_NIL_ADDR( addr );
    switch( id ) {
    case MENU_INITIALIZE:
        has_popitem = ( *WndPopItem( wnd ) != '\0' );
        if( has_popitem && !ScanSelectedExpr( WndPopItem( wnd ) ) ) {
            has_popitem = FALSE;
        }
        WndMenuEnable( wnd, MENU_FILE_SHOW, TRUE );
        WndMenuEnable( wnd, MENU_FILE_SHOW_ADDRESS, TRUE );
        WndMenuEnable( wnd, MENU_FILE_SHOW_MODULE, TRUE );
        WndMenuEnable( wnd, MENU_FILE_FUNCTIONS, file->mod != NO_MOD );
        WndMenuEnable( wnd, MENU_FILE_HOME, TRUE );
        addr = GetRowAddr( file, row, FALSE );
        WndMenuEnable( wnd, MENU_FILE_ASSEMBLY, !IS_NIL_ADDR( addr ) );
        WndMenuEnable( wnd, MENU_FILE_WATCH, has_popitem );
        WndMenuEnable( wnd, MENU_FILE_INSPECT, has_popitem );
        WndMenuEnable( wnd, MENU_FILE_STEP_INTO, file->mod != NO_MOD && has_popitem );
        WndMenuEnable( wnd, MENU_FILE_BREAK, has_popitem );
        WndMenuEnable( wnd, MENU_FILE_RUN, has_addr );
        WndMenuEnable( wnd, MENU_FILE_SKIP_TO_CURSOR, has_addr );
        break;
    case MENU_FILE_RUN:
        GoToAddr( addr );
        break;
    case MENU_FILE_SKIP_TO_CURSOR:
        SkipToAddr( addr );
        break;
    case MENU_FILE_BREAK:
        BreakOnSelected( WndPopItem( wnd ) );
        break;
    case MENU_FILE_HOME:
        GoHome();
        break;
    case MENU_FILE_SHOW_MODULE:
        mod = file->mod;
        if( DlgModName( LIT( New_Module ), &mod ) ) {
            WndModInspect( mod );
        }
        break;
    case MENU_FILE_SHOW_ADDRESS:
        if( DlgCodeAddr( LIT( New_Addr ), &addr ) ) {
            WndSrcInspect( addr );
        }
        break;
    case MENU_FILE_STEP_INTO:
        StepIntoFunction( WndPopItem( wnd ) );
        break;
    case MENU_FILE_INSPECT:
        WndInspect( WndPopItem( wnd ) );
        break;
    case MENU_FILE_WATCH:
        WndVarInspect( WndPopItem( wnd ) );
        break;
    case MENU_FILE_SEARCH:
        WndSaveToHistory( SrchHistory, WndPopItem( wnd ) );
        DbgWndSearch( wnd, FALSE, DlgSearch( wnd, SrchHistory ) );
        break;
    case MENU_FILE_ASSEMBLY:
        AsmWndFind( file->asm, addr, file->track );
        break;
    case MENU_FILE_LINE:
        GotoLine( wnd );
        break;
    case MENU_FILE_FUNCTIONS:
        WndFuncInspect( file->mod );
        break;
    }
}


static void FilePosInit( a_window *wnd )
{
    file_window *file = WndFile( wnd );

    if( file->viewhndl == NULL ) {
        file->size = 0;
    } else {
        file->size = FSize( file->viewhndl );
    }
    WndSetThumbPercent( wnd, 0 );
}


static void FilePos( a_window *wnd, int pos )
{
    unsigned long       range;
    file_window *file = WndFile( wnd );

    if( pos < 0 ) pos = 0;
    if( file->viewhndl == NULL ) {
        if( pos+WndRows(wnd) > file->eof ) return;
        WndSetTop( wnd, pos );
        return;
    }
    if( FReadLine( file->viewhndl, pos+WndRows(wnd), 0, TxtBuff, TXT_LEN ) < 0 ) {
        pos = FCurrLine( file->viewhndl ) - WndRows(wnd) - 1;
        if( pos < 0 ) {
            pos = 0;
        }
    }
    WndSetTop( wnd, pos );
    if( pos >= file->rows ) {
        file->rows = pos+1;
        file->rows_offset = FLastOffset( file->viewhndl );
    }
    if( file->rows == 0 ) file->rows = 1;
    if( file->rows_offset == 0 ) {
        range = file->size;
    } else {
        range = file->size * file->rows / file->rows_offset;
    }
    WndSetVScrollRange( wnd, range );
    WndSetThumbPos( wnd, pos );
}


static WNDSCROLL FileScroll;
static int FileScroll( a_window *wnd, int lines )
{
    int         old_top;

    old_top = WndTop( wnd );
    FilePos( wnd, old_top + lines );
    return( WndTop( wnd ) - old_top );
}


static  WNDMODIFY FileModify;
static  void    FileModify( a_window *wnd, int row, int piece )
{
    file_window *file = WndFile( wnd );
    address     addr;

    if( piece == PIECE_BREAK ) {
        addr = GetRowAddr( file, row, TRUE );
        if( IS_NIL_ADDR( addr ) ) return;
        file->toggled_break = ( ( WndFlags & UP_BREAK_CHANGE ) == 0 );
        ToggleBreak( addr );
        WndRowDirty( wnd, row );
    } else {
        WndFirstMenuItem( wnd, row, piece );
    }
}

static void FileSetDotAddr( a_window *wnd, address addr )
{
    file_window *file = WndFile( wnd );

    if( AddrComp( file->dotaddr, addr ) == 0 ) return;
    file->dotaddr = addr;
    if( IS_NIL_ADDR( addr ) ) return;
    if( wnd == WndFindActive() ) {
        AsmMoveDot( file->asm, addr );
        SetCodeDot( addr );
    }
}

static  WNDNOTIFY       FileNotify;
static void FileNotify( a_window *wnd, wnd_row row, int piece )
{
    file_window *file = WndFile( wnd );
    address     addr;

    piece = piece;
    addr = GetRowAddr( file, row, FALSE );
    if( IS_NIL_ADDR( addr ) ) return;
    FileSetDotAddr( wnd, addr );
}


bool FileOpenGadget( a_window *wnd, wnd_line_piece *line, mod_handle mod )
{
    a_window    *curr;
    for( curr = WndNext( NULL ); curr != NULL; curr = WndNext( curr ) ) {
        if( WndClass( curr ) != WND_SOURCE ) continue;
        if( mod == WndFile( curr )->mod ) {
            if( line != NULL ) SetGadgetLine( wnd, line, GADGET_OPEN_SOURCE );
            return( TRUE );
        }
    }
    if( line != NULL ) SetGadgetLine( wnd, line, GADGET_CLOSED_SOURCE );
    return( FALSE );
}


void FileBreakGadget( a_window *wnd, wnd_line_piece *line, bool curr, brk *bp )
{
    if( curr ) {
        if( bp == NULL ) {
            SetGadgetLine( wnd, line, GADGET_CURRLINE );
        } else if( bp->status.b.active ) {
            SetGadgetLine( wnd, line, GADGET_CURRBREAK );
        } else {
            SetGadgetLine( wnd, line, GADGET_CURRDIMBREAK );
        }
    } else {
        if( bp == NULL ) {
            SetGadgetLine( wnd, line, GADGET_NOBREAK );
        } else if( bp->status.b.active ) {
            SetGadgetLine( wnd, line, GADGET_BREAK );
        } else {
            SetGadgetLine( wnd, line, GADGET_DIMBREAK );
        }
    }
}


static WNDGETLINE FileGetLine;
static  bool    FileGetLine( a_window *wnd, int row, int piece,
                             wnd_line_piece *line )
{
    int         len;
    file_window *file = WndFile( wnd );
    address     addr;
    brk         *bp;
    bool        curr;
    DIPHDL( cue, ch );

    line->text = LIT( Empty );
    if( file->viewhndl == NULL && ModHasInfo( file->mod, HK_CUE ) != DS_OK ) {
        return( FALSE );
    }
    curr = ( row == file->active && ContextMod == file->mod );
    switch( piece ) {
    case PIECE_BREAK:
        line->tabstop = FALSE;
        if( row >= file->eof ) return( FALSE );
        if( file->mod == NO_MOD ) return( TRUE );
        addr = NilAddr;
        if( !WndDoingSearch ) { // too expensive
            addr = GetRowAddr( file, row, TRUE );
        }
        if( !IS_NIL_ADDR( addr ) ) {
            bp = FindBreakByLine( file->mod, file->file_id, row+1 );
            FileBreakGadget( wnd, line, curr, bp );
        }
        return( TRUE );
    case PIECE_SOURCE:
        line->text = TxtBuff;
        line->extent = WND_MAX_EXTEND;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?