/* * Copyright (C) 2002,2003,2004,2005 Daniel Heck * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * 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. * */ #include "file.hh" #include "enigma.hh" #include "video.hh" #include "main.hh" #include "ecl_system.hh" #include "config.h" #include #ifdef HAVE_DIRENT_H #include #endif #include #include #include #include using namespace enigma; using namespace ecl; using namespace std; DirIter::DirIter() {} DirIter::~DirIter() {} namespace { /* -------------------- DirIter (POSIX) -------------------- */ #ifdef HAVE_DIRENT_H class DirIterOS : DirIter { public: DirIterOS (const std::string &path) : m_dir (NULL), m_entry (NULL) { open (path); dir_path = path; } virtual ~DirIterOS () { if (m_dir != NULL) closedir (m_dir); } virtual bool open (const std::string &path) { m_dir = opendir (path.c_str()); return m_dir != 0; } virtual bool get_next (DirEntry &entry) { if (m_dir == 0) return false; m_entry = readdir(m_dir); if (m_entry != NULL) { entry.name = m_entry->d_name; // entry.is_dir = false; entry.is_dir = ecl::FolderExists(dir_path + "/" + entry.name); return true; } return false; } private: std::string dir_path; DIR *m_dir; struct dirent *m_entry; }; /* -------------------- DirIter (Win32) -------------------- */ #elif defined (_MSC_VER) #include class DirIterOS : DirIter { public: DirIterOS (const std::string &path) : m_handle (INVALID_HANDLE_VALUE) { open (path); } ~DirIterOS () { close(); } bool open (const std::string &path) { std::string glob (path); glob += "\\*.*"; m_handle = FindFirstFile (glob.c_str(), &m_dir); return m_handle != INVALID_HANDLE_VALUE; } bool get_next (DirEntry &entry) { if (m_handle != INVALID_HANDLE_VALUE) { entry.name = m_dir.cFileName; // entry.is_dir = false; entry.is_dir = m_dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; if (!FindNextFile (m_handle, &m_dir)) close(); return true; } return false; } private: void close () { if (m_handle != INVALID_HANDLE_VALUE) { FindClose (m_handle); m_handle = INVALID_HANDLE_VALUE; } } // Variables. WIN32_FIND_DATA m_dir; HANDLE m_handle; }; #endif } DirIter * DirIter::instance(const std::string &path) { return reinterpret_cast(new DirIterOS(path)); } /* -------------------- FileHandle_Dir -------------------- */ // // FileHandle_Dir::FileHandle_Dir (const std::string &name) // : m_name (name) // { // } // // bool FileHandle_Dir::exists() const // { // return true; // } // // void FileHandle_Dir::read (ByteVec &buffer) // { // std::ifstream ifs(m_name.c_str()); // enigma::readfile (ifs, buffer); // } // /* -------------------- GameFS implementation -------------------- */ GameFS::GameFS() : entries () { } void GameFS::append_dir (const string &path) { std::string full_path = ecl::ExpandPath (path); entries.push_back (FSEntry (FS_DIRECTORY, full_path)); } void GameFS::prepend_dir (const string &path) { std::string full_path = ecl::ExpandPath (path); entries.insert (entries.begin(), FSEntry (FS_DIRECTORY, full_path)); } void GameFS::prepend_zip (const std::string &filename) { std::string path = ecl::ExpandPath (filename); entries.insert (entries.begin(), FSEntry (FS_ZIPFILE, path)); } void GameFS::setDataPath (const string &p) { clear(); std::vector datapaths; split_copy (p, *ecl::PathsSeparator, back_inserter(datapaths)); for (unsigned i=0; i0) path += ecl::PathsSeparator; path += e.location; } return path; } std::vector GameFS::getPaths() { std::vector paths; for (unsigned i=0, size=entries.size(); i < size; ++i) { const FSEntry &e = entries[i]; paths.push_back(e.location); } return paths; } bool GameFS::findFile (const string &filename, string &dest) const { for (unsigned i=0; i &isresult) const { std::string::size_type slpos = filename.rfind('/'); std::string zipName; std::string zippedFilename1, zippedFilename2; bool searchZip = false; std::string complete_name; if (slpos != std::string::npos) { // file may be zipped - for "levels/Sokoban/mic_60.xml" we will look for // "mic_60.xml" and "Sokoban/mic_60.xml" at "levels/Sokoban.zip" searchZip = true; zipName = filename.substr(0, slpos) + ".zip"; zippedFilename1 = filename.substr(slpos + 1); std::string::size_type slpos2 = filename.rfind('/', slpos-1); zippedFilename2 = filename.substr(slpos2 + 1); } for (unsigned i=0; i GameFS::findSubfolderFiles(const string &folder, const string &filename) const { std::list matches; for (unsigned i=0; igfxdir) + basename; if (!findFile(fname, filename)) { fname = string ("gfx/") + basename; return findFile(fname, filename); } return true; } /* -------------------- Helper functions -------------------- */ std::istream & enigma::Readfile (std::istream &is, ByteVec &dest, int blocksize) { size_t len = dest.size(); int nread=0; do { dest.resize(dest.size() + blocksize); is.read (&dest[len], blocksize); nread = is.gcount(); len += nread; } while (nread == blocksize); dest.resize(len); return is; } bool enigma::Copyfile(std::string fromPath, std::string toPath) { ByteVec content; ifstream ifs(fromPath.c_str(), ios::binary | ios::in); Readfile (ifs, content); ofstream ofs(toPath.c_str(), ios::binary | ios::out); ofs.write(&content[0], content.size()); ofs.close(); return !ofs.fail(); }