Subversion Repositories Scribus

Rev

Rev 25069 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
411 Franz 7
/***************************************************************************
8
 *   Copyright (C) 2004 by Riku Leino                                      *
1157 tsoots 9
 *   tsoots@gmail.com                                                      *
411 Franz 10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU General Public License as published by  *
13
 *   the Free Software Foundation; either version 2 of the License, or     *
14
 *   (at your option) any later version.                                   *
15
 *                                                                         *
16
 *   This program is distributed in the hope that it will be useful,       *
17
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19
 *   GNU General Public License for more details.                          *
20
 *                                                                         *
21
 *   You should have received a copy of the GNU General Public License     *
22
 *   along with this program; if not, write to the                         *
23
 *   Free Software Foundation, Inc.,                                       *
18122 mrdocs 24
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
411 Franz 25
 ***************************************************************************/
26
 
27
#include "contentreader.h"
13805 jghali 28
#include "gtparagraphstyle.h"
411 Franz 29
 
30
#ifdef HAVE_XML
31
 
13805 jghali 32
#include "scribusstructs.h"
9535 fschmid 33
#include <QByteArray>
2986 craig 34
 
22528 craig 35
ContentReader* ContentReader::creader = nullptr;
411 Franz 36
 
37
extern xmlSAXHandlerPtr cSAXHandler;
38
 
22635 craig 39
ContentReader::ContentReader(const QString& documentName, StyleReader *s, gtWriter *w, bool textOnly)
411 Franz 40
{
41
        creader = this;
42
        docname = documentName;
43
        sreader = s;
44
        writer  = w;
45
        importTextOnly = textOnly;
46
}
47
 
24341 jghali 48
bool ContentReader::startElement(const QString &name, const SXWAttributesMap &attrs)
411 Franz 49
{
50
        if ((name == "text:p") || (name == "text:h"))
51
        {
12143 jghali 52
                ++append;
24341 jghali 53
                QString name = attrs.value("text:style-name");
54
                if (!name.isEmpty())
55
                        styleNames.push_back(name);
439 tsoots 56
                if (!inList)
57
                {
58
                        pstyle = sreader->getStyle(name);
59
                        currentStyle = pstyle;
60
                }
61
                else
62
                {
63
                        gtStyle *tmp = sreader->getStyle(getName());
10427 cbradney 64
                        if ((tmp->getName()).indexOf("default-style") != -1)
439 tsoots 65
                                getStyle();
66
                        else
67
                                currentStyle = tmp;
68
                }
411 Franz 69
        }
70
        else if (name == "text:span")
71
        {
72
                inSpan = true;
24341 jghali 73
                QString styleName = attrs.value("text:style-name");
74
                if (!styleName.isEmpty())
411 Franz 75
                {
24341 jghali 76
                        currentStyle = sreader->getStyle(styleName);
77
                        styleNames.push_back(styleName);
411 Franz 78
                }
79
                gtStyle *tmp = sreader->getStyle(getName());
10427 cbradney 80
                if ((tmp->getName()).indexOf("default-style") != -1)
411 Franz 81
                        getStyle();
82
                else
83
                        currentStyle = tmp;
84
        }
85
        else if ((name == "text:unordered-list") || (name == "text:ordered-list"))
86
        {
87
                inList = true;
88
                ++listLevel;
89
                if (static_cast<int>(listIndex2.size()) < listLevel)
90
                        listIndex2.push_back(0);
24341 jghali 91
                QString styleName = attrs.value("text:style-name");
92
                if (!styleName.isEmpty())
93
                        currentList = styleName;
411 Franz 94
                currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
439 tsoots 95
                styleNames.clear();
96
                styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
411 Franz 97
                if (name == "text:ordered-list")
98
                        isOrdered2.push_back(true);
99
                else
100
                        isOrdered2.push_back(false);
101
        }
102
        else if (name == "text:list-item")
103
        {
17730 jghali 104
                bool isOrdered = false;
105
                int levelIndex = listLevel - 1;
17810 fschmid 106
                if (levelIndex >= 0 && levelIndex < static_cast<int>(isOrdered2.size()))
17730 jghali 107
                        isOrdered = isOrdered2[listLevel - 1];
108
                if (isOrdered)
411 Franz 109
                {
110
                        ++listIndex;
111
                        ++listIndex2[listLevel - 1];
112
                        if (listLevel == 1)
113
                                write(QString("%1. ").arg(listIndex2[listLevel - 1]));
114
                        else
115
                                write(QString("%1. ").arg(listIndex2[listLevel - 1]));
116
                }
117
                else
118
                        write("- ");
119
        }
10574 jghali 120
        else if (name == "text:note")
121
                inNote = true;
122
        else if (name == "text:note-body")
123
                inNoteBody = true;
411 Franz 124
        else if (name == "style:style")
125
        {
25070 craig 126
                QString sname;
411 Franz 127
                bool isTextStyle = false;
24341 jghali 128
                for (auto attr = attrs.cbegin(); attr != attrs.cend(); ++attr)
411 Franz 129
                {
24935 craig 130
                        const QString& attrName = attr.key();
24341 jghali 131
                        if (attrName == "style:name")
132
                                sname = attr.value();
133
                        else if ((attrName == "style:family") && (attr.value() == "text"))
411 Franz 134
                                isTextStyle = true;
135
                }
136
                if (isTextStyle)
137
                {
138
                        tName = sname;
139
                        inT = true;
140
                }
141
        }
142
        else if ((name == "style:properties") && (inT))
143
        {
144
                Properties p;
24341 jghali 145
                for (auto attr = attrs.cbegin(); attr != attrs.cend(); ++attr)
411 Franz 146
                {
24341 jghali 147
                        std::pair<QString, QString> pair(attr.key(), attr.value());
411 Franz 148
                        p.push_back(pair);
149
                }
150
                tmap[tName] = p;
151
        }
420 Franz 152
        else if (name == "text:s")
153
        {
154
                int count = 1;
24341 jghali 155
                QString textC = attrs.value("text:c");
156
                if (!textC.isEmpty())
420 Franz 157
                {
24341 jghali 158
                        bool ok = false;
159
                        int tmpcount = textC.toInt(&ok);
160
                        if (ok)
161
                                count = tmpcount;
420 Franz 162
                }
163
                for (int i = 0; i < count; ++i)
164
                        write(" ");
165
        }
411 Franz 166
        return true;
167
}
168
 
