/* Copyright (C) 2003 Razvan Cojocaru 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include /*---------------------------------------------------------------------- * class CHMInputStream static members */ CHMFile *CHMInputStream::_archiveCache = NULL; wxString CHMInputStream::_path; void CHMInputStream::Cleanup() { if(_archiveCache != NULL) { delete _archiveCache; _archiveCache = NULL; } } CHMFile* CHMInputStream::GetCache() { return _archiveCache; } /*---------------------------------------------------------------------- * rest of class CHMInputStream implementation */ CHMInputStream::CHMInputStream(const wxString& archive, const wxString& file) : _currPos(0) { wxString filename = file; if(!archive.IsEmpty()) _path = archive.BeforeLast(wxT('/')) + wxT("/"); memset(&_ui, 0, sizeof(_ui)); // Maybe the cached chmFile* isn't valid anymore, // or maybe there is no chached chmFile* yet. if(!archive.IsEmpty() && !Init(archive)) { m_lasterror = wxSTREAM_READ_ERROR; return; } // Somebody's looking for the homepage. if(file.IsSameAs(wxT("/"))) filename = _archiveCache->HomePage(); if(!filename.Left(8).CmpNoCase(wxT("/MS-ITS:"))) { // If this ever happens chances are Microsoft // decided that even if we went through the // trouble to open this archive and check out // the index file, the index file is just a // link to a file in another archive. wxString arch_link = filename.AfterFirst(wxT(':')).BeforeFirst(wxT(':')); filename = filename.AfterLast(wxT(':')); // Reset the cached chmFile* and all. if(!Init(arch_link)) if(!Init(_path + arch_link)) { m_lasterror = wxSTREAM_READ_ERROR; return; } } assert(_archiveCache != NULL); // See if the file really is in the archive. if(!_archiveCache->ResolveObject(filename, &_ui)) { m_lasterror = wxSTREAM_READ_ERROR; return; } } size_t CHMInputStream::GetSize() const { return _ui.length; } bool CHMInputStream::Eof() const { return _currPos >= (off_t)_ui.length; } size_t CHMInputStream::OnSysRead(void *buffer, size_t bufsize) { if(_currPos >= (off_t)_ui.length) { m_lasterror = wxSTREAM_EOF; return 0; } if(!_archiveCache) return 0; if(_currPos + bufsize > (off_t)_ui.length) bufsize = _ui.length - _currPos; bufsize = _archiveCache->RetrieveObject(&_ui, (unsigned char *)buffer, _currPos, bufsize); _currPos += bufsize; return bufsize; } #ifdef __WXMSW__ wxFileOffset CHMInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) #else off_t CHMInputStream::OnSysSeek(off_t seek, wxSeekMode mode) #endif { switch(mode) { case wxFromCurrent: _currPos += seek; break; case wxFromStart: _currPos = seek; break; case wxFromEnd: _currPos = _ui.length - 1 + seek; break; default: _currPos = seek; } return _currPos; } bool CHMInputStream::Init(const wxString& archive) { if(_archiveCache == NULL || !_archiveCache->ArchiveName().IsSameAs(archive)) { Cleanup(); _archiveCache = new CHMFile(archive); if(!_archiveCache->IsOk()) { Cleanup(); return false; } } return true; } /* Local Variables: mode: c++ c-basic-offset: 8 tab-width: 8 c-indent-comments-syntactically-p: t c-tab-always-indent: t indent-tabs-mode: t End: */ // vim:shiftwidth=8:autoindent:tabstop=8:noexpandtab:softtabstop=8