示例#1
0
void RTFGenParser::tag_end(const QString &tagName)
{
    // Roll back until we find our tag.
    bool found = false;
    for(Tag* pTag = m_tags.peek(); pTag != NULL && !found; pTag = m_tags.peek())
    {
        if (pTag->name == tagName)
        {
            found = true;
        }

        if (pTag->hasCharStyle())
        {
            CharStyle style = *(pTag->pCharStyle);

            // We must pop here, so that getTopTagWithCharStyle will find a parent tag.
            m_tags.pop();
            pTag = NULL; // to avoid confusion

            Tag* pParentTag = m_tags.getTopTagWithCharStyle();
            if (pParentTag != NULL)
            {
                if (pParentTag->hasCharStyle())
                {
                    CharStyle* pParentStyle = pParentTag->pCharStyle;

                    // Roll back the character style. This is regardless of whether
                    // we found the closed tag; we just collapse all styles on our way.
                    QString rtf = pParentStyle->getDiffRTF(style);
                    if (!rtf.isEmpty())
                    {
                        res += rtf.utf8();
                        m_bSpace = true;
                    }
                }
            }
        }
        else // if this tag has no char style attached
        {
            m_tags.pop(); // just pop the tag out
            pTag = NULL; // to avoid confusion
        }
        
        if (found)
        {
            if (tagName.lower() == "p")
            {
                res += "\\par";
                m_bSpace = true;
            }
        }
    }
}
示例#2
0
void RTFGenParser::tag_start(const QString &tagName, const list<QString> &attrs)
{
    if (m_res_size)
        return;
    CharStyle parentStyle, style;
    {
        Tag* pParentTag = m_tags.getTopTagWithCharStyle();
        if (pParentTag != NULL)
        {
            parentStyle = *(pParentTag->pCharStyle);
        }
    }
    style = parentStyle;
    if ((tagName == "b") || (tagName == "i") || (tagName == "u") ||
            (tagName == "font") || (tagName == "p") || (tagName == "span")){
        QString tag = tagName;
        QString option;
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
            QString key = *it;
            ++it;
            QString value = *it;
            option += " ";
            option += key;
            if (!value.isEmpty()){
                option += "=\"";
                option += value;
                option += "\"";
            }
        }
        tags.push(tag);
        options.push(option);
    }

    if (tagName == "b"){
        style.bold = true;
    }
    else if (tagName == "i"){
        style.italic = true;
    }
    else if (tagName == "u"){
        style.underline = true;
    }
    else if (tagName == "font"){
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); it++){
            QString name = (*it);
            ++it;
            QString value = (*it);
            if (name == "color")
            {
                style.colorIdx = getColorIdx(value);
            }
            else if (name == "face")
            {
                style.faceIdx = getFontFaceIdx(value);
            }
            else if (name == "size")
            {
                int logicalSize = value.toInt();
                if (value[0] == '+' || value[0] == '-')
                    logicalSize += 3;
                if (logicalSize < 1)
                    logicalSize = 1;
                else if (logicalSize > 7)
                    logicalSize = 7;
                style.sizePt = htmlFontSizeToPt(logicalSize);
            }
        }
    }
    else if (tagName == "p"){
        m_paragraphDir = DirUnknown;
        m_lastParagraphPos = res.length();
        m_bSpace = true;
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
            QString name = (*it).lower();
            ++it;
            QString value = (*it);
            if (name == "dir")
            {
                QString dir = value.lower();
                if (dir == "ltr")
                {
                    res += "\\ltrpar";
                    m_paragraphDir = DirLTR;
                }
                if (dir == "rtl")
                {
                    res += "\\rtlpar";
                    m_paragraphDir = DirRTL;
                }
            }
        }

    }
    else if (tagName == "br"){
        res += "\\line";
        m_bSpace = true;
    }
    else if (tagName == "img"){
        QString src;
        QString alt;
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
            QString name = (*it);
            ++it;
            QString value = (*it);
            if (name == "src"){
                src = value;
                break;
            }
            if (name == "alt"){
                alt = value;
                break;
            }
        }
        if (src.left(5) == "icon:"){
            list<string> smiles = getIcons()->getSmile(src.mid(5).toLatin1());
            for (list<string>::iterator its = smiles.begin(); its != smiles.end(); ++its){
                string s = *its;
                for (unsigned nSmile = 0; nSmile < 26; nSmile++){
                    if (s != def_smiles[nSmile])
                        continue;
                    res += "<##icqimage00";
                    char buf[4];
                    sprintf(buf, "%02X", nSmile);
                    res += buf;
                    res += ">";
                    return;
                }
            }
            if (!smiles.empty()){
                text(QString::fromUtf8(smiles.front().c_str()));
                return;
            }
        }
        text(alt);
        return;
    }

    // Process attributes which all tags share.

    for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
        QString name = (*it).lower();
        ++it;
        QString value = (*it);

        // Any tag might have a STYLE.
        if (name == "style"){
            // A really crude CSS parser goes here:
            QRegExp cssReNum("[0-9]+");
            list<QString> cssProp = parseStyle(value);
            for (list<QString>::iterator it = cssProp.begin(); it != cssProp.end(); ++it){
                QString cssPropName = *it;
                ++it;
                if (it == cssProp.end())
                    break;
                QString cssPropValue = *it;
                if (cssPropName == "font-family")
                {
                    style.faceIdx = getFontFaceIdx(cssPropValue);
                }
                else if (cssPropName == "font-size")
                {
                    cssPropValue = cssPropValue.lower();
                    int length;
                    if (cssReNum.indexIn(cssPropValue, 0) == 0){
			length = cssReNum.matchedLength();
                        float number = cssPropValue.left(length).toFloat();
                        QString type = cssPropValue.mid(length);
                        if (type == "pt")
                        {
                            style.sizePt = static_cast<int>(number);
                        }
                        else if (type == "px")
                        {
                            // for now, handle like 'pt', though it's wrong
                            style.sizePt = static_cast<int>(number);
                        }
                        else if (type == "%")
                        {
                            style.sizePt = static_cast<int>(parentStyle.sizePt * (number/100));
                        }
                        // We don't handle 'cm', 'em' etc.
                    }
                    else if (cssPropValue == "smaller")
                    {
                        // FONT SIZE=3 is 'normal', 2 is 'smaller'
                        style.sizePt = htmlFontSizeToPt(2, parentStyle.sizePt);
                    }
                    else if (cssPropValue == "larger")
                    {
                        // FONT SIZE=3 is 'normal', 4 is 'larger'
                        style.sizePt = htmlFontSizeToPt(4, parentStyle.sizePt);
                    }

                    // We don't handle 'small', 'medium' etc. It goes too far
                    // beyond our basic implementation.
                    // Also, empty 'type' would be invalid CSS, thus ignored.
                }
                else if (cssPropName == "font-style")
                {
                    style.italic = (cssPropValue.lower() == "italic");
                }
                else if (cssPropName == "font-weight")
                {
                    style.bold = (cssPropValue.toInt() >= 600);
                }
                else if (cssPropName == "text-decoration")
                {
                    style.underline = (cssPropValue.lower() == "underline");
                }
                else if (cssPropName == "color")
                {
                    style.colorIdx = getColorIdx(cssPropValue);
                }
                else if (cssPropName == "background-color")
                {
                    style.bgColorIdx = getColorIdx(cssPropValue);
                }
            }
        }
    }

    Tag& tag = *(m_tags.pushNew());
    tag.name = tagName;
    // Check if anything changed in the style.
    // Only then the tag deserves getting a charStyle.
    if (parentStyle != style)
    {
        QString rtf = style.getDiffRTF(parentStyle);
        if (!rtf.isEmpty())
        {
            res += static_cast<string>(rtf.toUtf8());
            m_bSpace = true;
        }
        tag.setCharStyle(style);
    }
}
示例#3
0
string RTFGenParser::parse(const QString &text)
{
    res = "";
    m_res_size = 0;
    m_codec = getContacts()->getCodec(m_contact);
    int charset = 0;
    for (const ENCODING *c = getContacts()->getEncodings(); c->language; c++){
        if (!strcasecmp(c->codec, m_codec->name())){
            charset = c->rtf_code;
            break;
        }
    }
#ifdef WIN32
    if ((charset == 0) && !strcasecmp(m_codec->name(), "system")){
        char buff[256];
        int res = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, (char*)&buff, sizeof(buff));
        if (res){
            unsigned codepage = atol(buff);
            if (codepage){
                for (const rtf_cp *c = rtf_cps; c->cp; c++){
                    if (c->cp == codepage)
                        charset = c->charset;
                }
            }
        }
    }