169
bool ContentReader::characters(const QString &ch)
170
{
25068 craig 171
        QString tmp(ch);
25069 craig 172
        tmp.remove("\n");
173
        tmp.remove(""); // Remove all OO.o hyphenation chars
12874 jghali 174
        // Unneeded as scribus now also use standard unicode non-breakable space
175
        // tmp = tmp.replace(QChar(160), SpecialChars::NBSPACE); // replace OO.o nbsp with Scribus nbsp
12143 jghali 176
        if (append > 0)
411 Franz 177
                write(tmp);
178
        return true;
179
}
180
 
24341 jghali 181
bool ContentReader::endElement(const QString &name)
411 Franz 182
{
183
        if ((name == "text:p") || (name == "text:h"))
184
        {
185
                write("\n");
12143 jghali 186
                --append;
10574 jghali 187
                if (inList || inNote || inNoteBody)
4327 cbradney 188
                {
22612 craig 189
                        if (!styleNames.empty())
4327 cbradney 190
                                styleNames.pop_back();
191
                }
439 tsoots 192
                else
193
                        styleNames.clear();
411 Franz 194
        }
195
        else if (name == "text:span")
196
        {
197
                inSpan = false;
198
                currentStyle = pstyle;
22612 craig 199
                if (!styleNames.empty())
439 tsoots 200
                        styleNames.pop_back(); 
411 Franz 201
                currentStyle = sreader->getStyle(getName());
202
        }
10574 jghali 203
        else if (name == "text:note")
204
                inNote = false;
205
        else if (name == "text:note-body")
206
                inNoteBody = false;
411 Franz 207
        else if (name == "text:line-break")
10796 avox 208
                write(SpecialChars::LINEBREAK);
411 Franz 209
        else if (name == "text:tab-stop")
210
                write("\t");
211
        else if ((name == "text:unordered-list") || (name == "text:ordered-list"))
212
        {
213
                --listLevel;
439 tsoots 214
                styleNames.clear();
411 Franz 215
                if (listLevel == 0)
216
                {
217
                        inList = false;
218
                        listIndex2.clear();
219
                }
220
                else
439 tsoots 221
                {
411 Franz 222
                        currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
439 tsoots 223
                        styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
224
                }
411 Franz 225
        }
226
        else if ((name == "style:style") && (inT))
227
        {
228
                inT = false;
229
                tName = "";
230
        }
231
        return true;
232
}
233
 
234
void ContentReader::write(const QString& text)
235
{
10574 jghali 236
        if (!inNote && !inNoteBody) // Disable notes import for now
237
        {
238
                if (importTextOnly)
12895 jghali 239
                        writer->appendUnstyled(text);
10574 jghali 240
                else if (inSpan)
241
                        writer->append(text, currentStyle, false);
242
                else
243
                        writer->append(text, currentStyle);
244
        }
411 Franz 245
        lastStyle = currentStyle;
246
}
247
 
