bool Delete(int index) { if (index < Count()) { free(text.At(index)); text.RemoveAt(index); return true; } return false; }
WCHAR *DirFileProvider::NextFile() { while (filesToOpen.Count() > 0) { ScopedMem<WCHAR> path(filesToOpen.At(0)); filesToOpen.RemoveAt(0); return path.StealData(); } if (dirsToVisit.Count() > 0) { // test next directory ScopedMem<WCHAR> path(dirsToVisit.At(0)); dirsToVisit.RemoveAt(0); OpenDir(path); return NextFile(); } return NULL; }
static size_t GetAllMatchingFiles(const WCHAR *dir, const WCHAR *filter, WStrVec& files, bool showProgress) { WStrVec dirsToVisit; dirsToVisit.Append(str::Dup(dir)); while (dirsToVisit.Count() > 0) { if (showProgress) { wprintf(L"."); fflush(stdout); } ScopedMem<WCHAR> path(dirsToVisit[0]); dirsToVisit.RemoveAt(0); CollectStressTestSupportedFilesFromDirectory(path, filter, files); ScopedMem<WCHAR> pattern(str::Format(L"%s\\*", path)); CollectPathsFromDirectory(pattern, dirsToVisit, true); } return files.Count(); }
// removes thumbnails that don't belong to any frequently used item in file history void CleanUpThumbnailCache(FileHistory& fileHistory) { ScopedMem<WCHAR> thumbsPath(AppGenDataFilename(THUMBNAILS_DIR_NAME)); if (!thumbsPath) return; ScopedMem<WCHAR> pattern(path::Join(thumbsPath, L"*.png")); WStrVec files; WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(pattern, &fdata); if (INVALID_HANDLE_VALUE == hfind) return; do { if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) files.Append(str::Dup(fdata.cFileName)); } while (FindNextFile(hfind, &fdata)); FindClose(hfind); Vec<DisplayState *> list; fileHistory.GetFrequencyOrder(list); for (size_t i = 0; i < list.Count() && i < FILE_HISTORY_MAX_FREQUENT * 2; i++) { ScopedMem<WCHAR> bmpPath(GetThumbnailPath(list.At(i)->filePath)); if (!bmpPath) continue; int idx = files.Find(path::GetBaseName(bmpPath)); if (idx != -1) { CrashIf(idx < 0 || files.Count() <= (size_t)idx); WCHAR *fileName = files.At(idx); files.RemoveAt(idx); free(fileName); } } for (size_t i = 0; i < files.Count(); i++) { ScopedMem<WCHAR> bmpPath(path::Join(thumbsPath, files.At(i))); file::Delete(bmpPath); } }
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int retCode = 1; // by default it's error #ifdef DEBUG // Memory leak detection (only enable _CRTDBG_LEAK_CHECK_DF for // regular termination so that leaks aren't checked on exceptions, // aborts, etc. where some clean-up might not take place) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF); //_CrtSetBreakAlloc(421); TryLoadMemTrace(); #endif DisableDataExecution(); // ensure that C functions behave consistently under all OS locales // (use Win32 functions where localized input or output is desired) setlocale(LC_ALL, "C"); // don't show system-provided dialog boxes when accessing files on drives // that are not mounted (e.g. a: drive without floppy or cd rom drive // without a cd). SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); #if defined(DEBUG) || defined(SVN_PRE_RELEASE_VER) if (str::StartsWith(lpCmdLine, "/tester")) { extern int TesterMain(); // in Tester.cpp return TesterMain(); } if (str::StartsWith(lpCmdLine, "/regress")) { extern int RegressMain(); // in Regress.cpp return RegressMain(); } #endif #ifdef SUPPORTS_AUTO_UPDATE if (str::StartsWith(lpCmdLine, "-autoupdate")) { bool quit = AutoUpdateMain(); if (quit) return 0; } #endif srand((unsigned int)time(NULL)); // load uiautomationcore.dll before installing crash handler (i.e. initializing // dbghelp.dll), so that we get function names/offsets in GetCallstack() uia::Initialize(); #ifdef DEBUG dbghelp::RememberCallstackLogs(); #endif SetupCrashHandler(); ScopedOle ole; InitAllCommonControls(); ScopedGdiPlus gdiPlus(true); mui::Initialize(); uitask::Initialize(); prefs::Load(); CommandLineInfo i(GetCommandLine()); SetCurrentLang(i.lang ? i.lang : gGlobalPrefs->uiLanguage); // This allows ad-hoc comparison of gdi, gdi+ and gdi+ quick when used // in layout #if 0 RedirectIOToConsole(); BenchEbookLayout(L"C:\\kjk\\downloads\\pg12.mobi"); system("pause"); goto Exit; #endif if (i.showConsole) { RedirectIOToConsole(); RedirectDllIOToConsole(); } if (i.makeDefault) AssociateExeWithPdfExtension(); if (i.pathsToBenchmark.Count() > 0) { BenchFileOrDir(i.pathsToBenchmark); if (i.showConsole) system("pause"); } if (i.exitImmediately) goto Exit; gCrashOnOpen = i.crashOnOpen; gPolicyRestrictions = GetPolicies(i.restrictedUse); GetFixedPageUiColors(gRenderCache.textColor, gRenderCache.backgroundColor); DebugGdiPlusDevice(gUseGdiRenderer); if (!RegisterWinClass()) goto Exit; CrashIf(hInstance != GetModuleHandle(NULL)); if (!InstanceInit(nCmdShow)) goto Exit; if (i.hwndPluginParent) { if (!SetupPluginMode(i)) goto Exit; } if (i.printerName) { // note: this prints all PDF files. Another option would be to // print only the first one for (size_t n = 0; n < i.fileNames.Count(); n++) { bool ok = PrintFile(i.fileNames.At(n), i.printerName, !i.silent, i.printSettings); if (!ok) retCode++; } --retCode; // was 1 if no print failures, turn 1 into 0 goto Exit; } bool showStartPage = i.fileNames.Count() == 0 && gGlobalPrefs->rememberOpenedFiles && gGlobalPrefs->showStartPage; if (showStartPage) { // make the shell prepare the image list, so that it's ready when the first window's loaded SHFILEINFO sfi; SHGetFileInfo(L".pdf", 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES); } if (gGlobalPrefs->reopenOnce) { WStrVec moreFileNames; ParseCmdLine(gGlobalPrefs->reopenOnce, moreFileNames); moreFileNames.Reverse(); for (WCHAR **fileName = moreFileNames.IterStart(); fileName; fileName = moreFileNames.IterNext()) { i.fileNames.Append(*fileName); } moreFileNames.RemoveAt(0, moreFileNames.Count()); str::ReplacePtr(&gGlobalPrefs->reopenOnce, NULL); } HANDLE hMutex = NULL; HWND hPrevWnd = NULL; if (i.printDialog || i.stressTestPath || gPluginMode) { // TODO: pass print request through to previous instance? } else if (i.reuseDdeInstance) { hPrevWnd = FindWindow(FRAME_CLASS_NAME, NULL); } else if (gGlobalPrefs->reuseInstance || gGlobalPrefs->useTabs) { hPrevWnd = FindPrevInstWindow(&hMutex); } if (hPrevWnd) { for (size_t n = 0; n < i.fileNames.Count(); n++) { OpenUsingDde(hPrevWnd, i.fileNames.At(n), i, 0 == n); } goto Exit; } WindowInfo *win = NULL; for (size_t n = 0; n < i.fileNames.Count(); n++) { win = LoadOnStartup(i.fileNames.At(n), i, !win); if (!win) { retCode++; continue; } if (i.printDialog) OnMenuPrint(win, i.exitWhenDone); } if (i.fileNames.Count() > 0 && !win) { // failed to create any window, even though there // were files to load (or show a failure message for) goto Exit; } if (i.printDialog && i.exitWhenDone) goto Exit; if (!win) { win = CreateAndShowWindowInfo(); if (!win) goto Exit; } UpdateUITextForLanguage(); // needed for RTL languages if (win->IsAboutWindow()) { // TODO: shouldn't CreateAndShowWindowInfo take care of this? UpdateToolbarAndScrollbarState(*win); } // Make sure that we're still registered as default, // if the user has explicitly told us to be if (gGlobalPrefs->associatedExtensions) RegisterForPdfExtentions(win->hwndFrame); if (i.stressTestPath) { // don't save file history and preference changes gPolicyRestrictions = (gPolicyRestrictions | Perm_RestrictedUse) & ~Perm_SavePreferences; RebuildMenuBarForWindow(win); StartStressTest(&i, win, &gRenderCache); } if (gGlobalPrefs->checkForUpdates) UpdateCheckAsync(win, true); // only hide newly missing files when showing the start page on startup if (showStartPage && gFileHistory.Get(0)) { gFileExistenceChecker = new FileExistenceChecker(); gFileExistenceChecker->Start(); } // call this once it's clear whether Perm_SavePreferences has been granted prefs::RegisterForFileChanges(); retCode = RunMessageLoop(); SafeCloseHandle(&hMutex); CleanUpThumbnailCache(gFileHistory); Exit: prefs::UnregisterForFileChanges(); while (gWindows.Count() > 0) { DeleteWindowInfo(gWindows.At(0)); } #ifndef DEBUG // leave all the remaining clean-up to the OS // (as recommended for a quick exit) ExitProcess(retCode); #else DeleteObject(GetDefaultGuiFont()); DeleteBitmap(gBitmapReloadingCue); DeleteSplitterBrush(); // wait for FileExistenceChecker to terminate // (which should be necessary only very rarely) while (gFileExistenceChecker) { Sleep(10); uitask::DrainQueue(); } mui::Destroy(); uitask::Destroy(); trans::Destroy(); SaveCallstackLogs(); dbghelp::FreeCallstackLogs(); // must be after uitask::Destroy() because we might have queued prefs::Reload() // which crashes if gGlobalPrefs is freed gFileHistory.UpdateStatesSource(NULL); DeleteGlobalPrefs(gGlobalPrefs); // it's still possible to crash after this (destructors of static classes, // atexit() code etc.) point, but it's very unlikely UninstallCrashHandler(); // output leaks after all destructors of static objects have run _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); return retCode; #endif }