#endif
    unsigned ansicpg = 0;
    const char *send_encoding = 0;
    m_codec = NULL;
    if (charset){
        for (const ENCODING *c = getContacts()->getEncodings(); c->language; c++){
            if ((c->rtf_code == charset) && c->bMain){
                send_encoding = c->codec;
                m_codec = getContacts()->getCodecByName(send_encoding);
                ansicpg = c->cp_code;
                break;
            }
        }
    }

    // Add defaults to the tables
    m_fontFaces.push_back("MS Sans Serif");
    m_colors.push_back(m_foreColor);
    // Create a "fake" tag which'll serve as the default style
    CharStyle style;
    style.faceIdx = 0;
    style.colorIdx = 1; // colors are 1-based (0 = default)
    style.sizePt = 12; // default according to Microsoft
    Tag& tag = *(m_tags.pushNew());
    tag.setCharStyle(style);

    // Assume we go immediately after a tag.
    m_bSpace = true;
    HTMLParser::parse(text);

    string s;
    s = "{\\rtf1\\ansi";
    if (ansicpg){
        s += "\\ansicpg";
        s += number(ansicpg);
    }
    s += "\\deff0\r\n";
    s += "{\\fonttbl";
    unsigned n = 0;
    for (list<QString>::iterator it_face = m_fontFaces.begin(); it_face != m_fontFaces.end(); it_face++, n++){
        s += "{\\f";
        s += number(n);
        QString face = (*it_face);
        if (face.find("Times") >= 0){
            s += "\\froman";
        }else if (face.find("Courier") >= 0){
            s += "\\fmodern";
        }else{
            s += "\\fswiss";
        }
        if (charset){
            s += "\\fcharset";
            s += number(charset);
        }
        s += " ";
        int pos = face.find(QRegExp(" +["));
        if (pos > 0)
            face = face.left(pos);
        s += static_cast<string>(face.toLatin1());
        s += ";}";
    }
    s += "}\r\n";
    s += "{\\colortbl ;";
    for (list<QColor>::iterator it_colors = m_colors.begin(); it_colors != m_colors.end(); ++it_colors){
        QColor c = *it_colors;
        s += "\\red";
        s += number(c.red());
        s += "\\green";
        s += number(c.green());
        s += "\\blue";
        s += number(c.blue());
        s += ";";
    }
    s += "}\r\n";
    s += "\\viewkind4\\pard";
    s += static_cast<string>(style.getDiffRTF(CharStyle()).toUtf8());
    s += res;
    s += "\r\n}\r\n";

    log(L_DEBUG, "Resulting RTF: %s", s.c_str());

    return s;
}
示例#4
0
void RTFGenParser::tag_start(const QString &tagName, const list<QString> &attrs)
{
    CharStyle parentStyle, style;
    {
        Tag* pParentTag = m_tags.getTopTagWithCharStyle();
        if (pParentTag != NULL)
        {
            parentStyle = *(pParentTag->pCharStyle);
        }
    }
    style = parentStyle;

    if (tagName == "b"){
        style.bold = true;
    }
    else if (tagName == "i"){
        style.italic = true;
    }
    else if (tagName == "u"){
        style.underline = true;
    }
    else if (tagName == "font"){
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); it++){
            QString name = (*it);
            ++it;
            QString value = (*it);
            if (name == "color")
            {
                style.colorIdx = getColorIdx(value);
            }
            else if (name == "face")
            {
                style.faceIdx = getFontFaceIdx(value);
            }
            else if (name == "size")
            {
                int logicalSize = value.toInt();
                if (value[0] == '+' || value[0] == '-')
                    logicalSize += 3;
                if (logicalSize < 1)
                    logicalSize = 1;
                else if (logicalSize > 7)
                    logicalSize = 7;
                style.sizePt = htmlFontSizeToPt(logicalSize);
            }
        }
    }
    else if (tagName == "p"){
        m_paragraphDir = DirUnknown;
        m_lastParagraphPos = res.length();
        m_bSpace = true;
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
            QString name = (*it).lower();
            ++it;
            QString value = (*it);
            if (name == "dir")
            {
                QString dir = value.lower();
                if (dir == "ltr")
                {
                    res += "\\ltrpar";
                    m_paragraphDir = DirLTR;
                }
                if (dir == "rtl")
                {
                    res += "\\rtlpar";
                    m_paragraphDir = DirRTL;
                }
            }
        }

    }
    else if (tagName == "br"){
        res += "\\line";
        m_bSpace = true;
    }
    else if (tagName == "img"){
        QString src;
        for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
            QString name = (*it);
            ++it;
            QString value = (*it);
            if (name == "src"){
                src = value;
                break;
            }
        }
        if (src.left(10) != "icon:smile")
            return;
        bool bOK;
        unsigned nSmile = src.mid(10).toUInt(&bOK, 16);
        if (!bOK)
            return;
        if (nSmile < 16){
            res += "<##icqimage000";
            if (nSmile < 10){
                res += (char)(nSmile + '0');
            }else{
                res += (char)(nSmile - 10 + 'A');
            }
            res += ">";
            return;
        }
        const smile *p = smiles(nSmile);
        if (p)
            res += p->paste;
        return;
    }

    // Process attributes which all tags share.

    for (list<QString>::const_iterator it = attrs.begin(); it != attrs.end(); ++it){
        QString name = (*it).lower();
        ++it;
        QString value = (*it);

        // Any tag might have a STYLE.
        if (name == "style"){
            // A really crude CSS parser goes here:
            QRegExp cssReNum("[0-9]+");
            list<QString> cssProp = parseStyle(value);
            for (list<QString>::iterator it = cssProp.begin(); it != cssProp.end(); ++it){
                QString cssPropName = *it;
                ++it;
                if (it == cssProp.end())
                    break;
                QString cssPropValue = *it;
                if (cssPropName == "font-family")
                {
                    style.faceIdx = getFontFaceIdx(cssPropValue);
                }
                else if (cssPropName == "font-size")
                {
                    cssPropValue = cssPropValue.lower();
                    int length;
                    if (cssReNum.match(cssPropValue, 0, &length) == 0){
                        float number = cssPropValue.left(length).toFloat();
                        QString type = cssPropValue.mid(length);
                        if (type == "pt")
                        {
                            style.sizePt = static_cast<int>(number);
                        }
                        else if (type == "px")
                        {
                            // for now, handle like 'pt', though it's wrong
                            style.sizePt = static_cast<int>(number);
                        }
                        else if (type == "%")
                        {
                            style.sizePt = static_cast<int>(parentStyle.sizePt * (number/100));
                        }
                        // We don't handle 'cm', 'em' etc.
                    }
                    else if (cssPropValue == "smaller")
                    {
                        // FONT SIZE=3 is 'normal', 2 is 'smaller'
                        style.sizePt = htmlFontSizeToPt(2, parentStyle.sizePt);
                    }
                    else if (cssPropValue == "larger")
                    {
                        // FONT SIZE=3 is 'normal', 4 is 'larger'
                        style.sizePt = htmlFontSizeToPt(4, parentStyle.sizePt);
                    }

                    // We don't handle 'small', 'medium' etc. It goes too far
                    // beyond our basic implementation.
                    // Also, empty 'type' would be invalid CSS, thus ignored.
                }
                else if (cssPropName == "font-style")
                {
                    style.italic = (cssPropValue.lower() == "italic");
                }
                else if (cssPropName == "font-weight")
                {
                    style.bold = (cssPropValue.toInt() >= 600);
                }
                else if (cssPropName == "text-decoration")
                {
                    style.underline = (cssPropValue.lower() == "underline");
                }
                else if (cssPropName == "color")
                {
                    style.colorIdx = getColorIdx(cssPropValue);
                }
                else if (cssPropName == "background-color")
                {
                    style.bgColorIdx = getColorIdx(cssPropValue);
                }
            }
        }
    }

    Tag& tag = *(m_tags.pushNew());
    tag.name = tagName;
    // Check if anything changed in the style.
    // Only then the tag deserves getting a charStyle.
    if (parentStyle != style)
    {
        QString rtf = style.getDiffRTF(parentStyle);
        if (!rtf.isEmpty())
        {
            res += rtf.utf8();
            m_bSpace = true;
        }
        tag.setCharStyle(style);
    }
}