dbgwfunc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 349 行

C
349
字号
/****************************************************************************
*
*                            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:  The 'Functions' window.
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include "dbgdefn.h"
#include "dbginfo.h"
#include "dbgwind.h"
#include "dbgerr.h"
#include "dbgadget.h"
#include "dbgbreak.h"
#include "dbgtoggl.h"
#include "namelist.h"


extern brk              *FindBreak( address );
extern a_window         *WndAsmInspect( address );
extern a_window         *WndSrcInspect( address );
extern void             *AddBreak( address );
extern void             RemoveBreak( address );
extern bool             DlgBreak( address );
extern void             GoToAddr( address addr );
extern bool             HasLineInfo( address );
extern void             ToggleBreak( address );
extern char             *FileBreakGadget( a_window *, wnd_line_piece *, bool curr, brk *bp );
extern address          GetCodeDot( void );
extern search_result    DeAliasAddrMod( address a, mod_handle *mh );

extern char             *TxtBuff;
extern address          NilAddr;


#include "menudef.h"
static gui_menu_struct FuncMenu[] = {
    #include "menufunc.h"
};

typedef struct {
    name_list           ___n;           // don't reference directly!
    mod_handle          mod;
    gui_ord             max_name;
    unsigned            global : 1;
    unsigned            toggled_break : 1;
    unsigned            d2_only : 1;
} func_window;

#define WndFunc( wnd ) ( (func_window*)WndExtra( wnd ) )
#define NameList( f ) ( &(f)->___n )

enum {
    PIECE_BREAK,
    PIECE_NAME,
    PIECE_DEMANGLED,
};


static  WNDMODIFY       FuncModify;
static  void    FuncModify( a_window *wnd, int row, int piece )
{
    address     addr;
    func_window *func = WndFunc( wnd );

    if( piece == PIECE_BREAK ) {
        if( row < 0 ) return;
        if( row >= NameListNumRows( NameList( func ) ) ) return;
        addr = NameListAddr( NameList( func ), row );
        func->toggled_break = ( ( WndFlags & UP_BREAK_CHANGE ) == 0 );
        ToggleBreak( addr );
        WndRowDirty( wnd, row );
    } else {
        WndFirstMenuItem( wnd, row, piece );
    }
}

static void FuncNoMod( a_window *wnd )
{
    func_window *func = WndFunc( wnd );

    WndScrollAbs( wnd, 0 );
    NameListFree( NameList( func ) );
    WndZapped( wnd );
}

static void FuncGetSourceName( a_window *wnd, int row )
{
    func_window *func = WndFunc( wnd );

    NameListName( NameList( func ), row, TxtBuff, SN_QUALIFIED );
}

static int FuncNumRows( a_window *wnd )
{
    return( NameListNumRows( NameList( WndFunc( wnd ) ) ) );
}

static void CalcIndent( a_window *wnd )
{
    gui_ord     len,max;
    int         row,rows;

    rows = FuncNumRows( wnd );
    max = 0;
    for( row = 0; row < rows; ++row ) {
        FuncGetSourceName( wnd, row );
        len = WndExtentX( wnd, TxtBuff );
        if( len > max ) max = len;
    }
    WndFunc( wnd )->max_name = max;
}

static void FuncSetMod( a_window *wnd, mod_handle mod )
{
    func_window *func = WndFunc( wnd );

    func->mod = mod;
    NameListAddModules( NameList( func ), mod, func->d2_only, TRUE );
    CalcIndent( wnd );
}

static void FuncNewOptions( a_window *wnd )
{
    FuncNoMod( wnd );
    FuncSetMod( wnd, WndFunc( wnd )->mod );
    WndZapped( wnd );
}

static  WNDMENU FuncMenuItem;
static void     FuncMenuItem( a_window *wnd, unsigned id, int row, int piece )
{
    address     addr;
    func_window *func = WndFunc( wnd );

    piece=piece;
    addr = ( row == WND_NO_ROW ) ? NilAddr : NameListAddr( NameList( func ), row );
    switch( id ) {
    case MENU_INITIALIZE:
        if( IS_NIL_ADDR( addr ) ) {
            WndMenuGrayAll( wnd );
        } else {
            WndMenuEnableAll( wnd );
            WndMenuEnable( wnd, MENU_FUNCTIONS_SOURCE, HasLineInfo( addr ) );
        }
        WndMenuEnable( wnd, MENU_FUNCTIONS_D2_ONLY, TRUE );
        WndMenuCheck( wnd, MENU_FUNCTIONS_D2_ONLY, func->d2_only );
        break;
    case MENU_FUNCTIONS_SOURCE:
        WndSrcInspect( addr );
        break;
    case MENU_FUNCTIONS_ASSEMBLY:
        WndAsmInspect( addr );
        break;
    case MENU_FUNCTIONS_BREAK:
        DlgBreak( addr );
        break;
    case MENU_FUNCTIONS_D2_ONLY:
        func->d2_only = !func->d2_only;
        FuncNewOptions( wnd );
        break;
    }
}


static WNDGETLINE FuncGetLine;
static  bool    FuncGetLine( a_window *wnd, int row, int piece,
                             wnd_line_piece *line )
{
    address     addr;
    func_window *func = WndFunc( wnd );

    if( row >= NameListNumRows( NameList( func ) ) ) return( FALSE );
    addr = NameListAddr( NameList( func ), row );
    switch( piece ) {
    case PIECE_BREAK:
        FileBreakGadget( wnd, line, FALSE, FindBreak( addr ) );
        return( TRUE );
    case PIECE_NAME:
        line->indent = MaxGadgetLength;
        line->text = TxtBuff;
        line->extent = WND_MAX_EXTEND;
        FuncGetSourceName( wnd, row );
        return( TRUE );
    case PIECE_DEMANGLED:
        if( NameListName( NameList( func ), row, TxtBuff, SN_DEMANGLED ) == 0 ) {
            return( FALSE );
        }
        line->text = TxtBuff;
        line->use_prev_attr = TRUE;
        line->indent = MaxGadgetLength + func->max_name + 2 * WndAvgCharX( wnd );
        return( TRUE );
    default:
        return( FALSE );
    }
}

extern  void    FuncNewMod( a_window *wnd, mod_handle mod )
{
    if( WndFunc( wnd )->mod == mod ) return;
    FuncNoMod( wnd );
    FuncSetMod( wnd, mod );
    WndZapped( wnd );
}


static WNDREFRESH FuncRefresh;
static void FuncRefresh( a_window *wnd )
{
    func_window *func = WndFunc( wnd );
    mod_handle  mod;

    if( WndFlags & UP_SYM_CHANGE ) {
        if( func->global ) {
            FuncNewMod( wnd, func->mod );
        } else if( DeAliasAddrMod( GetCodeDot(), &mod ) == SR_NONE ) {
            FuncNoMod( wnd );
        } else {
            FuncNewMod( wnd, mod );
        }
    } else if( ( WndFlags & UP_CODE_ADDR_CHANGE ) && !func->global ) {
        if( DeAliasAddrMod( GetCodeDot(), &mod ) == SR_NONE ) {
            FuncNoMod( wnd );
        } else {
            FuncNewMod( wnd, mod );
        }
    } else if( WndFlags & UP_BREAK_CHANGE ) {
        if( func->toggled_break ) {
            func->toggled_break = FALSE;
        } else {
            WndRepaint( wnd );
        }
    }
}

static void FuncSetOptions( a_window *wnd )
{
    func_window *func = WndFunc( wnd );

    func->d2_only = func->global && _IsOn( SW_FUNC_D2_ONLY );
    FuncNewOptions( wnd );
}

static WNDCALLBACK FuncEventProc;
static bool FuncEventProc( a_window * wnd, gui_event gui_ev, void *parm )
{
    func_window *func = WndFunc( wnd );

    parm=parm;
    switch( gui_ev ) {
    case GUI_INIT_WINDOW:
        NameListInit( NameList( func ), WF_CODE );
        func->toggled_break = FALSE;
        FuncSetOptions( wnd );
        WndSetKey( wnd, PIECE_NAME );
        return( TRUE );
    case GUI_RESIZE :
        CalcIndent( wnd );
        WndZapped( wnd );
        break;
    case GUI_DESTROY :
        NameListFree( NameList( func ) );
        WndFree( func );
        return( TRUE );
    }
    return( FALSE );
}

void FuncChangeOptions( void )
{
    WndForAllClass( WND_GBLFUNCTIONS, FuncSetOptions );
}

wnd_info FuncInfo = {
    FuncEventProc,
    FuncRefresh,
    FuncGetLine,
    FuncMenuItem,
    NoScroll,
    NoBegPaint,
    NoEndPaint,
    FuncModify,
    FuncNumRows,
    NoNextRow,
    NoNotify,
    UP_SYM_CHANGE+UP_BREAK_CHANGE+UP_CODE_ADDR_CHANGE,
    DefPopUp( FuncMenu )
};

extern a_window *DoWndFuncOpen( bool global, mod_handle mod )
{
    func_window *func;
    wnd_class   class;
    char        *name;

    func = WndMustAlloc( sizeof( func_window ) );
    func->mod = mod;
    if( global ) {
        class = WND_GBLFUNCTIONS;
        func->global = TRUE;
    } else {
        class = WND_FUNCTIONS;
        func->global = FALSE;
    }
    if( global ) {
        name = LIT( WindowGlobal_Functions );
    } else {
        name = LIT( WindowFunctions );
    }
    return( DbgWndCreate( name, &FuncInfo, class, func, &FuncIcon ) );
}

extern WNDOPEN WndFuncOpen;
extern a_window *WndFuncOpen( void )
{
    return( DoWndFuncOpen( FALSE, NO_MOD ) );
}

extern WNDOPEN WndGblFuncOpen;
extern a_window *WndGblFuncOpen( void )
{
    return( DoWndFuncOpen( TRUE, NO_MOD ) );
}

⌨️ 快捷键说明

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