char *GetHtml() { // first add the homepage const char *index = doc->GetHomePath(); ScopedMem<WCHAR> url(doc->ToStr(index)); Visit(NULL, url, 0); // then add all pages linked to from the table of contents doc->ParseToc(this); // finally add all the remaining HTML files Vec<char *> *paths = doc->GetAllPaths(); for (size_t i = 0; i < paths->Count(); i++) { char *path = paths->At(i); if (str::EndsWithI(path, ".htm") || str::EndsWithI(path, ".html")) { if (*path == '/') path++; url.Set(str::conv::FromUtf8(path)); Visit(NULL, url, -1); } } FreeVecMembers(*paths); delete paths; return html.StealData(); }
ChmDoc* ChmDoc::CreateFromFile(const WCHAR* fileName) { ChmDoc* doc = new ChmDoc(); if (!doc || !doc->Load(fileName)) { delete doc; return nullptr; } return doc; }
DocTocItem *Chm2EngineImpl::GetTocTree() { EbookTocBuilder builder(this); doc->ParseToc(&builder); if (doc->HasIndex()) { // TODO: ToC code doesn't work too well for displaying an index, // so this should really become a tree of its own (which // doesn't rely on entries being in the same order as pages) builder.Visit(L"Index", NULL, 1); builder.SetIsIndex(true); doc->ParseIndex(&builder); } return builder.GetRoot(); }
virtual void Visit(const WCHAR *name, const WCHAR *url, int level) { if (!url || IsExternalUrl(url)) return; ScopedMem<WCHAR> plainUrl(str::ToPlainUrl(url)); if (added.FindI(plainUrl) != -1) return; ScopedMem<char> urlUtf8(str::conv::ToUtf8(plainUrl)); size_t pageHtmlLen; ScopedMem<unsigned char> pageHtml(doc->GetData(urlUtf8, &pageHtmlLen)); if (!pageHtml) return; html.AppendFmt("<pagebreak page_path=\"%s\" page_marker />", urlUtf8); html.AppendAndFree(doc->ToUtf8(pageHtml, ExtractHttpCharset((const char *)pageHtml.Get(), pageHtmlLen))); added.Append(plainUrl.StealData()); }
void CreateThumbnail(HtmlWindow *hw) { this->hw = hw; homeUrl.Set(str::conv::FromAnsi(doc->GetHomePath())); if (*homeUrl == '/') homeUrl.Set(str::Dup(homeUrl + 1)); hw->NavigateToDataUrl(homeUrl); }
virtual const unsigned char *GetDataForUrl(const WCHAR *url, size_t *len) { ScopedCritSec scope(&docAccess); ScopedMem<WCHAR> plainUrl(url::GetFullPath(url)); ScopedMem<char> urlUtf8(str::conv::ToUtf8(plainUrl)); data.Append(doc->GetData(urlUtf8, len)); return data.Last(); }
bool ChmEngineImpl::Load(const WCHAR *fileName) { this->fileName = str::Dup(fileName); Timer t(true); doc = ChmDoc::CreateFromFile(fileName); dbglog::LogF("ChmDoc::CreateFromFile(): %.2f ms", t.GetTimeInMs()); if (!doc) return false; // always make the document's homepage page 1 pages.Append(str::conv::FromAnsi(doc->GetHomePath())); // parse the ToC here, since page numbering depends on it t.Start(); doc->ParseToc(&ChmTocBuilder(doc, &pages, &tocRoot)); dbglog::LogF("doc->ParseToc(): %.2f ms", t.GetTimeInMs()); CrashIf(pages.Count() == 0); return pages.Count() > 0; }
ImageData *GetImageData(const char *id, const char *pagePath) { ScopedMem<char> url(NormalizeURL(id, pagePath)); str::UrlDecodeInPlace(url); for (size_t i = 0; i < images.Count(); i++) { if (str::Eq(images.At(i).id, url)) return &images.At(i).base; } ImageData2 data = { 0 }; data.base.data = (char *)doc->GetData(url, &data.base.len); if (!data.base.data) return NULL; data.id = url.StealData(); images.Append(data); return &images.Last().base; }
// Load and cache data for a given url inside CHM file. bool ChmEngineImpl::GetDataForUrl(const WCHAR *url, char **data, size_t *len) { ScopedMem<WCHAR> plainUrl(str::ToPlainUrl(url)); ChmCacheEntry *e = FindDataForUrl(plainUrl); if (!e) { e = new ChmCacheEntry(plainUrl); ScopedMem<char> urlUtf8(str::conv::ToUtf8(plainUrl)); e->data = (char *)doc->GetData(urlUtf8, &e->size); if (!e->data) { delete e; return false; } urlDataCache.Append(e); } *data = e->data; *len = e->size; return true; }