vcompon.cpp

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

CPP
895
字号
/****************************************************************************
*
*                            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:  Class definition for project files window.
*
****************************************************************************/


#include "vpemain.hpp"
#include "vcompon.hpp"
#include "wpshbttn.hpp"
#include "wtext.hpp"
#include "wmenuitm.hpp"
#include "maction.hpp"
#include "winpdlg.hpp"
#include "wpickdlg.hpp"
#include "weditdlg.hpp"
#include "wmsgdlg.hpp"
#include "wobjfile.hpp"
#include "wstrlist.hpp"
#include "mrule.hpp"
#include "mconfig.hpp"
#include "vsetup.hpp"
#include "vcompdlg.hpp"
#include "mitem.hpp"
#ifndef __OS2__
#include "vfilelst.hpp"
#endif

#include "whotpbox.hpp"

extern "C" {
    #include <dos.h>
    #include <objautod.h>
    #include "rcdefs.h"
    #include <autodep.h>
//  #include <wressetr.h>
    #include <direct.h>
};

extern char _viperError[];
extern char _viperRequest[];

Define( VComponent )

enum  w_style {
    W_NORMAL,
    W_MINIMIZED,
    W_MAXIMIZED
};

VComponent::VComponent( VpeMain* parent, MComponent* comp, WStyle style )
//  : WMdiChild( parent, "", style )
    : WMdiChild( parent, "", style & ~WStyleMaximize )
    , WView( comp )
    , _parent( parent )
    , _component( comp )
    , _vItems( NULL )
{
    initCtor();
}

VComponent::VComponent( VpeMain* parent, const WRect& r, MComponent* comp, WStyle style )
//  : WMdiChild( parent, r, "", style )
    : WMdiChild( parent, r, "", style & ~WStyleMaximize )
    , WView( comp )
    , _parent( parent )
    , _component( comp )
    , _vItems( NULL )
{
    initCtor();
}

void VComponent::initCtor()
{
    setIcon( I_Target );

    int box_h = getTextExtentY( "X" );
    int xindent = getTextExtentX( "X" ); /* / 2; Val became too small with new font RR */
    int yindent = getTextExtentY( "X" ) / 2;

    int off = yindent; /* 5; RR */
    _tBox = new WText( this, WRect( xindent, off, -xindent, box_h ), "" );
    _tBox->show();
    off += box_h + box_h/2;

    #define _SourceTitle "Source files:"
    int title_h = getTextExtentY( _SourceTitle );
    _vTitle = new WText( this, WRect( xindent, off, -xindent, title_h ), _SourceTitle );
    _vTitle->show();
    off += title_h + title_h/2;

    _vItems = new WHotPickBox( _component->items(), (cbs)&MItem::name, (icb)&MItem::type,
                  (bcb)&MItem::included, this, WRect(xindent, off, -xindent, -yindent),
                  &_parent->hotSpotList() );
    _vItems->show();

    createControls();

    updateView();

    _parent->setActive( this );

    resetPopups();

    _vItems->onDblClick( this, (cbw)&VComponent::dblClicked );
    _vItems->onHotPress( this, (cbw)&VComponent::expandItem );
    show();
    setFocus();
}

VComponent::~VComponent()
{
    setPopup( NULL );
    _vItems->setPopup( NULL );
    delete _vItems;
    _parent->setActive( NULL );
}

#ifndef NOPERSIST

VComponent* WEXPORT VComponent::createSelf( WObjectFile& p )
{
    WRect r; p.readObject( &r );
#if 1   //this can be removed when WRect is upgraded to handle legitimate
        //negative coordinates
    if( r.x() < 0 ) r.x( 0 );
    if( r.y() < 0 ) r.y( 0 );
#endif
    if( p.version() < 36 ) {
        r.w( (WOrdinal)((long)r.w()*10240/640) );
        r.h( (WOrdinal)((long)r.h()*10240/480) );
    }
    WStyle style = WStyleDefault;
    char wState = W_NORMAL;
    p.readObject( &wState );
    switch( wState ) {
        case W_MINIMIZED:
            style |= WStyleMinimize;
            break;
        case W_MAXIMIZED:
            style |= WStyleMaximize;
            break;
    }
    VpeMain* parent = (VpeMain*)p.readObject();
    WFileName fn;
    p.readObject( &fn );
    MComponent* component = NULL;
    if( p.version() < 35 ) {
        component = parent->project()->findOldComponent( fn );
    } else {
        component = parent->project()->findComponent( fn );
    }
    if( !component ) {
        WMessageDialog::messagef( parent, MsgError, MsgOk, _viperError,
            "Unable to locate target '%s'", (const char*)fn );
        //this isn't great but it will do (I think!)
        component = new MComponent( parent->project(),
            _config->nilRule(), "", fn );
    }
    return new VComponent( parent, r, component, style );
}

