vfilelst.cpp

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

CPP
443
字号
/****************************************************************************
*
*                            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: Standard open/close dialog support.
*
****************************************************************************/

/* TODO: This file is mostly specific to MS Windows.  We need to make a
 * platform neutral version and move the contents to the correct platform
 * specific directories.
 */

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <sys/stat.h>
#include <io.h>
#include <direct.h>
#ifdef __WINDOWS__
#include <commdlg.h>
#endif
#include "getfile.h"
#include "malloc.h"
#include "win1632.h"
#include "wstring.hpp"
#include "wstrlist.hpp"
#include "wfilenam.hpp"
#include "wwindow.hpp"

typedef struct {
    WString     *result;
    const char  *tgt_file;
} GetFilesInfo;

static DWORD getMaxItemLen( HWND lb ) {
    DWORD       cnt;
    DWORD       len;
    DWORD       rc;
    WPARAM      i;

    cnt = SendMessage( lb, LB_GETCOUNT, 0, 0 );
    len = 0;
    for( i=0; i < cnt; i++ ) {
        rc = SendMessage( lb, LB_GETTEXTLEN, i, 0 );
        if( rc > len ) len = rc;
    }
    return( len );
}

static void checkRemoveButton( HWND hwnd ) {
    HWND        ctl;
    DWORD       item;

    ctl = GetDlgItem( hwnd, FOD_FILELIST );
    item = SendMessage( ctl, LB_GETCURSEL, 0, 0 );
    if( item == LB_ERR ) {
        ctl = GetDlgItem( hwnd, FOD_REMOVE );
        EnableWindow( ctl, FALSE );
    } else {
        ctl = GetDlgItem( hwnd, FOD_REMOVE );
        EnableWindow( ctl, TRUE );
    }
}

static void getFullFname( HWND hwnd, const char *fname, WString *fullname ) {
    unsigned    len;
    char        buf[_MAX_PATH];
    char        drive[ _MAX_DRIVE ];

    drive[0] = '\0';
    _splitpath( fname, drive, NULL, NULL, NULL );
    if( drive[0] == '\0' ) {
        hwnd = hwnd;
        getcwd( buf, _MAX_PATH );
        *fullname = buf;
        len = strlen( buf );
        if( buf[ len-1 ] != '\\' ) fullname->concat( "\\" );
    }
    fullname->concat( fname );
}

static void formRelDir( const char *filedir, const char *tgtdir,WString *dir )
{
    const char          *tgt_bs;        //location of last found backslash
    const char          *file_bs;

    tgt_bs = tgtdir;
    file_bs = filedir;
    // get rid of identical prefix directories
    for( ;; ) {
        if( tolower( *filedir ) != tolower( *tgtdir ) ) {
            filedir = file_bs;
            tgtdir = tgt_bs;
            break;
        }
        if( *filedir == '\0' ) {
            break;
        } else if( *filedir == '\\' ) {
            tgt_bs = tgtdir;
            file_bs = filedir;
        }
        filedir++;
        tgtdir++;
    }
    *dir = "";
    for( ;; ) {
        while( *tgtdir == '\\' ) tgtdir++;
        if( *tgtdir != '\\' && *tgtdir != '\0' ) {
            while( *tgtdir != '\\' && *tgtdir != '\0' ) tgtdir++;
            dir->concat( "..\\" );
        }
        if( *tgtdir == '\0' ) break;
    }
    if( *filedir != '\0' ) dir->concat( filedir + 1 );
}

static void getRelFname( HWND hwnd, const char *fname, WString *relname ) {
    WString              fullpath;
    GetFilesInfo        *info;
    WFileName            tgt;
    WFileName            filename;
    char                 drive[ _MAX_DRIVE ];
    char                 dir[ _MAX_DIR ];

    info = (GetFilesInfo *)GetWindowLong( hwnd, DWL_USER );
    getFullFname( hwnd, fname, &fullpath );
    filename = fullpath.gets();
    _splitpath( info->tgt_file, drive, dir, NULL, NULL );
    if( !stricmp( drive, filename.drive() ) ) {
        formRelDir( filename.dir(), dir, relname );
        relname->concat( filename.fName() );
        relname->concat( filename.ext() );
    } else {
        *relname = fullpath.gets();
    }
}


static DWORD findMatchingFile( HWND hwnd, const char *fname ) {
    DWORD       rc;
    WString     fullname;
    HWND        lb;

    getFullFname( hwnd, fname, &fullname );
    lb = GetDlgItem( hwnd, FOD_FILELIST );
//    fullname.toLower();
    rc = SendMessage( lb, LB_FINDSTRINGEXACT, -1,
                      (LPARAM)(LPSTR)fullname.gets() );
    if( rc == LB_ERR ) {
        getRelFname( hwnd, fname, &fullname );
//        fullname.toLower();
        rc = SendMessage( lb, LB_FINDSTRINGEXACT, -1,
                          (LPARAM)(LPSTR)fullname.gets() );
    }
    return( rc );
}