22635 craig 248
void ContentReader::parse(const QString& fileName)
411 Franz 249
{
250
        sreader->parse(fileName);
7277 jghali 251
#if defined(_WIN32)
16577 craig 252
        QString fname = QDir::toNativeSeparators(fileName);
24851 jghali 253
        QByteArray fn = fname.toUtf8();
7277 jghali 254
#else
10493 fschmid 255
        QByteArray fn(fileName.toLocal8Bit());
7277 jghali 256
#endif
257
        xmlSAXParseFile(cSAXHandler, fn.data(), 1);
411 Franz 258
}
259
 
260
xmlSAXHandler cSAXHandlerStruct = {
22528 craig 261
        nullptr, // internalSubset,
262
        nullptr, // isStandalone,
263
        nullptr, // hasInternalSubset,
264
        nullptr, // hasExternalSubset,
265
        nullptr, // resolveEntity,
266
        nullptr, // getEntity,
267
        nullptr, // entityDecl,
268
        nullptr, // notationDecl,
269
        nullptr, // attributeDecl,
270
        nullptr, // elementDecl,
271
        nullptr, // unparsedEntityDecl,
272
        nullptr, // setDocumentLocator,
273
        nullptr, // startDocument,
274
        nullptr, // endDocument,
411 Franz 275
        ContentReader::startElement,
276
        ContentReader::endElement,
22528 craig 277
        nullptr, // reference,
411 Franz 278
        ContentReader::characters,
22528 craig 279
        nullptr, // ignorableWhitespace,
280
        nullptr, // processingInstruction,
281
        nullptr, // comment,
282
        nullptr, // warning,
283
        nullptr, // error,
284
        nullptr, // fatalError,
285
        nullptr, // getParameterEntity,
286
        nullptr, // cdata,
287
        nullptr,
411 Franz 288
        1
289
#ifdef HAVE_XML26
290
        ,
22528 craig 291
        nullptr,
292
        nullptr,
293
        nullptr,
294
        nullptr
411 Franz 295
#endif
296
};
297
 
298
xmlSAXHandlerPtr cSAXHandler = &cSAXHandlerStruct;
299
 
1157 tsoots 300
void ContentReader::startElement(void*, const xmlChar *fullname, const xmlChar ** atts)
411 Franz 301
{
12147 jghali 302
        QString name(QString((const char*) fullname).toLower());
24341 jghali 303
        SXWAttributesMap attrs;
304
        for (const xmlChar** cur = atts; cur && *cur; cur += 2)
411 Franz 305
        {
24341 jghali 306
                QString attrName((char*)*cur);
307
                QString attrValue((char*)*(cur + 1));
308
                attrs[attrName] = attrValue;
411 Franz 309
        }
24341 jghali 310
        creader->startElement(name, attrs);
411 Franz 311
}
312
 
1157 tsoots 313
void ContentReader::characters(void*, const xmlChar *ch, int len)
411 Franz 314
{
315
        QString chars = QString::fromUtf8((const char*) ch, len);
316
        creader->characters(chars);
317
}
318
 
1157 tsoots 319
void ContentReader::endElement(void*, const xmlChar *name)
411 Franz 320
{
12147 jghali 321
        QString nname(QString((const char*) name).toLower());
24341 jghali 322
        creader->endElement(nname);
411 Franz 323
}
324
 
325
QString ContentReader::getName()
326
{
25070 craig 327
        QString s;
411 Franz 328
        for (uint i = 0; i < styleNames.size(); ++i)
329
                s += styleNames[i];
330
        return s;
331
}
332
 
333
void ContentReader::getStyle()
334
{
23820 craig 335
        gtStyle *style = nullptr;
336
        gtStyle *tmp = nullptr;
22612 craig 337
        if (styleNames.empty())
11935 jghali 338
                style = sreader->getStyle("default-style");
439 tsoots 339
        else
11935 jghali 340
                style = sreader->getStyle(styleNames[0]);
22528 craig 341
        assert (style != nullptr);
11935 jghali 342
        gtParagraphStyle* par = dynamic_cast<gtParagraphStyle*>(style);
343
        if (par)
344
                tmp = new gtParagraphStyle(*par);
345
        else
346
                tmp = new gtStyle(*style);
411 Franz 347
        for (uint i = 1; i < styleNames.size(); ++i)
348
        {
349
                Properties& p = tmap[styleNames[i]];
350
                for (uint j = 0; j < p.size(); ++j)
351
                        sreader->updateStyle(tmp, sreader->getStyle(styleNames[i - 1]), p[j].first, p[j].second);
352
        }
353
        currentStyle = tmp;
354
        sreader->setStyle(getName(), tmp);
355
}
356
 
357
ContentReader::~ContentReader()
358
{
22528 craig 359
        creader = nullptr;
411 Franz 360
        delete defaultStyle;
361
}
362
 
363
#endif // HAVE_XML