void WEXPORT VComponent::readSelf( WObjectFile& p )
{
    int top;
    p.readObject( &top );
    _vItems->setTopIndex( top );
    int sel;
    p.readObject( &sel );
    _vItems->select( sel );
    update();
}

void WEXPORT VComponent::writeSelf( WObjectFile& p )
{
    WRect r; getNormalRectangle( r );
    p.writeObject( &r, FORCE );
    char wState = W_NORMAL;
    if( isMinimized() ) wState = W_MINIMIZED;
    if( isMaximized() ) wState = W_MAXIMIZED;
    p.writeObject( wState );
    p.writeObject( _parent );
    WFileName tgt( _component->relFilename() );
    p.writeObject( &tgt, FORCE );
    p.writeObject( _vItems->topIndex() );
    p.writeObject( _vItems->selected() );
}
#endif

bool VComponent::keyDown( WKeyCode kc, WKeyState ks )
{
    if( !WMdiChild::keyDown( kc, ks ) ) {
        return( _vItems->keyDown( kc, ks ) );
    } else {
        return( TRUE );
    }
}

// forward notification to the child control
bool VComponent::scrollNotify( WScrollNotification sn, int diff )
{
    return( _vItems->scrollNotify( sn, diff ) );
}

void VComponent::resetPopups()
{
    setPopup( _parent->targetPopup() );
    _vItems->setPopup( _parent->itemsPopup() );
}

void VComponent::createControls()
{
    _controls.deleteContents();

    WVList actlist;
    target()->addActions( actlist );
    int icount = actlist.count();

    int BW = 0;
    int BH = 0;
    int i;
    for( i=0; i<icount; i++ ) {
        MAction* action = (MAction*)actlist[i];
        if( action->button() ) {
            WString text;
            action->name( text );
            int bw = getTextExtentX( text );
            int bh = getTextExtentY( text );
            if( BW < bw ) BW = bw;
            if( BH < bh ) BH = bh;
        }
    }

    int xindent = getTextExtentX( "X" ) / 2;
    int yindent = getTextExtentY( "X" ) / 2;

    int off = BH + yindent;
    for( i=0; i<icount; i++ ) {
        MAction* action = (MAction*)actlist[i];
        if( action->button() ) {
            WString text;
            action->name( text );
            WPushButton* bAction =
                new WPushButton( this, WRect(-BW-xindent, off, BW, BH), text );
            bAction->setTagPtr( action );
            off += BH+BH/2;
            bAction->onClick( this, (cbw)&VComponent::bActionComponent );
            int accelKey = action->accelKey();
            if( accelKey ) {
//              bAction->addAccelerator( accelKey );
            }
            bAction->show();
            _controls.add( bAction );
        }
    }

    WRect r = _vItems->getAutosize();
    if( _controls.count() > 0 ) {
        r.w( -BW-xindent );
    } else {
        r.w( -xindent );
    }
    _vItems->move( r );
}

bool VComponent::okToInclude( MItem* item, bool warn, MItem* dupitem )
{
    if( !item->legal() ) {
        if( warn ) {
            WMessageDialog::messagef( this, MsgError, MsgOk, _viperError,
                                      "'%s' must be a legal filename",
                                      (const char*)*item );
        }
        return FALSE;
    }
    WFileName fullName( *item ); fullName.absoluteTo( _component->filename() );
    WFileName fullTarget; target()->absName( fullTarget );
    if( fullName.match( fullTarget, matchAll ) ) {
        if( warn ) {
            WMessageDialog::messagef( this, MsgError, MsgOk, _viperError,
                                      "'%s' cannot include itself",
                                      (const char*)*item );
        }
        return FALSE;
    }
    MComponent* comp = NULL;
    MItem* m = _parent->project()->findSameResult( item, &comp );
    if( m && dupitem != m ) {
        if( warn ) {
            WMessageDialog::messagef( this, MsgError, MsgOk, _viperError,
                                "Conflicting file '%s' found in target '%s'",
                                (const char*)*m, (const char*)*comp->target() );
        }
        return FALSE;
    }
    return TRUE;
}