static void addFileToList( HWND hwnd, char *fname ) {
    HWND        ctl;
    DWORD       item;
    DWORD       match;
    WFileName   fullname;
    bool        isLong = FALSE;

    int len = strlen( fname )-1;
    if( fname[0] == '"' && fname[len] == '"' ) {
        fname++;
        fname[len-1] = '\0';
        isLong = TRUE;
    } else {
        WFileName filename( fname );
        isLong = filename.needQuotes();
    }

    match = findMatchingFile( hwnd, fname );
    ctl = GetDlgItem( hwnd, FOD_FILELIST );
    if( match == LB_ERR ) {
        if( IsDlgButtonChecked( hwnd, FOD_STORE_ABSOLUTE ) ) {
            getFullFname( hwnd, fname, &fullname );
        } else {
            getRelFname( hwnd, fname, &fullname );
        }
//        fullname.toLower();
        if( isLong ) {
            fullname.addQuotes();
        }
        item = SendMessage( ctl, LB_ADDSTRING, 0,
                            (LPARAM)(LPSTR)fullname.gets() );
    } else {
        item = match;
    }
    SendMessage( ctl, LB_SETCURSEL, (WPARAM)item, 0 );
    checkRemoveButton( hwnd );
}

static void addCurrentFile( HWND hwnd  ) {
    char        *fname;
    int          len;
    HWND         ctl;
    struct stat  buf;

    ctl = GetDlgItem( hwnd, FOD_FILENAME );
    len = GetWindowTextLength( ctl );
    if( len == 0 ) return;
    fname = (char *)alloca( len + 1 );
    GetWindowText( ctl, fname, len + 1 );
    if( fname[ strlen( fname ) - 1 ] == '\\' ) return;
    stat( fname, &buf );
    if( S_ISDIR( buf.st_mode ) ) return;
    if( strpbrk( fname, "?*" ) != NULL ) return;
    addFileToList( hwnd, fname );
    SetWindowText( ctl, "" );
}

static void addAllFiles( HWND hwnd ) {
    HWND         ctl;
    LRESULT      cnt;
    char        *buf;
    unsigned     alloced;
    LRESULT      len;
    WPARAM       i;

    alloced = 512;
    buf = new char [alloced];

    ctl = GetDlgItem( hwnd, FOD_FILES );
    cnt = SendMessage( ctl, LB_GETCOUNT, 0, 0 );
    for( i=0; i < cnt; i++ ) {
        len = SendMessage( ctl, LB_GETTEXTLEN, i, 0 );
        len ++;
        if( len > alloced ) {
            delete buf;
            buf = new char [len];
        }
        SendMessage( ctl, LB_GETTEXT, i, (LPARAM)(LPSTR)buf );
        addFileToList( hwnd, buf );
    }
    free( buf );
}

void GetResults( HWND hwnd ) {
    char                *buf;
    DWORD               cnt;
    WPARAM              i;
    DWORD               len;
    HWND                lb;
    GetFilesInfo        *info;

    info = (GetFilesInfo *)GetWindowLong( hwnd, DWL_USER );
    lb = GetDlgItem( hwnd, FOD_FILELIST );
    len = getMaxItemLen( lb );
    buf = (char *)alloca( (size_t)( len + 1 ) );
    *info->result = "";
    cnt = SendMessage( lb, LB_GETCOUNT, 0, 0 );
    for( i=0; i < cnt; i++ ) {
        SendMessage( lb, LB_GETTEXT, i, (LPARAM)(LPSTR)buf );
        info->result->concat( buf );
        info->result->concat( " " );
    }
}

void initFileList( HWND hwnd ) {
    HWND                lb;
    GetFilesInfo        *info;

    info = (GetFilesInfo *)GetWindowLong( hwnd, DWL_USER );
    lb = GetDlgItem( hwnd, FOD_FILELIST );
    if( *info->result != "" ) {
        WStringList names( *info->result );
        for( ; names.count() > 0; ) {
            SendMessage( lb, LB_ADDSTRING, 0,
                         (LPARAM)(LPSTR)names.cStringAt( 0 ) );
            names.removeAt( 0 );
        }
    }
}

void doClose( HWND hwnd )
{
    HWND         ctl;

    ctl = GetDlgItem( hwnd, FOD_FILENAME );
    SetWindowText( ctl, "x_it_dlg.now" );
}

