/////////////////////////////////////////////////////////////////////////////
-// Name: chm.cpp
+// Name: src/html/chm.cpp
// Purpose: CHM (Help) support for wxHTML
// Author: Markus Sinner
// Copyright: (c) 2003 Herd Software Development
// CVS-ID: $Id$
-// Licence: wxWindows Licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifdef __BORLANDC__
-#pragma hdrstop
+ #pragma hdrstop
#endif
#if wxUSE_LIBMSPACK
#include <mspack.h>
-#ifndef WXPRECOMP
-#include "wx/intl.h"
-#include "wx/log.h"
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/module.h"
#endif
-#include "wx/module.h"
#include "wx/filesys.h"
#include "wx/mstream.h"
#include "wx/wfstream.h"
/// check archive for a file
bool Contains(const wxString& pattern);
- /// get a string for the last error occured
+ /// get a string for the last error which occurred
const wxString GetLastErrorMessage();
/// Last Error
{
m_chmFileName = archive.GetFullPath();
- wxASSERT_MSG( !m_chmFileName.empty(), _T("empty archive name") );
+ wxASSERT_MSG( !m_chmFileName.empty(), wxT("empty archive name") );
m_archive = NULL;
m_decompressor = NULL;
// strdup() [libmspack-20030726], which would cause crashes in
// Unicode build when mb_str() returns temporary buffer
m_chmFileNameANSI = strdup((const char*)m_chmFileName.mb_str(wxConvFile));
-
+
// Open the archive and store it in class:
if ( (chmh = chmd->open(chmd, (char*)m_chmFileNameANSI)) )
{
*
* Finds the next file descibed by a pattern in the archive, starting
* the file given by second parameter
- *
+ *
* @param pattern The file-pattern to search for. May contain '*' and/or '?'
* @param startfrom The filename which the search should start after
* @returns The full pathname of the found file
wxChmInputStream(const wxString& archive,
const wxString& file, bool simulate = false);
/// Destructor
- ~wxChmInputStream();
+ virtual ~wxChmInputStream();
/// Return the size of the accessed file in archive
virtual size_t GetSize() const { return m_size; }
/// See wxInputStream
virtual size_t OnSysRead(void *buffer, size_t bufsize);
/// See wxInputStream
- virtual off_t OnSysSeek(off_t seek, wxSeekMode mode);
+ virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
/// See wxInputStream
- virtual off_t OnSysTell() const { return m_pos; }
+ virtual wxFileOffset OnSysTell() const { return m_pos; }
private:
size_t m_size;
- off_t m_pos;
+ wxFileOffset m_pos;
bool m_simulateHHP;
char * m_content;
* be local file accesible via fopen, fread functions!
* @param filename The Name of the file to be extracted from archive
* @param simulate if true than class should simulate .HHP-File based on #SYSTEM
- * if false than class does nothing if it doesnt find .hhp
+ * if false than class does nothing if it doesn't find .hhp
*/
wxChmInputStream::wxChmInputStream(const wxString& archive,
const wxString& filename, bool simulate)
// if the file could not be located, but was *.hhp, than we create
// the content of the hhp-file on the fly and store it for reading
// by the application
- if ( m_fileName.Find(_T(".hhp")) != wxNOT_FOUND && m_simulateHHP )
+ if ( m_fileName.Find(wxT(".hhp")) != wxNOT_FOUND && m_simulateHHP )
{
// now we open an hhp-file
CreateHHPStream();
m_lasterror = wxSTREAM_NO_ERROR;
// If the rest to read from the stream is less
- // than the buffer size, than only read the rest
+ // than the buffer size, then only read the rest
if ( m_pos + bufsize > m_size )
bufsize = m_size - m_pos;
- m_contentStream->SeekI(m_pos);
- m_contentStream->Read(buffer, bufsize);
- m_pos +=bufsize;
- m_contentStream->SeekI(m_pos);
- return bufsize;
+ if (m_contentStream->SeekI(m_pos) == wxInvalidOffset)
+ {
+ m_lasterror = wxSTREAM_EOF;
+ return 0;
+ }
+
+ size_t read = m_contentStream->Read(buffer, bufsize).LastRead();
+ m_pos += read;
+
+ if (m_contentStream->SeekI(m_pos) == wxInvalidOffset)
+ {
+ m_lasterror = wxSTREAM_READ_ERROR;
+ return 0;
+ }
+
+ if (read != bufsize)
+ m_lasterror = m_contentStream->GetLastError();
+
+ return read;
}
-off_t wxChmInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
+wxFileOffset wxChmInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
{
wxString mode_str = wxEmptyString;
}
m_lasterror = wxSTREAM_NO_ERROR;
- off_t nextpos;
+ wxFileOffset nextpos;
switch ( mode )
{
/**
* Help Browser tries to read the contents of the
* file by interpreting a .hhp file in the Archiv.
- * For .chm doesnt include such a file, we need
+ * For .chm doesn't include such a file, we need
* to rebuild the information based on stored
* system-files.
*/
wxChmInputStream::CreateHHPStream()
{
wxFileName file;
- bool topic = false;
bool hhc = false;
bool hhk = false;
wxInputStream *i;
const char *tmp;
// Try to open the #SYSTEM-File and create the HHP File out of it
- // see http://bonedaddy.net/pabs3/chmspec/0.1/ch05s03.html#SYSTEM
- if ( ! m_chm->Contains(_("/#SYSTEM")) )
+ // see http://bonedaddy.net/pabs3/chmspec/0.1.2/Internal.html#SYSTEM
+ if ( ! m_chm->Contains(wxT("/#SYSTEM")) )
{
#ifdef DEBUG
- wxLogDebug("Archive doesnt contain #SYSTEM file");
+ wxLogDebug("Archive doesn't contain #SYSTEM file");
#endif
return;
}
else
{
- file = wxFileName(_T("/#SYSTEM"));
+ file = wxFileName(wxT("/#SYSTEM"));
}
- if ( CreateFileStream(_T("/#SYSTEM")) )
+ if ( CreateFileStream(wxT("/#SYSTEM")) )
{
// New stream for writing a memory area to simulate the
// .hhp-file
{
// Read #SYSTEM-Code and length
i->Read(&code, 2);
+ code = wxUINT16_SWAP_ON_BE( code ) ;
i->Read(&len, 2);
+ len = wxUINT16_SWAP_ON_BE( len ) ;
// data
buf = malloc(len);
i->Read(buf, len);
switch (code)
{
case 0: // CONTENTS_FILE
- tmp = "Contents file=";
- hhc=true;
+ if (len)
+ {
+ tmp = "Contents file=";
+ hhc=true;
+ }
break;
case 1: // INDEX_FILE
tmp = "Index file=";
break;
case 2: // DEFAULT_TOPIC
tmp = "Default Topic=";
- topic = true;
break;
case 3: // TITLE
tmp = "Title=";
out->Write( (const void *) tmp, strlen(tmp));
tmp = NULL;
break;
- case 4: // STRUCT
+ case 4: // STRUCT SYSTEM INFO
+ tmp = NULL ;
+ if ( len >= 28 )
+ {
+ char *structptr = (char*) buf ;
+ // LCID at position 0
+ wxUint32 dummy = *((wxUint32 *)(structptr+0)) ;
+ wxUint32 lcid = wxUINT32_SWAP_ON_BE( dummy ) ;
+ char msg[64];
+ int len = sprintf(msg, "Language=0x%X\r\n", lcid) ;
+ if (len > 0)
+ out->Write(msg, len) ;
+ }
+ break ;
default:
tmp=NULL;
}
free (m_content);
// Now add entries which are missing
- if ( !hhc && m_chm->Contains(_T("*.hhc")) )
+ if ( !hhc && m_chm->Contains(wxT("*.hhc")) )
{
tmp = "Contents File=*.hhc\r\n";
out->Write((const void *) tmp, strlen(tmp));
}
- if ( !hhk && m_chm->Contains(_T("*.hhk")) )
+ if ( !hhk && m_chm->Contains(wxT("*.hhk")) )
{
tmp = "Index File=*.hhk\r\n";
out->Write((const void *) tmp, strlen(tmp));
bool wxChmInputStream::CreateFileStream(const wxString& pattern)
{
wxFileInputStream * fin;
- wxString tmpfile = wxFileName::CreateTempFileName(_T("chmstrm"), NULL);
+ wxString tmpfile = wxFileName::CreateTempFileName(wxT("chmstrm"));
if ( tmpfile.empty() )
{
{
// Open a filestream to extracted file
fin = new wxFileInputStream(tmpfile);
+ if (!fin->IsOk())
+ return false;
+
m_size = fin->GetSize();
m_content = (char *) malloc(m_size+1);
fin->Read(m_content, m_size);
public:
/// Constructor and Destructor
wxChmFSHandler();
- ~wxChmFSHandler();
+ virtual ~wxChmFSHandler();
/// Is able to open location?
virtual bool CanOpen(const wxString& location);
/// Open a file
virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);
- /// Find first occurence of spec
+ /// Find first occurrence of spec
virtual wxString FindFirst(const wxString& spec, int flags = 0);
- /// Find next occurence of spec
+ /// Find next occurrence of spec
virtual wxString FindNext();
private:
bool wxChmFSHandler::CanOpen(const wxString& location)
{
wxString p = GetProtocol(location);
- return (p == _T("chm")) &&
- (GetProtocol(GetLeftLocation(location)) == _T("file"));
+ return (p == wxT("chm")) &&
+ (GetProtocol(GetLeftLocation(location)) == wxT("file"));
}
wxFSFile* wxChmFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs),
int index;
- if ( GetProtocol(left) != _T("file") )
+ if ( GetProtocol(left) != wxT("file") )
{
wxLogError(_("CHM handler currently supports only local files!"));
return NULL;
// Work around javascript
wxString tmp = wxString(right);
- if ( tmp.MakeLower().Contains(_T("javascipt")) && tmp.Contains(_T("\'")) )
+ if ( tmp.MakeLower().Contains(wxT("javascipt")) && tmp.Contains(wxT("\'")) )
{
- right = right.AfterFirst(_T('\'')).BeforeLast(_T('\''));
+ right = right.AfterFirst(wxT('\'')).BeforeLast(wxT('\''));
}
// now work on the right location
- if (right.Contains(_T("..")))
+ if (right.Contains(wxT("..")))
{
wxFileName abs(right);
- abs.MakeAbsolute(_T("/"));
+ abs.MakeAbsolute(wxT("/"));
right = abs.GetFullPath();
}
// a workaround for absolute links to root
- if ( (index=right.Index(_T("//"))) != wxNOT_FOUND )
+ if ( (index=right.Index(wxT("//"))) != wxNOT_FOUND )
{
right=wxString(right.Mid(index+1));
wxLogWarning(_("Link contained '//', converted to absolute link."));
}
wxFileName leftFilename = wxFileSystem::URLToFileName(left);
+ if (!leftFilename.FileExists())
+ return NULL;
// Open a stream to read the content of the chm-file
s = new wxChmInputStream(leftFilename.GetFullPath(), right, true);
- wxString mime = GetMimeTypeFromExt(location);
-
if ( s )
{
return new wxFSFile(s,
- left + _T("#chm:") + right,
- mime,
+ left + wxT("#chm:") + right,
+ wxEmptyString,
GetAnchor(location),
- wxDateTime(wxFileModificationTime(left)));
+ wxDateTime(leftFilename.GetModificationTime()));
}
delete s;
wxString left = GetLeftLocation(spec);
wxString nativename = wxFileSystem::URLToFileName(left).GetFullPath();
- if ( GetProtocol(left) != _T("file") )
+ if ( GetProtocol(left) != wxT("file") )
{
wxLogError(_("CHM handler currently supports only local files!"));
return wxEmptyString;
}
m_chm = new wxChmTools(wxFileName(nativename));
- m_pattern = right.AfterLast(_T('/'));
+ m_pattern = right.AfterLast(wxT('/'));
wxString m_found = m_chm->Find(m_pattern);
// now fake around hhp-files which are not existing in projects...
if (m_found.empty() &&
- m_pattern.Contains(_T(".hhp")) &&
- !m_pattern.Contains(_T(".hhp.cached")))
+ m_pattern.Contains(wxT(".hhp")) &&
+ !m_pattern.Contains(wxT(".hhp.cached")))
{
- m_found.Printf(_T("%s#chm:%s.hhp"),
- left.c_str(), m_pattern.BeforeLast(_T('.')).c_str());
+ m_found.Printf(wxT("%s#chm:%s.hhp"),
+ left.c_str(), m_pattern.BeforeLast(wxT('.')).c_str());
}
return m_found;