filefn.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,984 行 · 第 1/4 页
CPP
1,984 行
/////////////////////////////////////////////////////////////////////////////
// Name: filefn.cpp
// Purpose: File- and directory-related functions
// Author: Julian Smart
// Modified by:
// Created: 29/01/98
// RCS-ID: $Id: filefn.cpp,v 1.249.2.5 2006/02/27 15:16:37 VZ Exp $
// Copyright: (c) 1998 Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "filefn.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#include "wx/defs.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/utils.h"
#include "wx/intl.h"
#include "wx/file.h" // This does include filefn.h
#include "wx/filename.h"
#include "wx/dir.h"
// there are just too many of those...
#ifdef __VISUALC__
#pragma warning(disable:4706) // assignment within conditional expression
#endif // VC++
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(__WATCOMC__)
#if !(defined(_MSC_VER) && (_MSC_VER > 800))
#include <errno.h>
#endif
#endif
#if defined(__WXMAC__)
#include "wx/mac/private.h" // includes mac headers
#endif
#include "wx/log.h"
#ifdef __WINDOWS__
#include "wx/msw/private.h"
#include "wx/msw/mslu.h"
// sys/cygwin.h is needed for cygwin_conv_to_full_win32_path()
//
// note that it must be included after <windows.h>
#ifdef __GNUWIN32__
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
#endif // __GNUWIN32__
// io.h is needed for _get_osfhandle()
// Already included by filefn.h for many Windows compilers
#if defined __MWERKS__ || defined __CYGWIN__
#include <io.h>
#endif
#endif // __WINDOWS__
#if defined(__VMS__)
#include <fab.h>
#endif
// TODO: Borland probably has _wgetcwd as well?
#ifdef _MSC_VER
#define HAVE_WGETCWD
#endif
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
#ifndef _MAXPATHLEN
#define _MAXPATHLEN 1024
#endif
#ifdef __WXMAC__
# include "MoreFilesX.h"
#endif
// ----------------------------------------------------------------------------
// private globals
// ----------------------------------------------------------------------------
// MT-FIXME: get rid of this horror and all code using it
static wxChar wxFileFunctionsBuffer[4*_MAXPATHLEN];
#if defined(__VISAGECPP__) && __IBMCPP__ >= 400
//
// VisualAge C++ V4.0 cannot have any external linkage const decs
// in headers included by more than one primary source
//
const int wxInvalidOffset = -1;
#endif
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
// we need to translate Mac filenames before passing them to OS functions
#define OS_FILENAME(s) (s.fn_str())
// ============================================================================
// implementation
// ============================================================================
#ifdef wxNEED_WX_UNISTD_H
WXDLLEXPORT int wxStat( const wxChar *file_name, wxStructStat *buf )
{
return stat( wxConvFile.cWX2MB( file_name ), buf );
}
WXDLLEXPORT int wxAccess( const wxChar *pathname, int mode )
{
return access( wxConvFile.cWX2MB( pathname ), mode );
}
WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode )
{
return open( wxConvFile.cWX2MB( pathname ), flags, mode );
}
#endif
// wxNEED_WX_UNISTD_H
// ----------------------------------------------------------------------------
// wxPathList
// ----------------------------------------------------------------------------
// IMPLEMENT_DYNAMIC_CLASS(wxPathList, wxStringList)
static inline wxChar* MYcopystring(const wxString& s)
{
wxChar* copy = new wxChar[s.length() + 1];
return wxStrcpy(copy, s.c_str());
}
static inline wxChar* MYcopystring(const wxChar* s)
{
wxChar* copy = new wxChar[wxStrlen(s) + 1];
return wxStrcpy(copy, s);
}
void wxPathList::Add (const wxString& path)
{
wxStringList::Add (WXSTRINGCAST path);
}
// Add paths e.g. from the PATH environment variable
void wxPathList::AddEnvList (const wxString& WXUNUSED_IN_WINCE(envVariable))
{
// No environment variables on WinCE
#ifndef __WXWINCE__
static const wxChar PATH_TOKS[] =
#if defined(__WINDOWS__) || defined(__OS2__)
/*
The space has been removed from the tokenizers, otherwise a
path such as "C:\Program Files" would be split into 2 paths:
"C:\Program" and "Files"
*/
// wxT(" ;"); // Don't separate with colon in DOS (used for drive)
wxT(";"); // Don't separate with colon in DOS (used for drive)
#else
wxT(" :;");
#endif
wxString val ;
if (wxGetEnv (WXSTRINGCAST envVariable, &val))
{
wxChar *s = MYcopystring (val);
wxChar *save_ptr, *token = wxStrtok (s, PATH_TOKS, &save_ptr);
if (token)
{
Add(token);
while (token)
{
if ( (token = wxStrtok ((wxChar *) NULL, PATH_TOKS, &save_ptr))
!= NULL )
{
Add(token);
}
}
}
// suppress warning about unused variable save_ptr when wxStrtok() is a
// macro which throws away its third argument
save_ptr = token;
delete [] s;
}
#endif // !__WXWINCE__
}
// Given a full filename (with path), ensure that that file can
// be accessed again USING FILENAME ONLY by adding the path
// to the list if not already there.
void wxPathList::EnsureFileAccessible (const wxString& path)
{
wxString path_only(wxPathOnly(path));
if ( !path_only.empty() )
{
if ( !Member(path_only) )
Add(path_only);
}
}
bool wxPathList::Member (const wxString& path)
{
for (wxStringList::compatibility_iterator node = GetFirst(); node; node = node->GetNext())
{
wxString path2( node->GetData() );
if (
#if defined(__WINDOWS__) || defined(__OS2__) || defined(__VMS__) || defined(__WXMAC__)
// Case INDEPENDENT
path.CompareTo (path2, wxString::ignoreCase) == 0
#else
// Case sensitive File System
path.CompareTo (path2) == 0
#endif
)
return true;
}
return false;
}
wxString wxPathList::FindValidPath (const wxString& file)
{
if (wxFileExists (wxExpandPath(wxFileFunctionsBuffer, file)))
return wxString(wxFileFunctionsBuffer);
wxChar buf[_MAXPATHLEN];
wxStrcpy(buf, wxFileFunctionsBuffer);
wxChar *filename = wxIsAbsolutePath (buf) ? wxFileNameFromPath (buf) : (wxChar *)buf;
for (wxStringList::compatibility_iterator node = GetFirst(); node; node = node->GetNext())
{
const wxString path(node->GetData());
wxStrcpy (wxFileFunctionsBuffer, path);
wxChar ch = wxFileFunctionsBuffer[wxStrlen(wxFileFunctionsBuffer)-1];
if (ch != wxT('\\') && ch != wxT('/'))
wxStrcat (wxFileFunctionsBuffer, wxT("/"));
wxStrcat (wxFileFunctionsBuffer, filename);
#ifdef __WINDOWS__
wxUnix2DosFilename (wxFileFunctionsBuffer);
#endif
if (wxFileExists (wxFileFunctionsBuffer))
{
return wxString(wxFileFunctionsBuffer); // Found!
}
} // for()
return wxEmptyString; // Not found
}
wxString wxPathList::FindAbsoluteValidPath (const wxString& file)
{
wxString f = FindValidPath(file);
if ( f.empty() || wxIsAbsolutePath(f) )
return f;
wxString buf;
wxGetWorkingDirectory(wxStringBuffer(buf, _MAXPATHLEN), _MAXPATHLEN);
if ( !wxEndsWithPathSeparator(buf) )
{
buf += wxFILE_SEP_PATH;
}
buf += f;
return buf;
}
bool
wxFileExists (const wxString& filename)
{
#if defined(__WXPALMOS__)
return false;
#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
// we must use GetFileAttributes() instead of the ANSI C functions because
// it can cope with network (UNC) paths unlike them
DWORD ret = ::GetFileAttributes(filename);
return (ret != (DWORD)-1) && !(ret & FILE_ATTRIBUTE_DIRECTORY);
#else // !__WIN32__
wxStructStat st;
#ifndef wxNEED_WX_UNISTD_H
return (wxStat( filename.fn_str() , &st) == 0 && (st.st_mode & S_IFREG))
#ifdef __OS2__
|| (errno == EACCES) // if access is denied something with that name
// exists and is opened in exclusive mode.
#endif
;
#else
return wxStat( filename , &st) == 0 && (st.st_mode & S_IFREG);
#endif
#endif // __WIN32__/!__WIN32__
}
bool
wxIsAbsolutePath (const wxString& filename)
{
if (!filename.empty())
{
#if defined(__WXMAC__) && !defined(__DARWIN__)
// Classic or Carbon CodeWarrior like
// Carbon with Apple DevTools is Unix like
// This seems wrong to me, but there is no fix. since
// "MacOS:MyText.txt" is absolute whereas "MyDir:MyText.txt"
// is not. Or maybe ":MyDir:MyText.txt" has to be used? RR.
if (filename.Find(':') != wxNOT_FOUND && filename[0] != ':')
return true ;
#else
// Unix like or Windows
if (filename[0] == wxT('/'))
return true;
#endif
#ifdef __VMS__
if ((filename[0] == wxT('[') && filename[1] != wxT('.')))
return true;
#endif
#if defined(__WINDOWS__) || defined(__OS2__)
// MSDOS like
if (filename[0] == wxT('\\') || (wxIsalpha (filename[0]) && filename[1] == wxT(':')))
return true;
#endif
}
return false ;
}
/*
* Strip off any extension (dot something) from end of file,
* IF one exists. Inserts zero into buffer.
*
*/
void wxStripExtension(wxChar *buffer)
{
int len = wxStrlen(buffer);
int i = len-1;
while (i > 0)
{
if (buffer[i] == wxT('.'))
{
buffer[i] = 0;
break;
}
i --;
}
}
void wxStripExtension(wxString& buffer)
{
//RN: Be careful about the handling the case where
//buffer.Length() == 0
for(size_t i = buffer.Length() - 1; i != wxString::npos; --i)
{
if (buffer.GetChar(i) == wxT('.'))
{
buffer = buffer.Left(i);
break;
}
}
}
// Destructive removal of /./ and /../ stuff
wxChar *wxRealPath (wxChar *path)
{
#ifdef __WXMSW__
static const wxChar SEP = wxT('\\');
wxUnix2DosFilename(path);
#else
static const wxChar SEP = wxT('/');
#endif
if (path[0] && path[1]) {
/* MATTHEW: special case "/./x" */
wxChar *p;
if (path[2] == SEP && path[1] == wxT('.'))
p = &path[0];
else
p = &path[2];
for (; *p; p++)
{
if (*p == SEP)
{
if (p[1] == wxT('.') && p[2] == wxT('.') && (p[3] == SEP || p[3] == wxT('\0')))
{
wxChar *q;
for (q = p - 1; q >= path && *q != SEP; q--)
{
// Empty
}
if (q[0] == SEP && (q[1] != wxT('.') || q[2] != wxT('.') || q[3] != SEP)
&& (q - 1 <= path || q[-1] != SEP))
{
wxStrcpy (q, p + 3);
if (path[0] == wxT('\0'))
{
path[0] = SEP;
path[1] = wxT('\0');
}
#if defined(__WXMSW__) || defined(__OS2__)
/* Check that path[2] is NULL! */
else if (path[1] == wxT(':') && !path[2])
{
path[2] = SEP;
path[3] = wxT('\0');
}
#endif
p = q - 1;
}
}
else if (p[1] == wxT('.') && (p[2] == SEP || p[2] == wxT('\0')))
wxStrcpy (p, p + 2);
}
}
}
return path;
}
// Must be destroyed
wxChar *wxCopyAbsolutePath(const wxString& filename)
{
if (filename.empty())
return (wxChar *) NULL;
if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) {
wxChar buf[_MAXPATHLEN];
buf[0] = wxT('\0');
wxGetWorkingDirectory(buf, WXSIZEOF(buf));
wxChar ch = buf[wxStrlen(buf) - 1];
#ifdef __WXMSW__
if (ch != wxT('\\') && ch != wxT('/'))
wxStrcat(buf, wxT("\\"));
#else
if (ch != wxT('/'))
wxStrcat(buf, wxT("/"));
#endif
wxStrcat(buf, wxFileFunctionsBuffer);
return MYcopystring( wxRealPath(buf) );
}
return MYcopystring( wxFileFunctionsBuffer );
}
/*-
Handles:
~/ => home dir
~user/ => user's home dir
If the environment variable a = "foo" and b = "bar" then:
Unix:
$a => foo
$a$b => foobar
$a.c => foo.c
xxx$a => xxxfoo
${a}! => foo!
$(b)! => bar!
\$a => \$a
MSDOS:
$a ==> $a
$(a) ==> foo
$(a)$b ==> foo$b
$(a)$(b)==> foobar
test.$$ ==> test.$$
*/
/* input name in name, pathname output to buf. */
wxChar *wxExpandPath(wxChar *buf, const wxChar *name)
{
register wxChar *d, *s, *nm;
wxChar lnm[_MAXPATHLEN];
int q;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?