|
|
// TitleInfo.cpp : implementation file
//
//
// includes
//
#include "stdafx.h"
#include "titleinfo.h"
#include <locale.h>
#include <strsafe.h>
// constants
//
const char txtTopicsFile[] = "#TOPICS"; const char txtUrlTblFile[] = "#URLTBL"; const char txtUrlStrFile[] = "#URLSTR"; const char txtStringsFile[] = "#STRINGS"; const char txtMkStore[] = "ms-its:"; const char txtSepBack[] = "::/"; const char txtDoubleColonSep[] = "::";
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo Class
//
// This class provides the ability to retrieve topic titles and topic URLs
// from topic numbers from a CHM file (HTML Help title).
//
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo class constructor
//
CTitleInfo::CTitleInfo() { // init members
//
m_bOpen = FALSE; m_szTitlePath[0] = NULL; m_pUrlStrings = NULL; m_pTopics = NULL; m_pStrTbl = NULL; m_pUrlTbl = NULL; m_pTitleInfo = NULL; m_pCFileSystem = NULL; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo class destructor
//
CTitleInfo::~CTitleInfo() { // make sure the title was opened
//
if (!m_bOpen) return;
// close the subfiles
//
if (m_pUrlTbl) delete m_pUrlTbl;
if(m_pTopics) delete m_pTopics;
if(m_pStrTbl) delete m_pStrTbl;
if(m_pUrlStrings) delete m_pUrlStrings;
if(m_pTitleInfo) delete m_pTitleInfo;
// delete the mail filesystem
//
if(m_pCFileSystem) delete m_pCFileSystem;
// deinit the members
//
m_pUrlStrings = NULL; m_pTopics = NULL; m_pStrTbl = NULL; m_pUrlTbl = NULL;
// no longer open
//
m_bOpen = FALSE; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: OpenTitle method
//
// This funciton opens a help title
//
// Note: This method must be called before any other methods
//
// pwcTitlePath Path the help title (chm file)
//
BOOL CTitleInfo::OpenTitle(WCHAR *pwcTitlePath) { HRESULT hr;
// make sure we're not already open
//
if (m_bOpen) return TRUE;
WCHAR wcFullPath[_MAX_PATH]; WCHAR *pwcFilePart = NULL;
// get the full path to title
//
if(!GetFullPathNameW(pwcTitlePath, sizeof(wcFullPath)/sizeof(WCHAR), wcFullPath, &pwcFilePart)) return FALSE;
// create filesystem object
//
if (m_pCFileSystem) delete m_pCFileSystem; m_pCFileSystem = new CFileSystem(); if(!m_pCFileSystem) return FALSE;
hr = m_pCFileSystem->Init();
if(FAILED(hr)) { delete m_pCFileSystem; m_pCFileSystem = NULL; return FALSE; }
// open the CHM file
//
hr = m_pCFileSystem->Open(wcFullPath); if (FAILED(hr)) { delete m_pCFileSystem; m_pCFileSystem = NULL; return FALSE; }
if (m_pTitleInfo) delete m_pTitleInfo; m_pTitleInfo = new CTitleInformation(m_pCFileSystem);
if(!m_pTitleInfo) { delete m_pCFileSystem; m_pCFileSystem = NULL; return FALSE; }
// save the full path to the CHM (used when constructing URLs)
//
WideCharToMultiByte(CP_ACP, 0, wcFullPath, -1, m_szTitlePath, sizeof(m_szTitlePath), 0, 0);
// success!
//
m_bOpen = TRUE;
return TRUE; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetLocationName
//
// This function retrieves the location name of the CHM. This string is the
// friendly name for the CHM that appears in result lists.
//
// pwszLocationName Destination buffer for location name
// cch Size of pwszLocationName
//
HRESULT CTitleInfo::GetLocationName(WCHAR *pwszLocationName, int cch, UINT cp) { if(!pwszLocationName || !cch) return E_INVALIDARG;
if(m_pTitleInfo) { const CHAR* psz = NULL; psz = m_pTitleInfo->GetDefaultCaption(); if( !psz || !*psz ) psz = m_pTitleInfo->GetShortName(); if( psz && *psz ) { MultiByteToWideChar(cp, 0, psz, -1, pwszLocationName, cch); pwszLocationName[cch-1] = 0; return S_OK; } }
return E_FAIL; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicName
//
// This function retrieves a topic title from a topic number
//
// dwTopic Topic Number
// pwszTitle Destination buffer for topic title
// cch Size of pwszTitle
//
HRESULT CTitleInfo::GetTopicName(DWORD dwTopic, WCHAR* pwszTitle, int cch, UINT cp) { TOC_TOPIC topic; HRESULT hr; if (SUCCEEDED(hr = GetTopicData(dwTopic, &topic))) return GetString(topic.dwOffsTitle, pwszTitle, cch, cp); else return hr; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicURL
//
// This function retrieves a topic URL from a topic number
//
// dwTopic Topic Number
// pwszURL Destination buffer for URL
// cch Size of pwcURL
//
HRESULT CTitleInfo::GetTopicURL(DWORD dwTopic, CHAR* pwszURL, int cch) { TOC_TOPIC topic; HRESULT hr; CHAR* psz;
if (m_bOpen == FALSE) return E_FAIL;
if (!m_pUrlTbl) { m_pUrlTbl = new CPagedSubfile; if(!m_pUrlTbl) return E_FAIL; if (FAILED(hr = m_pUrlTbl->Open(this, txtUrlTblFile))) { delete m_pUrlTbl; m_pUrlTbl = NULL; return hr; } } if (!m_pUrlStrings) { m_pUrlStrings = new CPagedSubfile; if(!m_pUrlStrings) return E_FAIL; if (FAILED(hr = m_pUrlStrings->Open(this, txtUrlStrFile))) { delete m_pUrlStrings; m_pUrlStrings = NULL; return hr; } } if ( (hr = GetTopicData(dwTopic, &topic)) == S_OK ) { PCURL pUrlTbl; if ( (pUrlTbl = (PCURL)m_pUrlTbl->Offset(topic.dwOffsURL)) ) { PURLSTR purl = (PURLSTR) m_pUrlStrings->Offset(pUrlTbl->dwOffsURL); if (purl) { // If not an interfile jump, the create the full URL
//
if (! StrChr(purl->szURL, ':')) { psz = purl->szURL; if ((int) (strlen(psz) + strlen(txtMkStore) + strlen(m_szTitlePath) + 7) > cch) return E_OUTOFMEMORY; StringCchCopyA(pwszURL, cch, txtMkStore); pwszURL[cch-1] = 0; StringCchCatA(pwszURL, cch, m_szTitlePath);
if (*psz != '/') StringCchCatA(pwszURL, cch, txtSepBack); else StringCchCatA(pwszURL, cch, txtDoubleColonSep); StringCchCatA(pwszURL, cch, psz); } else return E_FAIL; // inter-chm jump, not supported by this function
} } } return hr; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicData
//
// This funciton retrieves data from the topics sub-file
//
HRESULT CTitleInfo::GetTopicData(DWORD dwTopic, TOC_TOPIC * pTopicData) { HRESULT hr; BYTE * pb; if (m_bOpen == FALSE) return E_FAIL;
if (!m_pTopics) { m_pTopics = new CPagedSubfile; if(!m_pTopics) return E_FAIL; if (FAILED(hr = m_pTopics->Open(this, txtTopicsFile))) { delete m_pTopics; m_pTopics = NULL; return hr; } } pb = (BYTE*)m_pTopics->Offset(dwTopic * sizeof(TOC_TOPIC)); if (pb) { memcpy(pTopicData, pb, sizeof(TOC_TOPIC)); return S_OK; } else return E_FAIL; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
HRESULT CTitleInfo::GetString( DWORD dwOffset, WCHAR* pwsz, int cch, UINT cp ) { const CHAR* pStr = GetString( dwOffset ); if( pStr ) { MultiByteToWideChar(cp, 0, pStr, -1, pwsz, cch ); return S_OK; } else return E_FAIL; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
const CHAR* CTitleInfo::GetString( DWORD dwOffset ) { HRESULT hr; const CHAR* pStr;
if( !m_bOpen ) return NULL;
if( !m_pStrTbl ) { m_pStrTbl = new CPagedSubfile; if(!m_pStrTbl) return NULL;
if( FAILED(hr = m_pStrTbl->Open(this,txtStringsFile)) ) { delete m_pStrTbl; m_pStrTbl = NULL;
return NULL; } }
pStr = (const CHAR*) m_pStrTbl->Offset( dwOffset );
return pStr; }
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
HRESULT CTitleInfo::GetString( DWORD dwOffset, CHAR* psz, int cb ) { const CHAR* pStr = GetString( dwOffset );
if( pStr ) { StringCbCopyA( psz, cb, pStr ); psz[cb-1] = 0; return S_OK; } else return E_FAIL; }
|