Directory.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Base/Stream.h>
  14. #include <Engine/Base/FileName.h>
  15. #include <Engine/Base/Unzip.h>
  16. #include <Engine/Templates/DynamicStackArray.cpp>
  17. #include <io.h>
  18. extern CDynamicStackArray<CTFileName> _afnmBaseBrowseInc;
  19. extern CDynamicStackArray<CTFileName> _afnmBaseBrowseExc;
  20. class CDirToRead {
  21. public:
  22. CListNode dr_lnNode;
  23. CTString dr_strDir;
  24. };
  25. int qsort_CompareCTFileName(const void *elem1, const void *elem2 )
  26. {
  27. const CTFileName &fnm1 = **(CTFileName **)elem1;
  28. const CTFileName &fnm2 = **(CTFileName **)elem2;
  29. return strcmp(fnm1, fnm2);
  30. }
  31. extern BOOL FileMatchesList(CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnm);
  32. void FillDirList_internal(const CTFileName &fnmBasePath,
  33. CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnmDir, const CTString &strPattern, BOOL bRecursive,
  34. CDynamicStackArray<CTFileName> *pafnmInclude, CDynamicStackArray<CTFileName> *pafnmExclude)
  35. {
  36. // add the directory to list of directories to search
  37. CListHead lhDirs;
  38. CDirToRead *pdrFirst = new CDirToRead;
  39. pdrFirst->dr_strDir = fnmDir;
  40. lhDirs.AddTail(pdrFirst->dr_lnNode);
  41. // while the list of directories is not empty
  42. while (!lhDirs.IsEmpty()) {
  43. // take the first one
  44. CDirToRead *pdr = LIST_HEAD(lhDirs, CDirToRead, dr_lnNode);
  45. CTFileName fnmDir = pdr->dr_strDir;
  46. delete pdr;
  47. // if the dir is not allowed
  48. if (pafnmInclude!=NULL &&
  49. (!FileMatchesList(*pafnmInclude, fnmDir) || FileMatchesList(*pafnmExclude, fnmDir)) ) {
  50. // skip it
  51. continue;
  52. }
  53. // start listing the directory
  54. struct _finddata_t c_file; long hFile;
  55. hFile = _findfirst( (const char *)(fnmBasePath+fnmDir+"*"), &c_file );
  56. // for each file in the directory
  57. for (
  58. BOOL bFileExists = hFile!=-1;
  59. bFileExists;
  60. bFileExists = _findnext( hFile, &c_file )==0) {
  61. // if dummy dir (this dir, parent dir, or any dir starting with '.')
  62. if (c_file.name[0]=='.') {
  63. // skip it
  64. continue;
  65. }
  66. // get the file's filepath
  67. CTFileName fnm = fnmDir+c_file.name;
  68. // if it is a directory
  69. if (c_file.attrib&_A_SUBDIR) {
  70. // if recursive reading
  71. if (bRecursive) {
  72. // add it to the list of directories to search
  73. CDirToRead *pdrNew = new CDirToRead;
  74. pdrNew->dr_strDir = fnm+"\\";
  75. lhDirs.AddTail(pdrNew->dr_lnNode);
  76. }
  77. // if it matches the pattern
  78. } else if (strPattern=="" || fnm.Matches(strPattern)) {
  79. // add that file
  80. afnm.Push() = fnm;
  81. }
  82. }
  83. }
  84. }
  85. // make a list of all files in a directory
  86. ENGINE_API void MakeDirList(
  87. CDynamicStackArray<CTFileName> &afnmDir, const CTFileName &fnmDir, const CTString &strPattern, ULONG ulFlags)
  88. {
  89. afnmDir.PopAll();
  90. BOOL bRecursive = ulFlags&DLI_RECURSIVE;
  91. BOOL bSearchCD = ulFlags&DLI_SEARCHCD;
  92. // make one temporary array
  93. CDynamicStackArray<CTFileName> afnm;
  94. if (_fnmMod!="") {
  95. FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive,
  96. &_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
  97. if (bSearchCD) {
  98. FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive,
  99. &_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
  100. }
  101. FillDirList_internal(_fnmApplicationPath+_fnmMod, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
  102. } else {
  103. FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
  104. if (bSearchCD) {
  105. FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
  106. }
  107. }
  108. // for each file in zip archives
  109. CTString strDirPattern = fnmDir;
  110. INDEX ctFilesInZips = UNZIPGetFileCount();
  111. for(INDEX iFileInZip=0; iFileInZip<ctFilesInZips; iFileInZip++) {
  112. const CTFileName &fnm = UNZIPGetFileAtIndex(iFileInZip);
  113. // if not in this dir, skip it
  114. if (bRecursive) {
  115. if (!fnm.HasPrefix(strDirPattern)) {
  116. continue;
  117. }
  118. } else {
  119. if (fnm.FileDir()!=fnmDir) {
  120. continue;
  121. }
  122. }
  123. // if doesn't match pattern
  124. if (strPattern!="" && !fnm.Matches(strPattern)) {
  125. // skip it
  126. continue;
  127. }
  128. // if mod is active, and the file is not in mod
  129. if (_fnmMod!="" && !UNZIPIsFileAtIndexMod(iFileInZip)) {
  130. // if it doesn't match base browse path
  131. if ( !FileMatchesList(_afnmBaseBrowseInc, fnm) || FileMatchesList(_afnmBaseBrowseExc, fnm) ) {
  132. // skip it
  133. continue;
  134. }
  135. }
  136. // add that file
  137. afnm.Push() = fnm;
  138. }
  139. // if no files
  140. if (afnm.Count()==0) {
  141. // don't check for duplicates
  142. return;
  143. }
  144. // resort the array
  145. qsort(afnm.da_Pointers, afnm.Count(), sizeof(void*), qsort_CompareCTFileName);
  146. // for each file
  147. INDEX ctFiles = afnm.Count();
  148. for (INDEX iFile=0; iFile<ctFiles; iFile++) {
  149. // if not same as last one
  150. if (iFile==0 || afnm[iFile]!=afnm[iFile-1]) {
  151. // copy over to final array
  152. afnmDir.Push() = afnm[iFile];
  153. }
  154. }
  155. }