コード例 #1
0
// FIXME: Not covered by tests
void DFMarkupCompatibilityProcessAttr(DFMarkupCompatibility *mc, Tag attr, const char *value, DFNameMap *map)
{
    const char **tokens = DFStringTokenize(value,isspace);
    for (int tokIndex = 0; tokens[tokIndex]; tokIndex++) {
        const char *component = tokens[tokIndex];

        char *prefix = NULL;
        char *localName = NULL;
        const char *colon = strchr(component,':');
        if (colon != NULL) {
            size_t colonPos = colon - component;
            prefix = DFSubstring(component,0,colonPos);
            localName = DFSubstring(component,colonPos+1,strlen(component));
        }
        else {
            prefix = xstrdup(component);
            localName = NULL;
        }

        const char *nsIdStr = NULL;

        // Find namespace ID for prefix
        for (int recordIndex = mc->depth-1; recordIndex >= 0; recordIndex--) {
            MCRecord *record = &mc->records[recordIndex];
            if (record->namespaces != NULL)
                nsIdStr = DFHashTableLookup(record->namespaces,prefix);
        }

        if (nsIdStr != NULL) {

            NamespaceID nsId = atoi(nsIdStr);
            Tag tag = 0;

            const NamespaceDecl *nsDecl = DFNameMapNamespaceForID(map,nsId);

            if (localName != NULL)
                tag = DFNameMapTagForName(map,nsDecl->namespaceURI,localName);

            switch (attr) {
                case MC_IGNORABLE:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionIgnore);
                    break;
                case MC_PROCESSCONTENT:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionProcessContent);
                    break;
                case MC_MUSTUNDERSTAND:
                    addDeclToRecord(&mc->records[mc->depth-1],nsId,tag,MCActionMustUnderstand);
                    break;
            }
        }
        free(prefix);
        free(localName);
    }
    free(tokens);
}
コード例 #2
0
static char *trimmedSubstring(CSSParser *p, size_t start, size_t pos)
{
    char *untrimmed = DFSubstring(p->chars,start,pos);
    char *trimmed = DFStringTrimWhitespace(untrimmed);
    free(untrimmed);
    return trimmed;
}
コード例 #3
0
ファイル: TextPackage.c プロジェクト: flyonok/DocFormats
static int processIncludes(TextPackage *package, const char *input, DFBuffer *output, const char *path, DFError **error)
{
    int ok = 1;
    const char **lines = DFStringSplit(input,"\n",0);
    for (int lineno = 0; lines[lineno] && ok; lineno++) {
        const char *line = lines[lineno];
        if (DFStringHasPrefix(line,"#include \"") && DFStringHasSuffix(line,"\"")) {
            char *inclRelPath = DFSubstring(line,10,strlen(line)-1);
            char *inclAbsPath = DFAppendPathComponent(path,inclRelPath);
            char *inclDirName = DFPathDirName(inclAbsPath);
            char *inclContent = DFStringReadFromFile(inclAbsPath,error);
            if (inclContent == NULL) {
                DFErrorFormat(error,"%s: %s",inclRelPath,DFErrorMessage(error));
                ok = 0;
            }
            else if (!processIncludes(package,inclContent,output,inclDirName,error)) {
                ok = 0;
            }
            free(inclRelPath);
            free(inclAbsPath);
            free(inclDirName);
            free(inclContent);
        }
        else {
            DFBufferFormat(output,"%s\n",line);
        }
    }
    free(lines);
    return ok;
}
コード例 #4
0
ファイル: TextPackage.c プロジェクト: flyonok/DocFormats
static int parsePackage(TextPackage *package, const char *string, const char *path, DFError **error)
{
    DFBuffer *replaced = DFBufferNew();
    if (!strcmp(path,""))
        path = ".";

    if (!processIncludes(package,string,replaced,path,error)) {
        DFBufferRelease(replaced);
        return 0;
    }


    char *currentKey = strdup("");
    DFBuffer *currentValue = DFBufferNew();
    const char **lines = DFStringSplit(replaced->data,"\n",0);
    for (int lineno = 0; lines[lineno]; lineno++) {
        const char *line = lines[lineno];

        if (!DFStringHasPrefix(line,"#")) {
            DFBufferFormat(currentValue,"%s\n",line);
        }
        else if (DFStringHasPrefix(line,"#item ")) {
            package->keys = (char **)realloc(package->keys,(package->nkeys+2)*sizeof(char *));
            package->keys[package->nkeys++] = strdup(currentKey);
            package->keys[package->nkeys] = NULL;
            DFHashTableAdd(package->items,currentKey,currentValue->data);
            free(currentKey);
            DFBufferRelease(currentValue);
            currentKey = DFSubstring(line,6,strlen(line));
            currentValue = DFBufferNew();
        }
        else if (DFStringHasPrefix(line,"##")) {
            DFBufferFormat(currentValue,"%s\n",&line[1]);
        }
        else {
            DFErrorFormat(error,"Unknown command: %s on line %d",line,(lineno+1));
            return 0;
        }
    }
    package->keys = (char **)realloc(package->keys,(package->nkeys+2)*sizeof(char *));
    package->keys[package->nkeys++] = strdup(currentKey);
    package->keys[package->nkeys] = NULL;
    DFHashTableAdd(package->items,currentKey,currentValue->data);

    free(lines);
    free(currentKey);
    DFBufferRelease(currentValue);
    DFBufferRelease(replaced);
    return 1;
}
コード例 #5
0
DFArray *CSSParserContent(CSSParser *p)
{
    DFArray *result = DFArrayNew((DFCopyFunction)ContentPartRetain,(DFFreeFunction)ContentPartRelease);
    matchWhitespace(p);
    while (p->pos < p->length) {
        size_t start = p->pos;
        switch (p->chars[p->pos]) {
            case '"':
            case '\'': {
                int invalid = 0;
                if (!matchString(p,&invalid))
                    return result;
                char *quotedValue = trimmedSubstring(p,start,p->pos);
                char *unquotedValue = DFUnquote(quotedValue);
                ContentPart *part = ContentPartNew(ContentPartString,unquotedValue,NULL);
                DFArrayAppend(result,part);
                ContentPartRelease(part);
                free(quotedValue);
                free(unquotedValue);
                if ((p->pos < p->length) && !matchWhitespace(p))
                    return result;
                break;
            }
            case 'C':
            case 'c': {
                if (matchSpecific(p,"counters(")) {
                    // Not yet supported
                    return result;
                }
                else if (matchSpecific(p,"counter(")) {
                    size_t nameStart = p->pos;
                    if (!matchIdent(p))
                        return result;
                    char *name = DFSubstring(p->chars,nameStart,p->pos);

                    char *type = NULL;
                    if (match(p,',')) {
                        size_t typeStart = p->pos;
                        if (!matchIdent(p)) {
                            free(name);
                            free(type);
                            return result;
                        }
                        type = DFSubstring(p->chars,typeStart,p->pos);
                    }

                    ContentPart *part = ContentPartNew(ContentPartCounter,name,type);
                    DFArrayAppend(result,part);
                    ContentPartRelease(part);

                    if (!match(p,')')) {
                        free(name);
                        free(type);
                        return result;
                    }

                    if ((p->pos < p->length) && !matchWhitespace(p)) {
                        free(name);
                        free(type);
                        return result;
                    }

                    free(name);
                    free(type);
                }
                else {
                    return result;
                }
                break;
            }
            default:
                return result;
        }
    }
    return result;
}
コード例 #6
0
ファイル: WordConverter.c プロジェクト: flyonok/DocFormats
char *WordStyleIdForStyle(CSSStyle *style)
{
    const char *selector = style->selector;
    char *resStyleId = NULL;

    if (!strcmp(selector,"table.Normal_Table"))
        return strdup("TableNormal");
    if (!strcmp(selector,"table.Table_Grid"))
        return strdup("TableGrid");
    if (!strcmp(selector,"span.Default_Paragraph_Font"))
        return strdup("DefaultParagraphFont");
    if (!strcmp(selector,"p.List_Paragraph"))
        return strdup("ListParagraph");

    int headingLevel = CSSSelectorHeadingLevel(selector);
    if (headingLevel != 0) {
        char *prefix = DFFormatString("heading_%d",headingLevel);
        if ((style->className != NULL) && DFStringHasPrefix(style->className,prefix)) {
            char *rest = DFSubstring(style->className,strlen(prefix),strlen(style->className));
            char *result = DFFormatString("Heading%d%s",headingLevel,rest);
            free(rest);
            free(prefix);
            return result;
        }
        free(prefix);
    }

    if (!strcmp(selector,"span.Heading1Char"))
        return strdup("Heading1Char");
    if (!strcmp(selector,"span.Heading2Char"))
        return strdup("Heading2Char");
    if (!strcmp(selector,"span.Heading3Char"))
        return strdup("Heading3Char");
    if (!strcmp(selector,"span.Heading4Char"))
        return strdup("Heading4Char");
    if (!strcmp(selector,"span.Heading5Char"))
        return strdup("Heading5Char");
    if (!strcmp(selector,"span.Heading6Char"))
        return strdup("Heading6Char");
    if (!strcmp(selector,"span.Heading7Char"))
        return strdup("Heading7Char");
    if (!strcmp(selector,"span.Heading8Char"))
        return strdup("Heading8Char");
    if (!strcmp(selector,"span.Heading9Char"))
        return strdup("Heading9Char");

    char *className = CSSSelectorCopyClassName(selector);
    switch (CSSSelectorGetTag(selector)) {
        case HTML_FIGURE: {
            resStyleId = DFStrDup("Figure");
            break;
        }
        case HTML_CAPTION: {
            resStyleId = DFStrDup("Caption");
            break;
        }
        case HTML_H1:
        case HTML_H2:
        case HTML_H3:
        case HTML_H4:
        case HTML_H5:
        case HTML_H6: {
            if ((className == NULL) || (strlen(className) == 0)) {
                int level = CSSSelectorHeadingLevel(selector);
                if ((level >= 1) && (level <= 6)) {
                    // FIXME: we shouldn't rely on the specific word "Heading" here - instead using the localised name
                    // FIXME: not covered by tests
                    resStyleId = DFFormatString("Heading%d",level);
                }
            }
            else {
                resStyleId = DFStrDup(className);
            }
            break;
        }
        case HTML_P:
            resStyleId = DFStrDup(className);
            break;
        case HTML_SPAN:
            resStyleId = DFStrDup(className);
            break;
        case HTML_TABLE:
            resStyleId = DFStrDup(className);
            break;
    }
    free(className);

    if (resStyleId == NULL) {
        // Note: selector here may start with . (i.e. applies to all elements)
        // FIXME: not covered by tests
        resStyleId = strdup(selector);
    }

    return resStyleId;
}
コード例 #7
0
ファイル: WordConverter.c プロジェクト: flyonok/DocFormats
static void extractPrefixRecursive(DFNode *node, const char *counterName, DFBuffer *result,
                                   int *foundSeq, int *foundContent)
{
    if (isSeqField(node)) {
        if (result->len > 0)
            DFBufferFormat(result," ");
        DFBufferFormat(result,"counter(%s)",counterName);
        *foundSeq = 1;
        DFRemoveNode(node);
        return;
    }

    if (node->tag == DOM_TEXT) {
        size_t valueLen = strlen(node->value);
        size_t pos = 0;

        if (*foundSeq) {
            size_t offset = 0;
            uint32_t ch;
            do {
                pos = offset;
                ch = DFNextChar(node->value,&offset);
            } while ((ch != 0) && (DFCharIsWhitespaceOrNewline(ch) || DFCharIsPunctuation(ch)));
        }
        else {
            pos = valueLen;
        }

        if (pos == valueLen) {
            if (result->len > 0)
                DFBufferFormat(result," ");
            char *quotedValue = DFQuote(node->value);
            DFBufferFormat(result,"%s",quotedValue);
            free(quotedValue);
            DFRemoveNode(node);
            if (*foundSeq)
                *foundContent = 1;
            return;
        }
        else if (pos > 0) {
            char *first = DFSubstring(node->value,0,pos);
            char *rest = DFSubstring(node->value,pos,valueLen);
            if (result->len > 0)
                DFBufferFormat(result," ");
            char *quotedFirst = DFQuote(first);
            DFBufferFormat(result,"%s",quotedFirst);
            free(quotedFirst);
            DFSetNodeValue(node,rest);
            if (*foundSeq)
                *foundContent = 1;
            free(first);
            free(rest);
            return;
        }
    }

    int wasEmpty = (node->first == NULL);
    DFNode *next;
    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;
        if (*foundContent)
            break;
        extractPrefixRecursive(child,counterName,result,foundSeq,foundContent);
    }
    int isEmpty = (node->first == NULL);
    if ((node->tag == HTML_SPAN) && isEmpty && !wasEmpty)
        DFRemoveNode(node);
}