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); }
DocTocItem *MobiEngineImpl::GetTocTree() { if (!tocReparsePoint) return NULL; EbookTocItem *root = NULL; ScopedMem<WCHAR> itemText; ScopedMem<WCHAR> itemLink; int itemLevel = 0; int idCounter = 0; // there doesn't seem to be a standard for Mobi ToCs, so we try to // determine the author's intentions by looking at commonly used tags HtmlPullParser parser(tocReparsePoint, str::Len(tocReparsePoint)); HtmlToken *tok; while ((tok = parser.Next()) && !tok->IsError()) { if (itemLink && tok->IsText()) { ScopedMem<WCHAR> linkText(str::conv::FromHtmlUtf8(tok->s, tok->sLen)); if (itemText) itemText.Set(str::Join(itemText, L" ", linkText)); else itemText.Set(linkText.StealData()); } else if (!tok->IsTag()) continue; else if (Tag_Mbp_Pagebreak == tok->tag) break; else if (!itemLink && tok->IsStartTag() && Tag_A == tok->tag) { AttrInfo *attr = tok->GetAttrByName("filepos"); if (!attr) attr = tok->GetAttrByName("href"); if (attr) itemLink.Set(str::conv::FromHtmlUtf8(attr->val, attr->valLen)); } else if (itemLink && tok->IsEndTag() && Tag_A == tok->tag) { PageDestination *dest = NULL; if (!itemText) { itemLink.Set(NULL); continue; } if (IsExternalUrl(itemLink)) dest = new SimpleDest2(0, RectD(), itemLink.StealData()); else dest = GetNamedDest(itemLink); EbookTocItem *item = new EbookTocItem(itemText.StealData(), dest); item->id = ++idCounter; item->open = itemLevel <= 2; AppendTocItem(root, item, itemLevel); itemLink.Set(NULL); } else if (Tag_Blockquote == tok->tag || Tag_Ul == tok->tag || Tag_Ol == tok->tag) { if (tok->IsStartTag()) itemLevel++; else if (tok->IsEndTag() && itemLevel > 0) itemLevel--; } } return root; }
bool ViewWithAcrobat(WindowInfo *win, const WCHAR *args) { if (!CanViewWithAcrobat(win)) return false; ScopedMem<WCHAR> exePath(GetAcrobatPath()); if (!exePath) return false; if (!args) args = L""; ScopedMem<WCHAR> params; // Command line format for version 6 and later: // /A "page=%d&zoom=%.1f,%d,%d&..." <filename> // see http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf#page=5 // /P <filename> // see http://www.adobe.com/devnet/acrobat/pdfs/Acrobat_SDK_developer_faq.pdf#page=24 // TODO: Also set zoom factor and scroll to current position? if (win->IsDocLoaded() && HIWORD(GetFileVersion(exePath)) >= 6) params.Set(str::Format(L"/A \"page=%d\" %s \"%s\"", win->ctrl->CurrentPageNo(), args, win->ctrl->FilePath())); else params.Set(str::Format(L"%s \"%s\"", args, win->loadedFilePath)); return LaunchFile(exePath, params); }
/* Caller needs to free() the result. */ WCHAR *AppGenDataFilename(WCHAR *fileName) { ScopedMem<WCHAR> path; if (IsRunningInPortableMode()) { /* Use the same path as the binary */ ScopedMem<WCHAR> exePath(GetExePath()); if (exePath) path.Set(path::GetDir(exePath)); } else { /* Use %APPDATA% */ WCHAR dir[MAX_PATH]; dir[0] = '\0'; BOOL ok = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, TRUE); if (ok) { path.Set(path::Join(dir, APP_NAME_STR)); if (path && !dir::Create(path)) path.Set(NULL); } } if (!path || !fileName) return NULL; return path::Join(path, fileName); }
static void SetupCrashHandler() { ScopedMem<WCHAR> symDir; ScopedMem<WCHAR> tmpDir(path::GetTempPath()); if (tmpDir) symDir.Set(path::Join(tmpDir, L"SumatraPDF-symbols")); else symDir.Set(AppGenDataFilename(L"SumatraPDF-symbols")); ScopedMem<WCHAR> crashDumpPath(AppGenDataFilename(CRASH_DUMP_FILE_NAME)); InstallCrashHandler(crashDumpPath, symDir); }
void CopySelectionToClipboard(WindowInfo *win) { if (!win->selectionOnPage) return; CrashIf(win->selectionOnPage->Count() == 0); if (win->selectionOnPage->Count() == 0) return; CrashIf(!win->dm || !win->dm->engine); if (!win->dm || !win->dm->engine) return; if (!OpenClipboard(NULL)) return; EmptyClipboard(); #ifndef DISABLE_DOCUMENT_RESTRICTIONS if (!win->dm->engine->AllowsCopyingText()) ShowNotification(win, _TR("Copying text was denied (copying as image only)")); else #endif if (!win->dm->engine->IsImageCollection()) { ScopedMem<WCHAR> selText; bool isTextSelection = win->dm->textSelection->result.len > 0; if (isTextSelection) { selText.Set(win->dm->textSelection->ExtractText(L"\r\n")); } else { WStrVec selections; for (size_t i = 0; i < win->selectionOnPage->Count(); i++) { SelectionOnPage *selOnPage = &win->selectionOnPage->At(i); WCHAR *text = win->dm->GetTextInRegion(selOnPage->pageNo, selOnPage->rect); if (text) selections.Push(text); } selText.Set(selections.Join()); } // don't copy empty text if (!str::IsEmpty(selText.Get())) CopyTextToClipboard(selText, true); if (isTextSelection) { // don't also copy the first line of a text selection as an image CloseClipboard(); return; } } /* also copy a screenshot of the current selection to the clipboard */ SelectionOnPage *selOnPage = &win->selectionOnPage->At(0); RenderedBitmap * bmp = win->dm->engine->RenderBitmap(selOnPage->pageNo, win->dm->ZoomReal(), win->dm->Rotation(), &selOnPage->rect, Target_Export); if (bmp) CopyImageToClipboard(bmp->GetBitmap(), true); delete bmp; CloseClipboard(); }
// Find a record corresponding to the given source file, line number and optionally column number. // (at the moment the column parameter is ignored) // // If there are several *consecutively declared* records for the same line then they are all returned. // The list of records is added to the vector 'records' // // If there is no record for that line, the record corresponding to the nearest line is selected // (within a range of EPSILON_LINE) // // The function returns PDFSYNCERR_SUCCESS if a matching record was found. UINT Pdfsync::SourceToRecord(const WCHAR* srcfilename, UINT line, UINT col, Vec<size_t> &records) { if (!srcfilename) return PDFSYNCERR_INVALID_ARGUMENT; ScopedMem<WCHAR> srcfilepath; // convert the source file to an absolute path if (PathIsRelative(srcfilename)) srcfilepath.Set(PrependDir(srcfilename)); else srcfilepath.Set(str::Dup(srcfilename)); if (!srcfilepath) return PDFSYNCERR_OUTOFMEMORY; // find the source file entry size_t isrc; for (isrc = 0; isrc < srcfiles.Count(); isrc++) if (path::IsSame(srcfilepath, srcfiles.At(isrc))) break; if (isrc == srcfiles.Count()) return PDFSYNCERR_UNKNOWN_SOURCEFILE; if (fileIndex.At(isrc).start == fileIndex.At(isrc).end) return PDFSYNCERR_NORECORD_IN_SOURCEFILE; // there is not any record declaration for that particular source file // look for sections belonging to the specified file // starting with the first section that is declared within the scope of the file. UINT min_distance = EPSILON_LINE; // distance to the closest record size_t lineIx = (size_t)-1; // closest record-line index for (size_t isec = fileIndex.At(isrc).start; isec < fileIndex.At(isrc).end; isec++) { // does this section belong to the desired file? if (lines.At(isec).file != isrc) continue; UINT d = abs((int)lines.At(isec).line - (int)line); if (d < min_distance) { min_distance = d; lineIx = isec; if (0 == d) break; // We have found a record for the requested line! } } if (lineIx == (size_t)-1) return PDFSYNCERR_NORECORD_FOR_THATLINE; // we read all the consecutive records until we reach a record belonging to another line for (size_t i = lineIx; i < lines.Count() && lines.At(i).line == lines.At(lineIx).line; i++) records.Push(lines.At(i).record); return PDFSYNCERR_SUCCESS; }
// Detect TeX editors installed on the system and construct the // corresponding inverse search commands. // // Parameters: // hwndCombo -- (optional) handle to a combo list that will be filled with the list of possible inverse search commands. // Returns: // the inverse search command of the first detected editor (the caller needs to free() the result). WCHAR *AutoDetectInverseSearchCommands(HWND hwndCombo) { WCHAR *firstEditor = NULL; WStrList foundExes; for (int i = 0; i < dimof(editor_rules); i++) { ScopedMem<WCHAR> path(ReadRegStr(editor_rules[i].RegRoot, editor_rules[i].RegKey, editor_rules[i].RegValue)); if (!path) continue; ScopedMem<WCHAR> exePath; if (editor_rules[i].Type == SiblingPath) { // remove file part ScopedMem<WCHAR> dir(path::GetDir(path)); exePath.Set(path::Join(dir, editor_rules[i].BinaryFilename)); } else if (editor_rules[i].Type == BinaryDir) exePath.Set(path::Join(path, editor_rules[i].BinaryFilename)); else // if (editor_rules[i].Type == BinaryPath) exePath.Set(path.StealData()); // don't show duplicate entries if (foundExes.FindI(exePath) != -1) continue; // don't show inexistent paths (and don't try again for them) if (!file::Exists(exePath)) { foundExes.Append(exePath.StealData()); continue; } ScopedMem<WCHAR> editorCmd(str::Format(L"\"%s\" %s", exePath, editor_rules[i].InverseSearchArgs)); if (!hwndCombo) { // no need to fill a combo box: return immeditately after finding an editor. return editorCmd.StealData(); } ComboBox_AddString(hwndCombo, editorCmd); if (!firstEditor) firstEditor = editorCmd.StealData(); foundExes.Append(exePath.StealData()); } // Fall back to notepad as a default handler if (!firstEditor) { firstEditor = str::Dup(L"notepad %f"); if (hwndCombo) ComboBox_AddString(hwndCombo, firstEditor); } return firstEditor; }
WCHAR *ChmDoc::GetProperty(DocumentProperty prop) { ScopedMem<WCHAR> result; if (Prop_Title == prop && title) result.Set(ToStr(title)); else if (Prop_CreatorApp == prop && creator) result.Set(ToStr(creator)); // TODO: shouldn't it be up to the front-end to normalize whitespace? if (result) { // TODO: original code called str::RemoveChars(result, "\n\r\t") str::NormalizeWS(result); } return result.StealData(); }
void RenderDocument(BaseEngine *engine, const WCHAR *renderPath) { for (int pageNo = 1; pageNo <= engine->PageCount(); pageNo++) { RenderedBitmap *bmp = engine->RenderBitmap(pageNo, 1.0, 0); size_t len = 0; ScopedMem<unsigned char> data; if (bmp && str::EndsWithI(renderPath, L".bmp")) data.Set(SerializeBitmap(bmp->GetBitmap(), &len)); else if (bmp) data.Set(tga::SerializeBitmap(bmp->GetBitmap(), &len)); ScopedMem<WCHAR> pageBmpPath(str::Format(renderPath, pageNo)); file::WriteAll(pageBmpPath, data, len); delete bmp; } }
// Show the result of a PDF forward-search synchronization (initiated by a DDE command) void ShowForwardSearchResult(WindowInfo *win, const WCHAR *fileName, UINT line, UINT col, UINT ret, UINT page, Vec<RectI> &rects) { win->fwdSearchMark.rects.Reset(); const PageInfo *pi = win->dm->GetPageInfo(page); if ((ret == PDFSYNCERR_SUCCESS) && (rects.Count() > 0) && (NULL != pi)) { // remember the position of the search result for drawing the rect later on win->fwdSearchMark.rects = rects; win->fwdSearchMark.page = page; win->fwdSearchMark.show = true; win->fwdSearchMark.hideStep = 0; if (!gUserPrefs->forwardSearch.highlightPermanent) SetTimer(win->hwndCanvas, HIDE_FWDSRCHMARK_TIMER_ID, HIDE_FWDSRCHMARK_DELAY_IN_MS, NULL); // Scroll to show the overall highlighted zone int pageNo = page; RectI overallrc = rects.At(0); for (size_t i = 1; i < rects.Count(); i++) overallrc = overallrc.Union(rects.At(i)); TextSel res = { 1, &pageNo, &overallrc }; if (!win->dm->PageVisible(page)) win->dm->GoToPage(page, 0, true); if (!win->dm->ShowResultRectToScreen(&res)) win->RepaintAsync(); if (IsIconic(win->hwndFrame)) ShowWindowAsync(win->hwndFrame, SW_RESTORE); return; } ScopedMem<WCHAR> buf; if (ret == PDFSYNCERR_SYNCFILE_NOTFOUND) ShowNotification(win, _TR("No synchronization file found")); else if (ret == PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED) ShowNotification(win, _TR("Synchronization file cannot be opened")); else if (ret == PDFSYNCERR_INVALID_PAGE_NUMBER) buf.Set(str::Format(_TR("Page number %u inexistant"), page)); else if (ret == PDFSYNCERR_NO_SYNC_AT_LOCATION) ShowNotification(win, _TR("No synchronization info at this position")); else if (ret == PDFSYNCERR_UNKNOWN_SOURCEFILE) buf.Set(str::Format(_TR("Unknown source file (%s)"), fileName)); else if (ret == PDFSYNCERR_NORECORD_IN_SOURCEFILE) buf.Set(str::Format(_TR("Source file %s has no synchronization point"), fileName)); else if (ret == PDFSYNCERR_NORECORD_FOR_THATLINE) buf.Set(str::Format(_TR("No result found around line %u in file %s"), line, fileName)); else if (ret == PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD) buf.Set(str::Format(_TR("No result found around line %u in file %s"), line, fileName)); if (buf) ShowNotification(win, buf); }
static bool ExtractSignature(const char *hexSignature, const void *data, size_t& dataLen, ScopedMem<BYTE>& signature, size_t& signatureLen) { // verify hexSignature format - must be either // * a string starting with "sha1:" followed by the signature (and optionally whitespace and further content) // * NULL, then the signature must be found on the last line of non-binary data, starting at " Signature sha1:" if (str::StartsWith(hexSignature, "sha1:")) hexSignature += 5; else if (!hexSignature) { if (dataLen < 20 || memchr(data, 0, dataLen)) return false; const char *lastLine = (const char *)data + dataLen - 1; while (lastLine > data && *(lastLine - 1) != '\n') lastLine--; if (lastLine == data || !str::Find(lastLine, " Signature sha1:")) return false; dataLen = lastLine - (const char *)data; hexSignature = str::Find(lastLine, " Signature sha1:") + 16; } else return false; str::Str<BYTE> signatureBytes; for (const char *c = hexSignature; *c && !str::IsWs(*c); c += 2) { int val; if (1 != sscanf_s(c, "%02x", &val)) return false; signatureBytes.Append((BYTE)val); } signatureLen = signatureBytes.Size(); signature.Set(signatureBytes.StealData()); return true; }
static void AppendFavMenuItems(HMENU m, DisplayState *f, UINT& idx, bool combined, bool isCurrent) { for (size_t i = 0; i < f->favorites->Count(); i++) { if (i >= MAX_FAV_MENUS) return; Favorite *fn = f->favorites->At(i); fn->menuId = idx++; ScopedMem<WCHAR> s; if (combined) s.Set(FavCompactReadableName(f, fn, isCurrent)); else s.Set(FavReadableName(fn)); s.Set(win::menu::ToSafeString(s)); AppendMenu(m, MF_STRING, (UINT_PTR)fn->menuId, s); } }
void AddFavorite(WindowInfo *win) { int pageNo = win->currPageNo; ScopedMem<WCHAR> name; if (win->dm->HasTocTree()) { // use the current ToC heading as default name DocTocItem *root = win->dm->engine->GetTocTree(); DocTocItem *item = TocItemForPageNo(root, pageNo); if (item) name.Set(str::Dup(item->title)); delete root; } ScopedMem<WCHAR> pageLabel(win->dm->engine->GetPageLabel(pageNo)); bool shouldAdd = Dialog_AddFavorite(win->hwndFrame, pageLabel, name); if (!shouldAdd) return; ScopedMem<WCHAR> plainLabel(str::Format(L"%d", pageNo)); bool needsLabel = !str::Eq(plainLabel, pageLabel); RememberFavTreeExpansionStateForAllWindows(); gFavorites.AddOrReplace(win->loadedFilePath, pageNo, name, needsLabel ? pageLabel.Get() : NULL); // expand newly added favorites by default DisplayState *fav = gFavorites.GetFavByFilePath(win->loadedFilePath); CrashIf(!fav || win->expandedFavorites.Contains(fav)); if (fav && fav->favorites->Count() == 2) win->expandedFavorites.Append(fav); UpdateFavoritesTreeForAllWindows(); prefs::Save(); }
/* Caller needs to free() the result. */ WCHAR *AppGenDataFilename(const WCHAR *fileName) { ScopedMem<WCHAR> path; /* Use %APPDATA% */ path.Set(GetSpecialFolder(CSIDL_APPDATA, true)); if (path) { path.Set(path::Join(path, APP_NAME_STR)); if (path && !dir::Create(path)) path.Set(NULL); } if (!path || !fileName) return NULL; return path::Join(path, fileName); }
// caller must free() the result char *Escape(WCHAR *string, bool keepString=false) { ScopedMem<WCHAR> freeOnReturn; if (!keepString) freeOnReturn.Set(string); if (str::IsEmpty(string)) return NULL; if (!str::FindChar(string, '<') && !str::FindChar(string, '&') && !str::FindChar(string, '"')) return str::conv::ToUtf8(string); str::Str<WCHAR> escaped(256); for (WCHAR *s = string; *s; s++) { switch (*s) { case '&': escaped.Append(L"&"); break; case '<': escaped.Append(L"<"); break; case '>': escaped.Append(L">"); break; case '"': escaped.Append(L"""); break; case '\'': escaped.Append(L"&"); break; default: escaped.Append(*s); break; } } return str::conv::ToUtf8(escaped.Get()); }
unsigned char *ChmDoc::GetData(const char *fileName, size_t *lenOut) { ScopedMem<char> fileNameTmp; if (!str::StartsWith(fileName, "/")) { fileNameTmp.Set(str::Join("/", fileName)); fileName = fileNameTmp; } else if (str::StartsWith(fileName, "///")) { fileName += 2; } struct chmUnitInfo info; int res = chm_resolve_object(chmHandle, fileName, &info); if (CHM_RESOLVE_SUCCESS != res) return NULL; size_t len = (size_t)info.length; if (len > 128 * 1024 * 1024) { // don't allow anything above 128 MB return NULL; } // +1 for 0 terminator for C string compatibility ScopedMem<unsigned char> data((unsigned char *)malloc(len + 1)); if (!data) return NULL; if (!chm_retrieve_object(chmHandle, &info, data.Get(), 0, len)) return NULL; data[len] = '\0'; if (lenOut) *lenOut = len; return data.StealData(); }
int Pdfsync::DocToSource(UINT pageNo, PointI pt, ScopedMem<WCHAR>& filename, UINT *line, UINT *col) { if (IsIndexDiscarded()) if (RebuildIndex() != PDFSYNCERR_SUCCESS) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // find the entry in the index corresponding to this page if (pageNo <= 0 || pageNo >= sheetIndex.Count() || pageNo > (UINT)engine->PageCount()) return PDFSYNCERR_INVALID_PAGE_NUMBER; // PdfSync coordinates are y-inversed RectI mbox = engine->PageMediabox(pageNo).Round(); pt.y = mbox.dy - pt.y; // distance to the closest pdf location (in the range <PDFSYNC_EPSILON_SQUARE) UINT closest_xydist = UINT_MAX; UINT selected_record = UINT_MAX; // If no record is found within a distance^2 of PDFSYNC_EPSILON_SQUARE // (selected_record == -1) then we pick up the record that is closest // vertically to the hit-point. UINT closest_ydist = UINT_MAX; // vertical distance between the hit point and the vertically-closest record UINT closest_xdist = UINT_MAX; // horizontal distance between the hit point and the vertically-closest record UINT closest_ydist_record = UINT_MAX; // vertically-closest record // read all the sections of 'p' declarations for this pdf sheet for (size_t i = sheetIndex.At(pageNo); i < points.Count() && points.At(i).page == pageNo; i++) { // check whether it is closer than the closest point found so far UINT dx = abs(pt.x - (int)SYNC_TO_PDF_COORDINATE(points.At(i).x)); UINT dy = abs(pt.y - (int)SYNC_TO_PDF_COORDINATE(points.At(i).y)); UINT dist = dx * dx + dy * dy; if (dist < PDFSYNC_EPSILON_SQUARE && dist < closest_xydist) { selected_record = points.At(i).record; closest_xydist = dist; } else if ((closest_xydist == UINT_MAX) && dy < PDFSYNC_EPSILON_Y && (dy < closest_ydist || (dy == closest_ydist && dx < closest_xdist))) { closest_ydist_record = points.At(i).record; closest_ydist = dy; closest_xdist = dx; } } if (selected_record == UINT_MAX) selected_record = closest_ydist_record; if (selected_record == UINT_MAX) return PDFSYNCERR_NO_SYNC_AT_LOCATION; // no record was found close enough to the hit point // We have a record number, we need to find its declaration ('l ...') in the syncfile PdfsyncLine cmp; cmp.record = selected_record; PdfsyncLine *found = (PdfsyncLine *)bsearch(&cmp, lines.LendData(), lines.Count(), sizeof(PdfsyncLine), cmpLineRecords); assert(found); if (!found) return PDFSYNCERR_NO_SYNC_AT_LOCATION; filename.Set(str::Dup(srcfiles.At(found->file))); *line = found->line; *col = found->column; return PDFSYNCERR_SUCCESS; }
// extract ComicBookInfo metadata // cf. http://code.google.com/p/comicbookinfo/ bool CbxEngineImpl::Visit(const char *path, const char *value, json::DataType type) { if (json::Type_String == type && str::Eq(path, "/ComicBookInfo/1.0/title")) propTitle.Set(str::conv::FromUtf8(value)); else if (json::Type_Number == type && str::Eq(path, "/ComicBookInfo/1.0/publicationYear")) propDate.Set(str::Format(L"%s/%d", propDate ? propDate : L"", atoi(value))); else if (json::Type_Number == type && str::Eq(path, "/ComicBookInfo/1.0/publicationMonth")) propDate.Set(str::Format(L"%d%s", atoi(value), propDate ? propDate : L"")); else if (json::Type_String == type && str::Eq(path, "/appID")) propCreator.Set(str::conv::FromUtf8(value)); else if (json::Type_String == type && str::Eq(path, "/lastModified")) propModDate.Set(str::conv::FromUtf8(value)); else if (json::Type_String == type && str::Eq(path, "/X-summary")) propSummary.Set(str::conv::FromUtf8(value)); else if (str::StartsWith(path, "/ComicBookInfo/1.0/credits[")) { int idx = -1; const char *prop = str::Parse(path, "/ComicBookInfo/1.0/credits[%d]/", &idx); if (prop) { if (json::Type_String == type && str::Eq(prop, "person")) propAuthorTmp.Set(str::conv::FromUtf8(value)); else if (json::Type_Bool == type && str::Eq(prop, "primary") && propAuthorTmp && propAuthors.Find(propAuthorTmp) == -1) { propAuthors.Append(propAuthorTmp.StealData()); } } return true; } // stop parsing once we have all desired information return !propTitle || propAuthors.Count() == 0 || !propCreator || !propDate || str::FindChar(propDate, '/') <= propDate; }
DocTocItem *Fb2EngineImpl::GetTocTree() { EbookTocItem *root = NULL; ScopedMem<WCHAR> itemText; int titleCount = 0; bool inTitle = false; int level = 0; size_t xmlLen; const char *xmlData = doc->GetTextData(&xmlLen); HtmlPullParser parser(xmlData, xmlLen); HtmlToken *tok; while ((tok = parser.Next()) && !tok->IsError()) { if (tok->IsStartTag() && Tag_Section == tok->tag) level++; else if (tok->IsEndTag() && Tag_Section == tok->tag && level > 0) level--; else if (tok->IsStartTag() && Tag_Title == tok->tag) { inTitle = true; titleCount++; } else if (tok->IsEndTag() && Tag_Title == tok->tag) { if (itemText) str::NormalizeWS(itemText); if (!str::IsEmpty(itemText.Get())) { ScopedMem<WCHAR> name(str::Format(TEXT(FB2_TOC_ENTRY_MARK) L"%d", titleCount)); PageDestination *dest = GetNamedDest(name); EbookTocItem *item = new EbookTocItem(itemText.StealData(), dest); item->id = titleCount; item->open = level <= 2; AppendTocItem(root, item, level); } inTitle = false; } else if (inTitle && tok->IsText()) { ScopedMem<WCHAR> text(str::conv::FromHtmlUtf8(tok->s, tok->sLen)); if (str::IsEmpty(itemText.Get())) itemText.Set(text.StealData()); else itemText.Set(str::Join(itemText, L" ", text)); } } return root; }
int SyncTex::DocToSource(UINT pageNo, PointI pt, ScopedMem<WCHAR>& filename, UINT *line, UINT *col) { if (IsIndexDiscarded()) { if (RebuildIndex() != PDFSYNCERR_SUCCESS) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; } CrashIf(!this->scanner); // Coverity: at this point, this->scanner->flags.has_parsed == 1 and thus // synctex_scanner_parse never gets the chance to freeing the scanner if (synctex_edit_query(this->scanner, pageNo, (float)pt.x, (float)pt.y) <= 0) return PDFSYNCERR_NO_SYNC_AT_LOCATION; synctex_node_t node = synctex_next_result(this->scanner); if (!node) return PDFSYNCERR_NO_SYNC_AT_LOCATION; const char *name = synctex_scanner_get_name(this->scanner, synctex_node_tag(node)); if (!name) return PDFSYNCERR_UNKNOWN_SOURCEFILE; bool isUtf8 = true; filename.Set(str::conv::FromUtf8(name)); TryAgainAnsi: if (!filename) return PDFSYNCERR_OUTOFMEMORY; // undecorate the filepath: replace * by space and / by \ str::TransChars(filename, L"*/", L" \\"); // Convert the source filepath to an absolute path if (PathIsRelative(filename)) filename.Set(PrependDir(filename)); // recent SyncTeX versions encode in UTF-8 instead of ANSI if (isUtf8 && !file::Exists(filename)) { isUtf8 = false; filename.Set(str::conv::FromAnsi(name)); goto TryAgainAnsi; } *line = synctex_node_line(node); *col = synctex_node_column(node); return PDFSYNCERR_SUCCESS; }
/* Returns true, if a Registry entry indicates that this executable has been created by an installer (and should be updated through an installer) */ bool HasBeenInstalled() { ScopedMem<WCHAR> installedPath; // cf. GetInstallationDir() in installer\Installer.cpp installedPath.Set(ReadRegStr(HKEY_CURRENT_USER, REG_PATH_UNINST, L"InstallLocation")); if (!installedPath) installedPath.Set(ReadRegStr(HKEY_LOCAL_MACHINE, REG_PATH_UNINST, L"InstallLocation")); if (!installedPath) return false; ScopedMem<WCHAR> exePath(GetExePath()); if (!exePath) return false; if (!str::EndsWithI(installedPath, L".exe")) installedPath.Set(path::Join(installedPath, path::GetBaseName(exePath))); return path::IsSame(installedPath, exePath); }
RemoteHtmlDest(const WCHAR *relativeURL) : SimpleDest2(0, RectD()) { const WCHAR *id = str::FindChar(relativeURL, '#'); if (id) { value.Set(str::DupN(relativeURL, id - relativeURL)); name.Set(str::Dup(id)); } else value.Set(str::Dup(relativeURL)); }
static void AppendFavMenuItems(HMENU m, FileFavs *f, UINT& idx, bool combined, bool isCurrent) { size_t items = f->favNames.Count(); if (items > MAX_FAV_MENUS) { items = MAX_FAV_MENUS; } for (size_t i = 0; i < items; i++) { FavName *fn = f->favNames.At(i); fn->menuId = idx++; ScopedMem<TCHAR> s; if (combined) s.Set(FavCompactReadableName(f, fn, isCurrent)); else s.Set(FavReadableName(fn)); s.Set(win::menu::ToSafeString(s)); AppendMenu(m, MF_STRING, (UINT_PTR)fn->menuId, s); } }
void ChmDoc::FixPathCodepage(ScopedMem<char>& path, UINT& fileCP) { if (!path || HasData(path)) return; ScopedMem<char> utf8Path(ToUtf8((unsigned char *)path.Get())); if (HasData(utf8Path)) { path.Set(utf8Path.StealData()); fileCP = codepage; } else if (fileCP != codepage) { utf8Path.Set(ToUtf8((unsigned char *)path.Get(), fileCP)); if (HasData(utf8Path)) { path.Set(utf8Path.StealData()); codepage = fileCP; } } }
bool IsRunningInPortableMode() { // cache the result so that it will be consistent during the lifetime of the process static int sCacheIsPortable = -1; // -1 == uninitialized, 0 == installed, 1 == portable if (sCacheIsPortable != -1) return sCacheIsPortable != 0; sCacheIsPortable = 1; ScopedMem<WCHAR> exePath(GetExePath()); if (!exePath) return true; // if we can't get a path, assume we're not running from "Program Files" ScopedMem<WCHAR> installedPath; // cf. GetInstallationDir() in installer\Installer.cpp installedPath.Set(ReadRegStr(HKEY_CURRENT_USER, REG_PATH_UNINST, L"InstallLocation")); if (!installedPath) installedPath.Set(ReadRegStr(HKEY_LOCAL_MACHINE, REG_PATH_UNINST, L"InstallLocation")); if (installedPath) { if (!str::EndsWithI(installedPath.Get(), L".exe")) installedPath.Set(path::Join(installedPath.Get(), path::GetBaseName(exePath))); if (path::IsSame(installedPath, exePath)) { sCacheIsPortable = 0; return false; } } ScopedMem<WCHAR> programFilesDir(GetSpecialFolder(CSIDL_PROGRAM_FILES)); if (!programFilesDir) return true; // check if one of the exePath's parent directories is "Program Files" // (or a junction to it) WCHAR *baseName; while ((baseName = (WCHAR*)path::GetBaseName(exePath)) > exePath) { baseName[-1] = '\0'; if (path::IsSame(programFilesDir, exePath)) { sCacheIsPortable = 0; return false; } } return true; }
bool ViewWithHtmlHelp(WindowInfo *win, const WCHAR *args) { if (!CanViewWithHtmlHelp(win)) return false; ScopedMem<WCHAR> exePath(GetHtmlHelpPath()); if (!exePath) return false; if (!args) args = L""; ScopedMem<WCHAR> params; if (win->IsDocLoaded()) params.Set(str::Format(L"%s \"%s\"", args, win->ctrl->FilePath())); else params.Set(str::Format(L"%s \"%s\"", args, win->loadedFilePath)); return LaunchFile(exePath, params); }
void ChmFormatter::HandleTagPagebreak(HtmlToken *t) { AttrInfo *attr = t->GetAttrByName("page_path"); if (!attr || pagePath) ForceNewPage(); if (attr) { RectF bbox(0, currY, pageDx, 0); currPage->instructions.Append(DrawInstr::Anchor(attr->val, attr->valLen, bbox)); pagePath.Set(str::DupN(attr->val, attr->valLen)); } }
bool ViewWithPDFXChange(WindowInfo *win, const WCHAR *args) { if (!CanViewWithPDFXChange(win)) return false; ScopedMem<WCHAR> exePath(GetPDFXChangePath()); if (!exePath) return false; if (!args) args = L""; // PDFXChange cmd-line format: // [/A "param=value [¶m2=value ..."] [PDF filename] // /A params: page=<page number> ScopedMem<WCHAR> params; if (win->IsDocLoaded()) params.Set(str::Format(L"%s /A \"page=%d\" \"%s\"", args, win->ctrl->CurrentPageNo(), win->ctrl->FilePath())); else params.Set(str::Format(L"%s \"%s\"", args, win->loadedFilePath)); return LaunchFile(exePath, params); }
PrintData(BaseEngine *engine, PRINTER_INFO_2 *printerInfo, DEVMODE *devMode, Vec<PRINTPAGERANGE>& ranges, Print_Advanced_Data& advData, int rotation=0, Vec<SelectionOnPage> *sel=NULL) : engine(NULL), advData(advData), rotation(rotation) { if (engine) this->engine = engine->Clone(); if (printerInfo) { driverName.Set(str::Dup(printerInfo->pDriverName)); printerName.Set(str::Dup(printerInfo->pPrinterName)); portName.Set(str::Dup(printerInfo->pPortName)); } if (devMode) this->devMode.Set((LPDEVMODE)memdup(devMode, devMode->dmSize + devMode->dmDriverExtra)); if (!sel) this->ranges = ranges; else this->sel = *sel; }