2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
#include "Engine/StdH.h"
|
2016-03-11 14:57:17 +01:00
|
|
|
#include <Engine/Base/Stream.h>
|
|
|
|
#include <Engine/Base/FileName.h>
|
|
|
|
#include <Engine/Base/Unzip.h>
|
2016-03-29 03:03:54 +02:00
|
|
|
#include <Engine/Base/FileSystem.h>
|
2016-03-11 14:57:17 +01:00
|
|
|
#include <Engine/Templates/DynamicStackArray.cpp>
|
|
|
|
|
|
|
|
extern CDynamicStackArray<CTFileName> _afnmBaseBrowseInc;
|
|
|
|
extern CDynamicStackArray<CTFileName> _afnmBaseBrowseExc;
|
|
|
|
|
|
|
|
class CDirToRead {
|
|
|
|
public:
|
|
|
|
CListNode dr_lnNode;
|
|
|
|
CTString dr_strDir;
|
|
|
|
};
|
|
|
|
|
|
|
|
int qsort_CompareCTFileName(const void *elem1, const void *elem2 )
|
|
|
|
{
|
|
|
|
const CTFileName &fnm1 = **(CTFileName **)elem1;
|
|
|
|
const CTFileName &fnm2 = **(CTFileName **)elem2;
|
|
|
|
return strcmp(fnm1, fnm2);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern BOOL FileMatchesList(CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnm);
|
|
|
|
|
|
|
|
void FillDirList_internal(const CTFileName &fnmBasePath,
|
|
|
|
CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnmDir, const CTString &strPattern, BOOL bRecursive,
|
|
|
|
CDynamicStackArray<CTFileName> *pafnmInclude, CDynamicStackArray<CTFileName> *pafnmExclude)
|
|
|
|
{
|
|
|
|
// add the directory to list of directories to search
|
|
|
|
CListHead lhDirs;
|
|
|
|
CDirToRead *pdrFirst = new CDirToRead;
|
|
|
|
pdrFirst->dr_strDir = fnmDir;
|
|
|
|
lhDirs.AddTail(pdrFirst->dr_lnNode);
|
|
|
|
|
|
|
|
// while the list of directories is not empty
|
|
|
|
while (!lhDirs.IsEmpty()) {
|
|
|
|
// take the first one
|
|
|
|
CDirToRead *pdr = LIST_HEAD(lhDirs, CDirToRead, dr_lnNode);
|
|
|
|
CTFileName fnmDir = pdr->dr_strDir;
|
|
|
|
delete pdr;
|
|
|
|
|
|
|
|
// if the dir is not allowed
|
|
|
|
if (pafnmInclude!=NULL &&
|
|
|
|
(!FileMatchesList(*pafnmInclude, fnmDir) || FileMatchesList(*pafnmExclude, fnmDir)) ) {
|
|
|
|
// skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-03-29 03:03:54 +02:00
|
|
|
const char *dirsep = CFileSystem::GetDirSeparator();
|
|
|
|
|
2016-03-11 14:57:17 +01:00
|
|
|
// start listing the directory
|
2016-03-29 03:03:54 +02:00
|
|
|
CDynamicArray<CTString> *files;
|
|
|
|
files = _pFileSystem->FindFiles(fnmBasePath+fnmDir, "*");
|
|
|
|
int max = files->Count();
|
|
|
|
|
2016-03-11 14:57:17 +01:00
|
|
|
// for each file in the directory
|
2016-03-29 03:03:54 +02:00
|
|
|
for (int i = 0; i < max; i++) {
|
|
|
|
const char *fname = (*files)[i];
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
// if dummy dir (this dir, parent dir, or any dir starting with '.')
|
2016-03-29 03:03:54 +02:00
|
|
|
if (_pFileSystem->IsDummyFile(fname)) {
|
2016-03-11 14:57:17 +01:00
|
|
|
// skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the file's filepath
|
2016-03-29 03:03:54 +02:00
|
|
|
CTFileName fnm = fnmDir + fname;
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
// if it is a directory
|
2016-03-29 03:03:54 +02:00
|
|
|
if (_pFileSystem->IsDirectory(fnm)) {
|
2016-03-11 14:57:17 +01:00
|
|
|
// if recursive reading
|
|
|
|
if (bRecursive) {
|
|
|
|
// add it to the list of directories to search
|
|
|
|
CDirToRead *pdrNew = new CDirToRead;
|
2016-03-29 03:03:54 +02:00
|
|
|
pdrNew->dr_strDir = fnm + dirsep;
|
2016-03-11 14:57:17 +01:00
|
|
|
lhDirs.AddTail(pdrNew->dr_lnNode);
|
|
|
|
}
|
|
|
|
// if it matches the pattern
|
|
|
|
} else if (strPattern=="" || fnm.Matches(strPattern)) {
|
|
|
|
// add that file
|
|
|
|
afnm.Push() = fnm;
|
|
|
|
}
|
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
|
|
|
|
delete files;
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// make a list of all files in a directory
|
|
|
|
ENGINE_API void MakeDirList(
|
2016-03-29 03:03:54 +02:00
|
|
|
CDynamicStackArray<CTFileName> &afnmDir, const CTFileName &fnmDir, const CTFileName &fnmPattern, ULONG ulFlags)
|
2016-03-11 14:57:17 +01:00
|
|
|
{
|
|
|
|
afnmDir.PopAll();
|
|
|
|
BOOL bRecursive = ulFlags&DLI_RECURSIVE;
|
|
|
|
BOOL bSearchCD = ulFlags&DLI_SEARCHCD;
|
|
|
|
|
|
|
|
// make one temporary array
|
|
|
|
CDynamicStackArray<CTFileName> afnm;
|
|
|
|
|
|
|
|
if (_fnmMod!="") {
|
2016-03-29 03:03:54 +02:00
|
|
|
FillDirList_internal(_fnmUserDir, afnm, fnmDir, fnmPattern, bRecursive,
|
|
|
|
&_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
|
|
|
|
FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, fnmPattern, bRecursive,
|
2016-03-11 14:57:17 +01:00
|
|
|
&_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
|
|
|
|
if (bSearchCD) {
|
2016-03-29 03:03:54 +02:00
|
|
|
FillDirList_internal(_fnmCDPath, afnm, fnmDir, fnmPattern, bRecursive,
|
2016-03-11 14:57:17 +01:00
|
|
|
&_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
|
|
|
|
}
|
2016-03-29 03:03:54 +02:00
|
|
|
FillDirList_internal(_fnmUserDir+_fnmMod, afnm, fnmDir, fnmPattern, bRecursive, NULL, NULL);
|
|
|
|
FillDirList_internal(_fnmApplicationPath+_fnmMod, afnm, fnmDir, fnmPattern, bRecursive, NULL, NULL);
|
2016-03-11 14:57:17 +01:00
|
|
|
} else {
|
2016-03-29 03:03:54 +02:00
|
|
|
FillDirList_internal(_fnmUserDir, afnm, fnmDir, fnmPattern, bRecursive, NULL, NULL);
|
|
|
|
FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, fnmPattern, bRecursive, NULL, NULL);
|
2016-03-11 14:57:17 +01:00
|
|
|
if (bSearchCD) {
|
2016-03-29 03:03:54 +02:00
|
|
|
FillDirList_internal(_fnmCDPath, afnm, fnmDir, fnmPattern, bRecursive, NULL, NULL);
|
2016-03-11 14:57:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for each file in zip archives
|
|
|
|
CTString strDirPattern = fnmDir;
|
|
|
|
INDEX ctFilesInZips = UNZIPGetFileCount();
|
|
|
|
for(INDEX iFileInZip=0; iFileInZip<ctFilesInZips; iFileInZip++) {
|
|
|
|
const CTFileName &fnm = UNZIPGetFileAtIndex(iFileInZip);
|
|
|
|
|
|
|
|
// if not in this dir, skip it
|
|
|
|
if (bRecursive) {
|
|
|
|
if (!fnm.HasPrefix(strDirPattern)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (fnm.FileDir()!=fnmDir) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if doesn't match pattern
|
2016-03-29 03:03:54 +02:00
|
|
|
if (fnmPattern!="" && !fnm.Matches(fnmPattern)) {
|
2016-03-11 14:57:17 +01:00
|
|
|
// skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if mod is active, and the file is not in mod
|
|
|
|
if (_fnmMod!="" && !UNZIPIsFileAtIndexMod(iFileInZip)) {
|
|
|
|
// if it doesn't match base browse path
|
|
|
|
if ( !FileMatchesList(_afnmBaseBrowseInc, fnm) || FileMatchesList(_afnmBaseBrowseExc, fnm) ) {
|
|
|
|
// skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add that file
|
|
|
|
afnm.Push() = fnm;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if no files
|
|
|
|
if (afnm.Count()==0) {
|
|
|
|
// don't check for duplicates
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// resort the array
|
|
|
|
qsort(afnm.da_Pointers, afnm.Count(), sizeof(void*), qsort_CompareCTFileName);
|
|
|
|
|
|
|
|
// for each file
|
|
|
|
INDEX ctFiles = afnm.Count();
|
|
|
|
for (INDEX iFile=0; iFile<ctFiles; iFile++) {
|
|
|
|
// if not same as last one
|
|
|
|
if (iFile==0 || afnm[iFile]!=afnm[iFile-1]) {
|
|
|
|
// copy over to final array
|
|
|
|
afnmDir.Push() = afnm[iFile];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|