bool VComponent::newItem( WFileName& fn, bool warn, bool mark, unsigned owner )
{
    if( fn.size() > 0 ) {
        WFileName cwd;
        _component->filename().path( cwd, TRUE );
        int len = cwd.size();
        if( len > 0 ) {
            if( strnicmp( cwd, fn, len ) == 0 ) {
                fn.chop( len );
            }
        }
    }
    MRule* rule = _config->findMatchingRule( fn, target()->rule(),
                      _component->mask() );
    if( rule ) {
        MItem* item = new MItem( fn, _component, rule );
        if( okToInclude( item, warn ) ) {
            _component->newItem( item );
            _vItems->selectSameTag( item );
            if( mark ) {
                item->setVisited( TRUE );
                item->setOwner( owner );
            }
            return TRUE;
        }
        delete item;    //added to fix memory leak!
    }
    return FALSE;
}

void VComponent::mAddItem( WMenuItem* )
{
    WString h; h.printf( "Add File(s) to '%s'", (const char*)*target() );
    bool        list_was_empty;
    WString     inp;
    bool        rc;
#ifndef __OS2__
    int         ret;
#else
    WInputDialog add( this, h );
    add.setBrowse( _config->fileFilters(), TRUE );
#endif

    list_was_empty = FALSE;
    if( _component->items().count() == 0 ) list_was_empty = TRUE;
    for( ;; ) {
#ifdef __OS2__
        rc = add.getInput( inp, "Enter filename(s) separated by spaces:" );
#else
        ret = GetNewFiles( this, &inp, h, _config->fileFilters(),
                            _component->filename() );
        rc = (ret != 0);
#endif
        if( !rc ) break;
//        inp.toLower();
        WStringList names( inp );
        startWait();
        //someday change this to use addFromFilename() in mcompon.cpp
        bool done = FALSE;
        _component->setBatchMode();
        for( ; !done && names.count() > 0; ) {
            WFileName search( names.cStringAt( 0 ) );
            search.removeQuotes();
            if( search.isMask() ) {
                WFileName asearch( search );
                asearch.absoluteTo( _component->filename() );
                DIR* dir = opendir( asearch );
                if( !dir ) {
                    WMessageDialog::messagef( this, MsgError, MsgOk,
                        _viperError, "no files found for '%s'",
                        (const char*)search );
                    done = TRUE;
                } else {
                    for(;;) {
                        struct dirent* ent = readdir( dir );
                        if( !ent ) break;
                        WFileName fn( ent->d_name );
//                        fn.toLower();
                        fn.absoluteTo( asearch );
                        WVList& items = _component->items();
                        MItem* mm = NULL;
                        for( int j=0; j<items.count(); j++ ) {
                            mm = (MItem*)items[j];
                            WFileName ff; mm->absName( ff );
                            if( ff == fn ) break;
                            mm = NULL;
                        }
                        if( !mm ) {
                            WFileName newfile( ent->d_name );
                            newfile.setDrive( search.drive() );
                            newfile.setDir( search.dir() );
                            if( !newItem( newfile ) ) {
                                done = TRUE;
                                break;
                            }
                        }
                    }
                    closedir( dir );
                }
            } else {
                if( !newItem( search ) ) break;
            }
            names.removeAt( 0 );
        }
        _component->setBatchMode( FALSE );
        stopWait();
        if( names.count() == 0 ) break;
        inp = names.cString();
    }
    if( list_was_empty && _component->items().count() != 0 ) {
        _vItems->select( 0 );
    }
}

void VComponent::mRemoveItem( WMenuItem* )
{
    MItem* m = selectedItem();
    if( m ) {
        bool ok = TRUE;
        if( m->isMask() ) {
            ok = _parent->confirm( "Remove all '%s' files?", m->ext() );
        } else {
            ok = _parent->confirm( "Are you sure you wish to remove '%s'?", *m );
        }
        if( ok ) {
            _vItems->setSelected( _vItems->selected()-1 );

⌨️ 快捷键说明

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