UINT CALLBACK AddSrcDlgProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
    WORD        cmd;
    LRESULT     item;
    DWORD       rc;
    HWND        ctl;

    lparam = lparam;
    switch( msg ) {
    case WM_INITDIALOG:
        {
            OPENFILENAME        *of;

            ctl = GetDlgItem( hwnd, FOD_REMOVE );
            EnableWindow( ctl, FALSE );
            ctl = GetDlgItem( hwnd, IDOK );
            EnableWindow( ctl, FALSE );
            of = (OPENFILENAME *)lparam;
            SetWindowLong( hwnd, DWL_USER, of->lCustData );
            initFileList( hwnd );
        }
        break;
    case WM_COMMAND:
        cmd = LOWORD( wparam );
        switch( cmd ) {
        case FOD_FILES:
            if( GET_WM_COMMAND_CMD( wparam, lparam ) == LBN_DBLCLK ) {
                addCurrentFile( hwnd );
                return( TRUE );
            } else {
                return( FALSE );
            }
        case IDOK:
            return( FALSE );
        case FOD_ADD:
            addCurrentFile( hwnd );
            PostMessage( hwnd, WM_COMMAND, IDOK, 0 );
            return( TRUE );
        case FOD_ADDALL:
            addAllFiles( hwnd );
            break;
        case FOD_REMOVE:
            ctl = GetDlgItem( hwnd, FOD_FILELIST );
            item = SendMessage( ctl, LB_GETCURSEL, 0, 0 );
            if( item != LB_ERR ) {
                rc = SendMessage( ctl, LB_DELETESTRING, (WPARAM)item, 0 );
                if( item != 0 ) {
                    SendMessage( ctl, LB_SETCURSEL, (WPARAM)(item-1), 0 );
                } else {
                    SendMessage( ctl, LB_SETCURSEL, (WPARAM)item, 0 );
                }
            }
            checkRemoveButton( hwnd );
            break;
        case FOD_FILELIST:
            if( GET_WM_COMMAND_CMD( wparam, lparam ) == LBN_SELCHANGE ||
                GET_WM_COMMAND_CMD( wparam, lparam ) == LBN_SELCANCEL ) {
                checkRemoveButton( hwnd );
            }
            break;
        case FOD_CLOSE:
            GetResults( hwnd );
            doClose( hwnd );
            PostMessage( hwnd, WM_COMMAND, IDOK, 0 );
            return( TRUE );
        default:
            return( FALSE );
        }
        break;
    default:
        return( FALSE );
    }
    return( TRUE );
}

static BOOL fileSelectDlg( HINSTANCE hinst, HWND parent, GetFilesInfo *info,
                    const char *caption, const char *filters  )
{
    static DWORD        last_filter_index = 1L;
    OPENFILENAME        of;
    int                 rc;
    char                fname[256];
    char                 drive[ _MAX_DRIVE ];
    char                 dir[ _MAX_DIR ];
    char                 newpath[ _MAX_PATH ];

    _splitpath( info->tgt_file, drive, dir, NULL, NULL );
    _makepath( newpath, drive, dir, NULL, NULL );

    typedef UINT    (CALLBACK *CallbackFnType)(HWND, UINT, WPARAM, LPARAM);


    fname[ 0 ] = 0;
    memset( &of, 0, sizeof( OPENFILENAME ) );
    of.lStructSize = sizeof( OPENFILENAME );
    of.hwndOwner = parent;
    of.hInstance = hinst;
    of.lpstrFilter = (LPSTR) filters;
    of.lpstrDefExt = "";
    of.nFilterIndex = last_filter_index;
    of.lpstrFile = fname;
    of.nMaxFile = _MAX_PATH;
    of.lpstrTitle = caption;
    of.Flags = OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
    #ifdef __WINDOWS__
        of.lpfnHook = (CallbackFnType)MakeProcInstance( (FARPROC)AddSrcDlgProc, hinst );
    #else
        of.lpfnHook = AddSrcDlgProc;
    #endif
    of.lpTemplateName = "ADD_SRC_DLG";
    of.lCustData = (DWORD)info;
    of.lpstrInitialDir = newpath;
    rc = GetOpenFileName( &of );
    last_filter_index = of.nFilterIndex;
    return( rc );
}

int GetNewFiles( WWindow *parent, WString *results, const char *caption,
                 const char *filters, const char *tgt_file )
{
    HWND                owner;
    HINSTANCE           hinst;
    GetFilesInfo        info;

    // this is a grody kludge to get an HWND from a gui_window
    // it assumes that the HWND is the first field in the gui_window structure
    owner = *( (HWND *)(parent->handle() ) );
    hinst = (HINSTANCE)GET_HINSTANCE( owner );
    info.result = results;
    info.tgt_file = tgt_file;
    return( fileSelectDlg( hinst, owner, &info, caption, filters ) );
}


⌨️ 快捷键说明

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