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;
}
Ejemplo n.º 2
0
// 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;
}
Ejemplo n.º 3
0
// 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;
}
Ejemplo n.º 4
0
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();
}
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;
}
Ejemplo n.º 6
0
static void DeserializeAdvancedSettings(const WCHAR *filepath, SettingInfo *info, size_t count, void *structBase)
{
    char *base = (char *)structBase;
    const WCHAR *section = NULL;
    INT intValue, intValueDef;
    ScopedMem<WCHAR> strValue;

    for (size_t i = 0; i < count; i++) {
        SettingInfo& meta = info[i];
        CrashIf(meta.type != SType_Section && !section);
        switch (meta.type) {
        case SType_Section:
            section = meta.name;
            break;
        case SType_Bool:
            intValueDef = *(bool *)(base + meta.offset) ? 1 : 0;
            intValue = GetPrivateProfileInt(section, meta.name, intValueDef, filepath);
            *(bool *)(base + meta.offset) = intValue != 0;
            break;
        case SType_Color:
            strValue.Set(ReadIniString(filepath, section, meta.name));
            if (str::Parse(strValue, L"#%6x", &intValue))
                *(COLORREF *)(base + meta.offset) = (COLORREF)intValue;
            break;
        case SType_Int:
            intValueDef = *(int *)(base + meta.offset);
            intValue = GetPrivateProfileInt(section, meta.name, intValueDef, filepath);
            *(int *)(base + meta.offset) = intValue;
            break;
        case SType_String:
            strValue.Set(ReadIniString(filepath, section, meta.name, L"\n"));
            if (!str::Eq(strValue, L"\n"))
                ((ScopedMem<WCHAR> *)(base + meta.offset))->Set(strValue.StealData());
            break;
        case SType_BoolVec:
        case SType_ColorVec:
        case SType_IntVec:
        case SType_StringVec:
            ScopedMem<WCHAR> sections(ReadIniString(filepath, section, NULL));
            for (const WCHAR *name = sections; *name; name += str::Len(name) + 1) {
                UINT idx;
                if (str::Eq(str::Parse(name, L"%u.", &idx), meta.name)) {
                    if (SType_BoolVec == meta.type) {
                        bool value = GetPrivateProfileInt(section, name, 0, filepath) != 0;
                        ((Vec<bool> *)(base + meta.offset))->InsertAt(idx, value);
                    }
                    else if (SType_ColorVec == meta.type) {
                        strValue.Set(ReadIniString(filepath, section, name));
                        if (str::Parse(strValue, L"#%6x", &intValue)) {
                            COLORREF value = (COLORREF)intValue;
                            ((Vec<COLORREF> *)(base + meta.offset))->InsertAt(idx, value);
                        }
                    }
                    else if (SType_IntVec == meta.type) {
                        intValue = GetPrivateProfileInt(section, name, 0, filepath);
                        ((Vec<int> *)(base + meta.offset))->InsertAt(idx, intValue);
                    }
                    else {
                        strValue.Set(ReadIniString(filepath, section, name));
                        WStrVec *strVec = (WStrVec *)(base + meta.offset);
                        // TODO: shouldn't InsertAt free the previous string?
                        if (idx < strVec->Count())
                            free(strVec->At(idx));
                        strVec->InsertAt(idx, strValue.StealData());
                    }
                }
            }
            break;
        }
    }
}