Пример #1
0
bool StressTest::GoToNextFile()
{
    for (;;) {
        while (filesToOpen.Count() > 0) {
            // test next file
            ScopedMem<TCHAR> path(filesToOpen.At(0));
            filesToOpen.RemoveAt(0);
            if (!IsInRange(fileRanges, ++fileIndex))
                continue;
            if (OpenFile(path))
                return true;
        }

        if (dirsToVisit.Count() > 0) {
            // test next directory
            ScopedMem<TCHAR> path(dirsToVisit.At(0));
            dirsToVisit.RemoveAt(0);
            OpenDir(path);
            continue;
        }

        if (--cycles <= 0)
            return false;
        // start next cycle
        if (file::Exists(basePath))
            filesToOpen.Append(str::Dup(basePath));
        else
            OpenDir(basePath);
    }
}
Пример #2
0
bool ImageDirEngineImpl::LoadImageDir(const TCHAR *dirName)
{
    fileName = str::Dup(dirName);
    fileExt = _T("");

    ScopedMem<TCHAR> pattern(path::Join(dirName, _T("*")));

    WIN32_FIND_DATA fdata;
    HANDLE hfind = FindFirstFile(pattern, &fdata);
    if (INVALID_HANDLE_VALUE == hfind)
        return false;

    do {
        if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            if (ImageEngine::IsSupportedFile(fdata.cFileName))
                pageFileNames.Append(path::Join(dirName, fdata.cFileName));
        }
    } while (FindNextFile(hfind, &fdata));
    FindClose(hfind);

    if (pageFileNames.Count() == 0)
        return false;
    pageFileNames.SortNatural();

    pages.AppendBlanks(pageFileNames.Count());
    mediaboxes.AppendBlanks(pageFileNames.Count());

    return true;
}
Пример #3
0
static void StrVecTest()
{
    StrVec v;
    v.Append(str::Dup(_T("foo")));
    v.Append(str::Dup(_T("bar")));
    TCHAR *s = v.Join();
    assert(v.Count() == 2);
    assert(str::Eq(_T("foobar"), s));
    free(s);

    s = v.Join(_T(";"));
    assert(v.Count() == 2);
    assert(str::Eq(_T("foo;bar"), s));
    free(s);

    v.Append(str::Dup(_T("glee")));
    s = v.Join(_T("_ _"));
    assert(v.Count() == 3);
    assert(str::Eq(_T("foo_ _bar_ _glee"), s));
    free(s);

    v.Sort();
    s = v.Join();
    assert(str::Eq(_T("barfooglee"), s));
    free(s);

    {
        StrVec v2(v);
        assert(str::Eq(v2.At(1), _T("foo")));
        v2.Append(str::Dup(_T("nobar")));
        assert(str::Eq(v2.At(3), _T("nobar")));
        v2 = v;
        assert(v2.Count() == 3 && v2.At(0) != v.At(0));
        assert(str::Eq(v2.At(1), _T("foo")));
        assert(&v2.At(2) == v2.AtPtr(2) && str::Eq(*v2.AtPtr(2), _T("glee")));
    }

    {
        StrVec v2;
        size_t count = v2.Split(_T("a,b,,c,"), _T(","));
        assert(count == 5 && v2.Find(_T("c")) == 3);
        assert(v2.Find(_T("")) == 2 && v2.Find(_T(""), 3) == 4 && v2.Find(_T(""), 5) == -1);
        assert(v2.Find(_T("B")) == -1 && v2.FindI(_T("B")) == 1);
        ScopedMem<TCHAR> joined(v2.Join(_T(";")));
        assert(str::Eq(joined, _T("a;b;;c;")));
    }

    {
        StrVec v2;
        size_t count = v2.Split(_T("a,b,,c,"), _T(","), true);
        assert(count == 3 && v2.Find(_T("c")) == 2);
        ScopedMem<TCHAR> joined(v2.Join(_T(";")));
        assert(str::Eq(joined, _T("a;b;c")));
        ScopedMem<TCHAR> last(v2.Pop());
        assert(v2.Count() == 2 && str::Eq(last, _T("c")));
    }
}
Пример #4
0
// 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 TCHAR* srcfilename, UINT line, UINT col, Vec<size_t> &records)
{
    if (!srcfilename)
        return PDFSYNCERR_INVALID_ARGUMENT;

    ScopedMem<TCHAR> 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;
}
Пример #5
0
/* The html looks like:
<li>
  <object type="text/sitemap">
    <param name="Keyword" value="- operator">
    <param name="Name" value="Subtraction Operator (-)">
    <param name="Local" value="html/vsoprsubtract.htm">
    <param name="Name" value="Subtraction Operator (-)">
    <param name="Local" value="html/js56jsoprsubtract.htm">
  </object>
  <ul> ... optional children ... </ul>
<li>
  ... siblings ...
*/
static bool VisitChmIndexItem(EbookTocVisitor *visitor, HtmlElement *el, UINT cp, int level)
{
    CrashIf(!el->NameIs("li"));
    el = el->GetChildByName("object");
    if (!el)
        return false;

    StrVec references;
    ScopedMem<TCHAR> keyword, name;
    for (el = el->GetChildByName("param"); el; el = el->next) {
        if (!el->NameIs("param"))
            continue;
        ScopedMem<TCHAR> attrName(el->GetAttribute("name"));
        ScopedMem<TCHAR> attrVal(el->GetAttribute("value"));
#ifdef UNICODE
        if (attrName && attrVal && cp != CP_CHM_DEFAULT) {
            ScopedMem<char> bytes(str::conv::ToCodePage(attrVal, CP_CHM_DEFAULT));
            attrVal.Set(str::conv::FromCodePage(bytes, cp));
        }
#endif
        if (!attrName || !attrVal)
            /* ignore incomplete/unneeded <param> */;
        else if (str::EqI(attrName, _T("Keyword")))
            keyword.Set(attrVal.StealData());
        else if (str::EqI(attrName, _T("Name"))) {
            name.Set(attrVal.StealData());
            // some CHM documents seem to use a lonely Name instead of Keyword
            if (!keyword)
                keyword.Set(str::Dup(name));
        }
        else if (str::EqI(attrName, _T("Local")) && name) {
            // remove the ITS protocol and any filename references from the URLs
            if (str::Find(attrVal, _T("::/")))
                attrVal.Set(str::Dup(str::Find(attrVal, _T("::/")) + 3));
            references.Append(name.StealData());
            references.Append(attrVal.StealData());
        }
    }
    if (!keyword)
        return false;

    if (references.Count() == 2) {
        visitor->visit(keyword, references.At(1), level);
        return true;
    }
    visitor->visit(keyword, NULL, level);
    for (size_t i = 0; i < references.Count(); i += 2) {
        visitor->visit(references.At(i), references.At(i + 1), level + 1);
    }
    return true;
}
Пример #6
0
// extract ComicBookInfo metadata
// cf. http://code.google.com/p/comicbookinfo/
bool CbxEngineImpl::observe(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(_T("%s/%d"), propDate ? propDate : _T(""), atoi(value)));
    else if (json::Type_Number == type && str::Eq(path, "/ComicBookInfo/1.0/publicationMonth"))
        propDate.Set(str::Format(_T("%d%s"), atoi(value), propDate ? propDate : _T("")));
    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;
}
Пример #7
0
static void BenchDir(TCHAR *dir)
{
    StrVec files;
    ScopedMem<TCHAR> pattern(str::Format(_T("%s\\*.pdf"), dir));
    CollectPathsFromDirectory(pattern, files, false);
    for (size_t i = 0; i < files.Count(); i++) {
        BenchFile(files.At(i), NULL);
    }
}
Пример #8
0
bool StressTest::OpenDir(const TCHAR *dirPath)
{
    assert(filesToOpen.Count() == 0);

    bool hasFiles = CollectStressTestSupportedFilesFromDirectory(dirPath, fileFilter, filesToOpen);
    filesToOpen.SortNatural();

    ScopedMem<TCHAR> pattern(str::Format(_T("%s\\*"), dirPath));
    bool hasSubDirs = CollectPathsFromDirectory(pattern, dirsToVisit, true);

    return hasFiles || hasSubDirs;
}
Пример #9
0
int ImageDirEngineImpl::GetPageByLabel(const TCHAR *label)
{
    for (size_t i = 0; i < pageFileNames.Count(); i++) {
        const TCHAR *fileName = path::GetBaseName(pageFileNames.At(i));
        const TCHAR *fileExt = path::GetExt(fileName);
        if (str::StartsWithI(fileName, label) &&
            (fileName + str::Len(label) == fileExt || fileName[str::Len(label)] == '\0'))
            return (int)i + 1;
    }

    return BaseEngine::GetPageByLabel(label);
}
Пример #10
0
static bool SetupPluginMode(CommandLineInfo& i)
{
    if (!IsWindow(i.hwndPluginParent) || i.fileNames.Count() == 0)
        return false;

    gPluginURL = i.pluginURL;
    if (!gPluginURL)
        gPluginURL = i.fileNames.At(0);

    assert(i.fileNames.Count() == 1);
    while (i.fileNames.Count() > 1) {
        free(i.fileNames.Pop());
    }
    i.reuseInstance = i.exitOnPrint = false;
    // always display the toolbar when embedded (as there's no menubar in that case)
    gGlobalPrefs.toolbarVisible = true;
    // never allow esc as a shortcut to quit
    gGlobalPrefs.escToExit = false;
    // never show the sidebar by default
    gGlobalPrefs.tocVisible = false;
    if (DM_AUTOMATIC == gGlobalPrefs.defaultDisplayMode) {
        // if the user hasn't changed the default display mode,
        // display documents as single page/continuous/fit width
        // (similar to Adobe Reader, Google Chrome and how browsers display HTML)
        gGlobalPrefs.defaultDisplayMode = DM_CONTINUOUS;
        gGlobalPrefs.defaultZoom = ZOOM_FIT_WIDTH;
    }

    // extract some command line arguments from the URL's hash fragment where available
    // see http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf#nameddest=G4.1501531
    if (i.pluginURL && str::FindChar(i.pluginURL, '#')) {
        ScopedMem<TCHAR> args(str::Dup(str::FindChar(i.pluginURL, '#') + 1));
        str::TransChars(args, _T("#"), _T("&"));
        StrVec parts;
        parts.Split(args, _T("&"), true);
        for (size_t k = 0; k < parts.Count(); k++) {
            TCHAR *part = parts.At(k);
            int pageNo;
            if (str::StartsWithI(part, _T("page=")) && str::Parse(part + 4, _T("=%d%$"), &pageNo))
                i.pageNumber = pageNo;
            else if (str::StartsWithI(part, _T("nameddest=")) && part[10])
                str::ReplacePtr(&i.destName, part + 10);
            else if (!str::FindChar(part, '=') && part[0])
                str::ReplacePtr(&i.destName, part);
        }
    }

    return true;
}
Пример #11
0
void BenchFileOrDir(StrVec& pathsToBench)
{
    gLog = new slog::StderrLogger();

    size_t n = pathsToBench.Count() / 2;
    for (size_t i = 0; i < n; i++) {
        TCHAR *path = pathsToBench.At(2 * i);
        if (file::Exists(path))
            BenchFile(path, pathsToBench.At(2 * i + 1));
        else if (dir::Exists(path))
            BenchDir(path);
        else
            logbench("Error: file or dir %s doesn't exist", path);
    }

    delete gLog;
}
Пример #12
0
TCHAR *CbxEngineImpl::GetProperty(DocumentProperty prop)
{
    switch (prop) {
    case Prop_Title:
        return propTitle ? str::Dup(propTitle) : NULL;
    case Prop_Author:
        return propAuthors.Count() ? propAuthors.Join(_T(", ")) : NULL;
    case Prop_CreationDate:
        return propDate ? str::Dup(propDate) : NULL;
    case Prop_ModificationDate:
        return propModDate ? str::Dup(propModDate) : NULL;
    case Prop_CreatorApp:
        return propCreator ? str::Dup(propCreator) : NULL;
    // TODO: replace with Prop_Summary
    case Prop_Subject:
        return propSummary ? str::Dup(propSummary) : NULL;
    default:
        return NULL;
    }
}
Пример #13
0
static bool CollectStressTestSupportedFilesFromDirectory(const TCHAR *dirPath, const TCHAR *filter, StrVec& paths)
{
    ScopedMem<TCHAR> pattern(path::Join(dirPath, _T("*")));

    WIN32_FIND_DATA fdata;
    HANDLE hfind = FindFirstFile(pattern, &fdata);
    if (INVALID_HANDLE_VALUE == hfind)
        return false;

    do {
        if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            if (IsStressTestSupportedFile(fdata.cFileName, filter)) {
                paths.Append(path::Join(dirPath, fdata.cFileName));
            }
        }
    } while (FindNextFile(hfind, &fdata));
    FindClose(hfind);

    return paths.Count() > 0;
}
Пример #14
0
bool CollectPathsFromDirectory(const TCHAR *pattern, StrVec& paths, bool dirsInsteadOfFiles)
{
    ScopedMem<TCHAR> dirPath(path::GetDir(pattern));

    WIN32_FIND_DATA fdata;
    HANDLE hfind = FindFirstFile(pattern, &fdata);
    if (INVALID_HANDLE_VALUE == hfind)
        return false;

    do {
        bool append = !dirsInsteadOfFiles;
        if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            append = dirsInsteadOfFiles && !IsSpecialDir(fdata.cFileName);
        if (append)
            paths.Append(path::Join(dirPath, fdata.cFileName));
    } while (FindNextFile(hfind, &fdata));
    FindClose(hfind);

    return paths.Count() > 0;
}
Пример #15
0
// parses a list of page ranges such as 1,3-5,7- (i..e all but pages 2 and 6)
// into an interable list (returns NULL on parsing errors)
// caller must delete the result
static bool ParsePageRanges(const TCHAR *ranges, Vec<PageRange>& result)
{
    if (!ranges)
        return false;

    StrVec rangeList;
    rangeList.Split(ranges, _T(","), true);
    rangeList.SortNatural();

    for (size_t i = 0; i < rangeList.Count(); i++) {
        int start, end;
        if (str::Parse(rangeList.At(i), _T("%d-%d%$"), &start, &end) && 0 < start && start <= end)
            result.Append(PageRange(start, end));
        else if (str::Parse(rangeList.At(i), _T("%d-%$"), &start) && 0 < start)
            result.Append(PageRange(start, INT_MAX));
        else if (str::Parse(rangeList.At(i), _T("%d%$"), &start) && 0 < start)
            result.Append(PageRange(start, start));
        else
            return false;
    }

    return result.Count() > 0;
}
Пример #16
0
/* parse argument list. we assume that all unrecognized arguments are file names. */
void CommandLineInfo::ParseCommandLine(TCHAR *cmdLine)
{
    StrVec argList;
    ParseCmdLine(cmdLine, argList);
    size_t argCount = argList.Count();

#define is_arg(txt) str::EqI(_T(txt), argument)
#define is_arg_with_param(txt) (is_arg(txt) && param != NULL)
#define additional_param() argList.At(n + 1)
#define has_additional_param() ((argCount > n + 1) && ('-' != additional_param()[0]))

    for (size_t n = 1; n < argCount; n++) {
        TCHAR *argument = argList.At(n);
        TCHAR *param = NULL;
        if (argCount > n + 1)
            param = argList.At(n + 1);

        if (is_arg("-register-for-pdf")) {
            makeDefault = true;
            exitImmediately = true;
            return;
        }
        else if (is_arg("-silent")) {
            // silences errors happening during -print-to and -print-to-default
            silent = true;
        }
        else if (is_arg("-print-to-default")) {
            TCHAR *name = GetDefaultPrinterName();
            if (name) {
                str::ReplacePtr(&printerName, name);
                free(name);
            }
        }
        else if (is_arg_with_param("-print-to")) {
            str::ReplacePtr(&printerName, argList.At(++n));
        }
        else if (is_arg("-print-dialog")) {
            printDialog = true;
        }
        else if (is_arg_with_param("-print-settings")) {
            // argument is a comma separated list of page ranges and
            // advanced options [even|odd] and [noscale|shrink|fit]
            // e.g. -print-settings "1-3,5,10-8,odd,fit"
            str::ReplacePtr(&printSettings, argList.At(++n));
            str::RemoveChars(printSettings, _T(" "));
        }
        else if (is_arg("-exit-on-print")) {
            // only affects -print-dialog (-print-to and -print-to-default
            // always exit on print)
            exitOnPrint = true;
        }
        else if (is_arg_with_param("-bgcolor") || is_arg_with_param("-bg-color")) {
            // -bgcolor is for backwards compat (was used pre-1.3)
            // -bg-color is for consistency
            ParseColor(&bgColor, argList.At(++n));
        }
        else if (is_arg_with_param("-inverse-search")) {
            str::ReplacePtr(&inverseSearchCmdLine, argList.At(++n));
        }
        else if ((is_arg_with_param("-forward-search") ||
                  is_arg_with_param("-fwdsearch")) && argCount > n + 2) {
            // -forward-search is for consistency with -inverse-search
            // -fwdsearch is for consistency with -fwdsearch-*
            str::ReplacePtr(&forwardSearchOrigin, argList.At(++n));
            forwardSearchLine = _ttoi(argList.At(++n));
        }
        else if (is_arg_with_param("-fwdsearch-offset")) {
            fwdSearch.offset = _ttoi(argList.At(++n));
        }
        else if (is_arg_with_param("-fwdsearch-width")) {
            fwdSearch.width = _ttoi(argList.At(++n));
        }
        else if (is_arg_with_param("-fwdsearch-color")) {
            ParseColor(&fwdSearch.color, argList.At(++n));
        }
        else if (is_arg_with_param("-fwdsearch-permanent")) {
            fwdSearch.permanent = _ttoi(argList.At(++n));
        }
        else if (is_arg("-esc-to-exit")) {
            escToExit = true;
        }
        else if (is_arg("-reuse-instance")) {
            // find the window handle of a running instance of SumatraPDF
            // TODO: there should be a mutex here to reduce possibility of
            // race condition and having more than one copy launch because
            // FindWindow() in one process is called before a window is created
            // in another process
            reuseInstance = (FindWindow(FRAME_CLASS_NAME, 0) != NULL);
        }
        else if (is_arg_with_param("-lang")) {
            free(lang);
            lang = str::conv::ToAnsi(argList.At(++n));
        }
        else if (is_arg_with_param("-nameddest") || is_arg_with_param("-named-dest")) {
            // -nameddest is for backwards compat (was used pre-1.3)
            // -named-dest is for consistency
            str::ReplacePtr(&destName, argList.At(++n));
        }
        else if (is_arg_with_param("-page")) {
            pageNumber = _ttoi(argList.At(++n));
        }
        else if (is_arg("-restrict")) {
            restrictedUse = true;
        }
        // TODO: remove -invert-colors and -set-color-range in favor
        //       of the UI settable gGlobalPrefs.useSysColors(?)
        else if (is_arg("-invertcolors") || is_arg("-invert-colors")) {
            // -invertcolors is for backwards compat (was used pre-1.3)
            // -invert-colors is for consistency
            // -invert-colors is a shortcut for -set-color-range 0xFFFFFF 0x000000
            // (i.e. it sets white as foreground color and black as background color)
            colorRange[0] = WIN_COL_WHITE;
            colorRange[1] = WIN_COL_BLACK;
        }
        else if (is_arg("-set-color-range") && argCount > n + 2) {
            STATIC_ASSERT(sizeof(colorRange[0]) == sizeof(int), colorref_as_int);
            ParseColor((int *)&colorRange[0], argList.At(++n));
            ParseColor((int *)&colorRange[1], argList.At(++n));
        }
        else if (is_arg("-presentation")) {
            enterPresentation = true;
        }
        else if (is_arg("-fullscreen")) {
            enterFullscreen = true;
        }
        else if (is_arg_with_param("-view")) {
            ParseViewMode(&startView, argList.At(++n));
        }
        else if (is_arg_with_param("-zoom")) {
            ParseZoomValue(&startZoom, argList.At(++n));
        }
        else if (is_arg_with_param("-scroll")) {
            ParseScrollValue(&startScroll, argList.At(++n));
        }
        else if (is_arg("-console")) {
            showConsole = true;
        }
        else if (is_arg_with_param("-plugin")) {
            // -plugin [<URL>] <parent HWND>
            if (!str::IsDigit(*param) && has_additional_param())
                str::ReplacePtr(&pluginURL, argList.At(++n));
            // the argument is a (numeric) window handle to
            // become the parent of a frameless SumatraPDF
            // (used e.g. for embedding it into a browser plugin)
            hwndPluginParent = (HWND)_ttol(argList.At(++n));
        }
        else if (is_arg_with_param("-stress-test")) {
            // -stress-test <file or dir path> [<file filter>] [<page/file range(s)>] [<cycle count>x]
            // e.g. -stress-test file.pdf 25x  for rendering file.pdf 25 times
            //      -stress-test file.pdf 1-3  render only pages 1, 2 and 3 of file.pdf
            //      -stress-test dir 301- 2x   render all files in dir twice, skipping first 300
            //      -stress-test dir *.pdf;*.xps  render all files in dir that are either PDF or XPS
            str::ReplacePtr(&stressTestPath, argList.At(++n));
            int num;
            if (has_additional_param() && str::FindChar(additional_param(), '*')) {
                str::ReplacePtr(&stressTestFilter, additional_param());
                n++;
            }
            if (has_additional_param() && IsValidPageRange(additional_param())) {
                str::ReplacePtr(&stressTestRanges, additional_param());
                n++;
            }
            if (has_additional_param() && str::Parse(additional_param(), _T("%dx%$"), &num) && num > 0) {
                stressTestCycles = num;
                n++;
            }
        }
        else if (is_arg_with_param("-bench")) {
            TCHAR *s = str::Dup(argList.At(++n));
            pathsToBenchmark.Push(s);
            s = NULL;
            if (has_additional_param() && IsBenchPagesInfo(additional_param())) {
                s = str::Dup(additional_param());
                n++;
            }
            pathsToBenchmark.Push(s);
            exitImmediately = true;
        } else if (is_arg("-crash-on-open")) {
            // to make testing of crash reporting system in pre-release/release
            // builds possible
            crashOnOpen = true;
        } else if (is_arg_with_param("-manga-mode")) {
            // TODO: we should have a ui for this instead of remembering it globally
            // in prefs
            TCHAR *s = argList.At(++n);
            cbxR2L = str::EqI(_T("true"), s) || str::Eq(_T("1"), s);
        }
#ifdef DEBUG
        else if (is_arg("-enum-printers")) {
            EnumeratePrinters();
            /* this is for testing only, exit immediately */
            exitImmediately = true;
            return;
        }
#endif
        else {
            // Remember this argument as a filename to open
            TCHAR *filepath = NULL;
            if (str::EndsWithI(argList.At(n), _T(".lnk")))
                filepath = ResolveLnk(argList.At(n));
            if (!filepath)
                filepath = str::Dup(argList.At(n));
            fileNames.Push(filepath);
        }
    }
#undef is_arg
#undef is_arg_with_param
#undef additional_param
#undef has_additional_param
}
Пример #17
0
// see http://itexmac.sourceforge.net/pdfsync.html for the specification
int Pdfsync::RebuildIndex()
{
    size_t len;
    ScopedMem<char> data(file::ReadAll(syncfilepath, &len));
    if (!data)
        return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED;
    // convert the file data into a list of zero-terminated strings
    str::TransChars(data, "\r\n", "\0\0");

    // parse preamble (jobname and version marker)
    char *line = data;
    char *dataEnd = data + len;

    // replace star by spaces (TeX uses stars instead of spaces in filenames)
    str::TransChars(line, "*/", " \\");
    ScopedMem<TCHAR> jobName(str::conv::FromAnsi(line));
    jobName.Set(str::Join(jobName, _T(".tex")));
    jobName.Set(PrependDir(jobName));

    line = Advance0Line(line, dataEnd);
    UINT versionNumber = 0;
    if (!line || !str::Parse(line, "version %u", &versionNumber) || versionNumber != 1)
        return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED;

    // reset synchronizer database
    srcfiles.Reset();
    lines.Reset();
    points.Reset();
    fileIndex.Reset();
    sheetIndex.Reset();

    Vec<size_t> filestack;
    UINT page = 1;
    sheetIndex.Append(0);

    // add the initial tex file to the source file stack
    filestack.Push(srcfiles.Count());
    srcfiles.Append(jobName.StealData());
    PdfsyncFileIndex findex = { 0 };
    fileIndex.Append(findex);

    PdfsyncLine psline;
    PdfsyncPoint pspoint;

    // parse data
    UINT maxPageNo = engine->PageCount();
    while ((line = Advance0Line(line, dataEnd))) {
        switch (*line) {
        case 'l':
            psline.file = filestack.Last();
            if (str::Parse(line, "l %u %u %u", &psline.record, &psline.line, &psline.column))
                lines.Append(psline);
            else if (str::Parse(line, "l %u %u", &psline.record, &psline.line)) {
                psline.column = 0;
                lines.Append(psline);
            }
            // else dbg("Bad 'l' line in the pdfsync file");
            break;

        case 's':
            if (str::Parse(line, "s %u", &page))
                sheetIndex.Append(points.Count());
            // else dbg("Bad 's' line in the pdfsync file");
            // if (0 == page || page > maxPageNo)
            //     dbg("'s' line with invalid page number in the pdfsync file");
            break;

        case 'p':
            pspoint.page = page;
            if (0 == page || page > maxPageNo)
                /* ignore point for invalid page number */;
            else if (str::Parse(line, "p %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y))
                points.Append(pspoint);
            else if (str::Parse(line, "p* %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y))
                points.Append(pspoint);
            // else dbg("Bad 'p' line in the pdfsync file");
            break;

        case '(':
            {
                ScopedMem<TCHAR> filename(str::conv::FromAnsi(line + 1));
                // if the filename contains quotes then remove them
                // TODO: this should never happen!?
                if (filename[0] == '"' && filename[str::Len(filename) - 1] == '"')
                    filename.Set(str::DupN(filename + 1, str::Len(filename) - 2));
                // undecorate the filepath: replace * by space and / by \ 
                str::TransChars(filename, _T("*/"), _T(" \\"));
                // if the file name extension is not specified then add the suffix '.tex'
                if (str::IsEmpty(path::GetExt(filename)))
                    filename.Set(str::Join(filename, _T(".tex")));
                // ensure that the path is absolute
                if (PathIsRelative(filename))
                    filename.Set(PrependDir(filename));

                filestack.Push(srcfiles.Count());
                srcfiles.Append(filename.StealData());
                findex.start = findex.end = lines.Count();
                fileIndex.Append(findex);
            }
            break;

        case ')':
            if (filestack.Count() > 1)
                fileIndex.At(filestack.Pop()).end = lines.Count();
            // else dbg("Unbalanced ')' line in the pdfsync file");
            break;

        default:
            // dbg("Ignoring invalid pdfsync line starting with '%c'", *line);
            break;
        }
    }

    fileIndex.At(0).end = lines.Count();
    assert(filestack.Count() == 1);

    return Synchronizer::RebuildIndex();
}