Example #1
0
static void DeserializeStruct(PrefInfo *info, size_t count, void *structBase, BencDict *prefs)
{
    char *base = (char *)structBase;
    BencInt *intObj;
    BencString *strObj;
    BencArray *arrObj;

    for (size_t i = 0; i < count; i++) {
        PrefInfo& meta = info[i];
        switch (meta.type) {
        case Pref_Bool:
            if ((intObj = prefs->GetInt(meta.name)))
                *(bool *)(base + meta.offset) = intObj->Value() != 0;
            break;
        case Pref_Int:
            if ((intObj = prefs->GetInt(meta.name)))
                *(int *)(base + meta.offset) = (int)intObj->Value();
            break;
        case Pref_Str:
            if ((strObj = prefs->GetString(meta.name)))
                str::ReplacePtr((char **)(base + meta.offset), strObj->RawValue());
            break;
        case Pref_WStr:
            if ((strObj = prefs->GetString(meta.name))) {
                ScopedMem<WCHAR> str(strObj->Value());
                if (str)
                    str::ReplacePtr((WCHAR **)(base + meta.offset), str);
            }
            break;
        case Pref_DisplayMode:
            if ((strObj = prefs->GetString(meta.name))) {
                ScopedMem<WCHAR> mode(strObj->Value());
                if (mode)
                    DisplayModeConv::EnumFromName(mode, (DisplayMode *)(base + meta.offset));
            }
            break;
        case Pref_Float:
            if ((strObj = prefs->GetString(meta.name))) {
                // note: this might round the value for files produced with versions
                //       prior to 1.6 and on a system where the decimal mark isn't a '.'
                //       (the difference should be hardly notable, though)
                *(float *)(base + meta.offset) = (float)atof(strObj->RawValue());
            }
            break;
        case Pref_IntVec:
            if ((arrObj = prefs->GetArray(meta.name))) {
                size_t len = arrObj->Length();
                Vec<int> *intVec = new Vec<int>(len);
                if (intVec) {
                    for (size_t idx = 0; idx < len; idx++) {
                        if ((intObj = arrObj->GetInt(idx)))
                            intVec->Append((int)intObj->Value());
                    }
                    delete *(Vec<int> **)(base + meta.offset);
                    *(Vec<int> **)(base + meta.offset) = intVec;
                }
            }
            break;
        case Pref_UILang:
            if ((strObj = prefs->GetString(meta.name))) {
                // ensure language code is valid
                const char *langCode = trans::ValidateLangCode(strObj->RawValue());
                if (langCode)
                    *(const char **)(base + meta.offset) = langCode;
            }
            break;
        }
    }
}
Example #2
0
static void SerializeAdvancedSettings(const WCHAR *filepath, SettingInfo *info, size_t count, void *structBase)
{
    char *base = (char *)structBase;
    const WCHAR *section = NULL;
    bool skipSection = false;
    ScopedMem<WCHAR> strValue;

    for (size_t i = 0; i < count; i++) {
        SettingInfo& meta = info[i];
        CrashIf(meta.type != SType_Section && !section);
        if (meta.type != SType_Section && skipSection)
            continue;
        switch (meta.type) {
        case SType_Section:
            section = meta.name;
            skipSection = !meta.offset;
            break;
        case SType_Bool:
            strValue.Set(str::Format(L"%d", *(bool *)(base + meta.offset) ? 1 : 0));
            WritePrivateProfileString(section, meta.name, strValue, filepath);
            break;
        case SType_Color:
            strValue.Set(str::Format(L"#%06X", (int)*(COLORREF *)(base + meta.offset)));
            WritePrivateProfileString(section, meta.name, strValue, filepath);
            break;
        case SType_Int:
            strValue.Set(str::Format(L"%d", *(int *)(base + meta.offset)));
            WritePrivateProfileString(section, meta.name, strValue, filepath);
            break;
        case SType_String:
            WritePrivateProfileString(section, meta.name, ((ScopedMem<WCHAR> *)(base + meta.offset))->Get(), filepath);
            break;
        case SType_BoolVec:
            {
                Vec<bool> *vec = (Vec<bool> *)(base + meta.offset);
                for (size_t n = 1; n < vec->Count(); n++) {
                    ScopedMem<WCHAR> key(str::Format(L"%u.%s", n, meta.name));
                    strValue.Set(str::Format(L"%d", vec->At(n) ? 1 : 0));
                    WritePrivateProfileString(section, key, strValue, filepath);
                }
            }
            break;
        case SType_ColorVec:
            {
                Vec<COLORREF> *vec = (Vec<COLORREF> *)(base + meta.offset);
                for (size_t n = 1; n < vec->Count(); n++) {
                    ScopedMem<WCHAR> key(str::Format(L"%u.%s", n, meta.name));
                    strValue.Set(str::Format(L"#%06X", (int)vec->At(n)));
                    WritePrivateProfileString(section, key, strValue, filepath);
                }
            }
            break;
        case SType_IntVec:
            {
                Vec<int> *vec = (Vec<int> *)(base + meta.offset);
                for (size_t n = 1; n < vec->Count(); n++) {
                    ScopedMem<WCHAR> key(str::Format(L"%u.%s", n, meta.name));
                    strValue.Set(str::Format(L"%d", vec->At(n)));
                    WritePrivateProfileString(section, key, strValue, filepath);
                }
            }
            break;
        case SType_StringVec:
            {
                WStrVec *vec = (WStrVec *)(base + meta.offset);
                for (size_t n = 1; n < vec->Count(); n++) {
                    ScopedMem<WCHAR> key(str::Format(L"%u.%s", n, meta.name));
                    WritePrivateProfileString(section, key, vec->At(n), filepath);
                }
            }
            break;
        }
    }
}
Example #3
0
static void VecTest()
{
    Vec<int> ints;
    assert(ints.Count() == 0);
    ints.Append(1);
    ints.Push(2);
    ints.InsertAt(0, -1);
    assert(ints.Count() == 3);
    assert(ints.At(0) == -1 && ints.At(1) == 1 && ints.At(2) == 2);
    assert(ints.At(0) == -1 && ints.Last() == 2);
    int last = ints.Pop();
    assert(last == 2);
    assert(ints.Count() == 2);
    ints.Push(3);
    ints.RemoveAt(0);
    assert(ints.Count() == 2);
    assert(ints.At(0) == 1 && ints.At(1) == 3);
    ints.Reset();
    assert(ints.Count() == 0);

    for (int i = 0; i < 1000; i++) {
        ints.Push(i);
    }
    assert(ints.Count() == 1000 && ints.At(500) == 500);
    ints.Remove(500);
    assert(ints.Count() == 999 && ints.At(500) == 501);
    last = ints.Pop();
    assert(last == 999);
    ints.Append(last);
    assert(ints.AtPtr(501) == &ints.At(501));

    {
        Vec<int> ints2(ints);
        assert(ints2.Count() == 999);
        assert(ints.LendData() != ints2.LendData());
        ints.Remove(600);
        assert(ints.Count() < ints2.Count());
        ints2 = ints;
        assert(ints2.Count() == 998);
    }

    {
        char buf[2] = {'a', '\0'};
        str::Str<char> v(0);
        for (int i = 0; i < 7; i++) {
            v.Append(buf, 1);
            buf[0] = buf[0] + 1;
        }
        char *s = v.LendData();
        assert(str::Eq("abcdefg", s));
        assert(7 == v.Count());
        v.Set("helo");
        assert(4 == v.Count());
        assert(str::Eq("helo", v.LendData()));
    }

    {
        str::Str<char> v(128);
        v.Append("boo", 3);
        assert(str::Eq("boo", v.LendData()));
        assert(v.Count() == 3);
        v.Append("fop");
        assert(str::Eq("boofop", v.LendData()));
        assert(v.Count() == 6);
        v.RemoveAt(2, 3);
        assert(v.Count() == 3);
        assert(str::Eq("bop", v.LendData()));
        v.Append('a');
        assert(v.Count() == 4);
        assert(str::Eq("bopa", v.LendData()));
        char *s = v.StealData();
        assert(str::Eq("bopa", s));
        free(s);
        assert(v.Count() == 0);
    }

    {
        str::Str<char> v(0);
        for (int i = 0; i < 32; i++) {
            assert(v.Count() == i * 6);
            v.Append("lambd", 5);
            if (i % 2 == 0)
                v.Append('a');
            else
                v.Push('a');
        }

        for (int i=1; i<=16; i++) {
            v.RemoveAt((16 - i) * 6, 6);
            assert(v.Count() == (32 - i) * 6);
        }

        v.RemoveAt(0, 6 * 15);
        assert(v.Count() == 6);
        char *s = v.LendData();
        assert(str::Eq(s, "lambda"));
        s = v.StealData();
        assert(str::Eq(s, "lambda"));
        free(s);
        assert(v.Count() == 0);

        v.Append("lambda");
        assert(str::Eq(v.LendData(), "lambda"));
        char c = v.Pop();
        assert(c == 'a');
        assert(str::Eq(v.LendData(), "lambd"));
    }

    VecTestAppendFmt();

    {
        Vec<PointI *> v;
        srand((unsigned int)time(NULL));
        for (int i = 0; i < 128; i++) {
            v.Append(new PointI(i, i));
            size_t pos = rand() % v.Count();
            v.InsertAt(pos, new PointI(i, i));
        }
        assert(v.Count() == 128 * 2);
        size_t idx = 0;
        for (PointI **p = v.IterStart(); p; p = v.IterNext()) {
            assert(idx == v.IterIdx());
            ++idx;
        }

        while (v.Count() > 64) {
            size_t pos = rand() % v.Count();
            PointI *f = v.At(pos);
            v.Remove(f);
            delete f;
        }
        DeleteVecMembers(v);
    }

    {
        Vec<int> v;
        v.Append(2);
        for (int i = 0; i < 500; i++)
            v.Append(4);
        v.At(250) = 5;
        v.Reverse();
        assert(v.Count() == 501 && v.At(0) == 4 && v.At(249) == v.At(251) && v.At(250) == 5 && v.At(500) == 2);
        v.Remove(4);
        v.Reverse();
        assert(v.Count() == 500 && v.At(0) == 2 && v.At(249) == v.At(251) && v.At(250) == 5 && v.At(499) == 4);
    }
}
Example #4
0
int SyncTex::SourceToDoc(const WCHAR* srcfilename, UINT line, UINT col, UINT* page, Vec<RectI>& rects) {
    if (IsIndexDiscarded()) {
        if (RebuildIndex() != PDFSYNCERR_SUCCESS)
            return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED;
    }
    AssertCrash(this->scanner);

    AutoFreeW srcfilepath;
    // convert the source file to an absolute path
    if (PathIsRelative(srcfilename))
        srcfilepath.Set(PrependDir(srcfilename));
    else
        srcfilepath.SetCopy(srcfilename);
    if (!srcfilepath)
        return PDFSYNCERR_OUTOFMEMORY;

    bool isUtf8 = true;
    char* mb_srcfilepath = str::conv::ToUtf8(srcfilepath).StealData();
TryAgainAnsi:
    if (!mb_srcfilepath)
        return PDFSYNCERR_OUTOFMEMORY;
    int ret = synctex_display_query(this->scanner, mb_srcfilepath, line, col);
    free(mb_srcfilepath);
    // recent SyncTeX versions encode in UTF-8 instead of ANSI
    if (isUtf8 && -1 == ret) {
        isUtf8 = false;
        mb_srcfilepath = str::conv::ToAnsi(srcfilepath).StealData();
        goto TryAgainAnsi;
    }

    if (-1 == ret)
        return PDFSYNCERR_UNKNOWN_SOURCEFILE;
    if (0 == ret)
        return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD;

    synctex_node_t node;
    int firstpage = -1;
    rects.Reset();

    while ((node = synctex_next_result(this->scanner)) != nullptr) {
        if (firstpage == -1) {
            firstpage = synctex_node_page(node);
            if (firstpage <= 0 || firstpage > engine->PageCount())
                continue;
            *page = (UINT)firstpage;
        }
        if (synctex_node_page(node) != firstpage)
            continue;

        RectD rc;
        rc.x = synctex_node_box_visible_h(node);
        rc.y = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node);
        rc.dx = synctex_node_box_visible_width(node),
        rc.dy = synctex_node_box_visible_height(node) + synctex_node_box_visible_depth(node);
        rects.Push(rc.Round());
    }

    if (firstpage <= 0)
        return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD;
    return PDFSYNCERR_SUCCESS;
}
Example #5
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 WCHAR* srcfilename, UINT line, UINT col, Vec<size_t>& records) {
    UNUSED(col);
    if (!srcfilename)
        return PDFSYNCERR_INVALID_ARGUMENT;

    AutoFreeW srcfilepath;
    // convert the source file to an absolute path
    if (PathIsRelative(srcfilename))
        srcfilepath.Set(PrependDir(srcfilename));
    else
        srcfilepath.SetCopy(srcfilename);
    if (!srcfilepath)
        return PDFSYNCERR_OUTOFMEMORY;

    // find the source file entry
    size_t isrc;
    for (isrc = 0; isrc < srcfiles.size(); isrc++)
        if (path::IsSame(srcfilepath, srcfiles.at(isrc)))
            break;
    if (isrc == srcfiles.size())
        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.size() && lines.at(i).line == lines.at(lineIx).line; i++)
        records.Push(lines.at(i).record);

    return PDFSYNCERR_SUCCESS;
}
Example #6
0
// see http://itexmac.sourceforge.net/pdfsync.html for the specification
int Pdfsync::RebuildIndex() {
    OwnedData data(file::ReadFile(syncfilepath));
    if (!data.data) {
        return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED;
    }
    // convert the file data into a list of zero-terminated strings
    str::TransChars(data.data, "\r\n", "\0\0");

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

    // replace star by spaces (TeX uses stars instead of spaces in filenames)
    str::TransChars(line, "*/", " \\");
    AutoFreeW jobName(str::conv::FromAnsi(line));
    jobName.Set(str::Join(jobName, L".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.size());
    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)) != nullptr) {
        if (!line)
            break;
        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.size());
                // 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 '(': {
                AutoFreeW 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 \ (backslash)
                str::TransChars(filename, L"*/", L" \\");
                // if the file name extension is not specified then add the suffix '.tex'
                if (str::IsEmpty(path::GetExt(filename)))
                    filename.Set(str::Join(filename, L".tex"));
                // ensure that the path is absolute
                if (PathIsRelative(filename))
                    filename.Set(PrependDir(filename));

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

            case ')':
                if (filestack.size() > 1)
                    fileIndex.at(filestack.Pop()).end = lines.size();
                // 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.size();
    AssertCrash(filestack.size() == 1);

    return Synchronizer::RebuildIndex();
}