Subversion Repositories Scribus

Rev

Rev 17810 | Rev 22528 | Go to most recent revision | 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
 
411 Franz 35
ContentReader* ContentReader::creader = NULL;
36
 
37
extern xmlSAXHandlerPtr cSAXHandler;
38
 
39
ContentReader::ContentReader(QString documentName, StyleReader *s, gtWriter *w, bool textOnly)
40
{
41
        creader = this;
42
        docname = documentName;
43
        sreader = s;
44
        writer  = w;
45
        importTextOnly = textOnly;
46
        defaultStyle = NULL;
47
        currentStyle = NULL;
48
        inList = false;
10574 jghali 49
        inNote = false;
50
        inNoteBody = false;
411 Franz 51
        inSpan = false;
12143 jghali 52
        append    = 0;
411 Franz 53
        listIndex = 0;
54
        listLevel = 0;
55
        currentList = "";
56
        inT = false;
57
        tName = "";
58
}
59
 
60
bool ContentReader::startElement(const QString&, const QString&, const QString &name, const QXmlAttributes &attrs)
61
{
62
        if ((name == "text:p") || (name == "text:h"))
63
        {
12143 jghali 64
                ++append;
439 tsoots 65
                QString name = "";
66
                for (int i = 0; i < attrs.count(); ++i)
411 Franz 67
                {
439 tsoots 68
                        if (attrs.localName(i) == "text:style-name")
411 Franz 69
                        {
439 tsoots 70
                                name = attrs.value(i);
71
                                styleNames.push_back(attrs.value(i));
411 Franz 72
                        }
73
                }
439 tsoots 74
                if (!inList)
75
                {
76
                        pstyle = sreader->getStyle(name);
77
                        currentStyle = pstyle;
78
                }
79
                else
80
                {
81
                        gtStyle *tmp = sreader->getStyle(getName());
10427 cbradney 82
                        if ((tmp->getName()).indexOf("default-style") != -1)
439 tsoots 83
                                getStyle();
84
                        else
85
                                currentStyle = tmp;
86
                }
411 Franz 87
        }
88
        else if (name == "text:span")
89
        {
90
                inSpan = true;
91
                QString styleName = "";
92
                for (int i = 0; i < attrs.count(); ++i)
93
                {
94
                        if (attrs.localName(i) == "text:style-name")
95
                        {
96
                                currentStyle = sreader->getStyle(attrs.value(i));
97
                                styleName = attrs.value(i);
98
                                styleNames.push_back(styleName);
99
                        }
100
                }
101
                gtStyle *tmp = sreader->getStyle(getName());
10427 cbradney 102
                if ((tmp->getName()).indexOf("default-style") != -1)
411 Franz 103
                        getStyle();
104
                else
105
                        currentStyle = tmp;
106
        }
107
        else if ((name == "text:unordered-list") || (name == "text:ordered-list"))
108
        {
109
                inList = true;
110
                ++listLevel;
111
                if (static_cast<int>(listIndex2.size()) < listLevel)
112
                        listIndex2.push_back(0);
113
                for (int i = 0; i < attrs.count(); ++i)
114
                {
115
                        if (attrs.localName(i) == "text:style-name")
116
                                currentList = attrs.value(i);
117
                }
118
                currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
439 tsoots 119
                styleNames.clear();
120
                styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
411 Franz 121
                if (name == "text:ordered-list")
122
                        isOrdered2.push_back(true);
123
                else
124
                        isOrdered2.push_back(false);
125
        }
126
        else if (name == "text:list-item")
127
        {
17730 jghali 128
                bool isOrdered = false;
129
                int levelIndex = listLevel - 1;
17810 fschmid 130
                if (levelIndex >= 0 && levelIndex < static_cast<int>(isOrdered2.size()))
17730 jghali 131
                        isOrdered = isOrdered2[listLevel - 1];
132
                if (isOrdered)
411 Franz 133
                {
134
                        ++listIndex;
135
                        ++listIndex2[listLevel - 1];
136
                        if (listLevel == 1)
137
                                write(QString("%1. ").arg(listIndex2[listLevel - 1]));
138
                        else
139
                                write(QString("%1. ").arg(listIndex2[listLevel - 1]));
140
                }
141
                else
142
                        write("- ");
143
        }
10574 jghali 144
        else if (name == "text:note")
145
                inNote = true;
146
        else if (name == "text:note-body")
147
                inNoteBody = true;
411 Franz 148
        else if (name == "style:style")
149
        {
150
                QString sname = "";
151
                bool isTextStyle = false;
152
                for (int i = 0; i < attrs.count(); ++i)
153
                {
154
                        if (attrs.localName(i) == "style:name")
155
                                sname = attrs.value(i);
3258 cbradney 156
                        else if ((attrs.localName(i) == "style:family") && (attrs.value(i) == "text"))
411 Franz 157
                                isTextStyle = true;
158
                }
159
                if (isTextStyle)
160
                {
161
                        tName = sname;
162
                        inT = true;
163
                }
164
        }
165
        else if ((name == "style:properties") && (inT))
166
        {
167
                Properties p;
168
                for (int i = 0; i < attrs.count(); ++i)
169
                {
170
                        std::pair<QString, QString> pair(attrs.localName(i), attrs.value(i));
171
                        p.push_back(pair);
172
                }
173
                tmap[tName] = p;
174
        }
420 Franz 175
        else if (name == "text:s")
176
        {
177
                int count = 1;
178
                for (int i = 0; i < attrs.count(); ++i)
179
                {
180
                        if (attrs.localName(i) == "text:c")
181
                        {
182
                                bool ok = false;
183
                                int tmpcount = (attrs.value(i)).toInt(&ok);
184
                                if (ok)
185
                                        count = tmpcount;
186
                        }
187
                }
188
                for (int i = 0; i < count; ++i)
189
                        write(" ");
190
        }
411 Franz 191
        return true;
192
}
193
 
194
bool ContentReader::characters(const QString &ch)
195
{
196
        QString tmp = ch;
197
        tmp = tmp.remove("\n");
198
        tmp = tmp.remove(""); // Remove all OO.o hyphenation chars
12874 jghali 199
        // Unneeded as scribus now also use standard unicode non-breakable space
200
        // tmp = tmp.replace(QChar(160), SpecialChars::NBSPACE); // replace OO.o nbsp with Scribus nbsp
12143 jghali 201
        if (append > 0)
411 Franz 202
                write(tmp);
203
        return true;
204
}
205
 
206
bool ContentReader::endElement(const QString&, const QString&, const QString &name)
207
{
208
        if ((name == "text:p") || (name == "text:h"))
209
        {
210
                write("\n");
12143 jghali 211
                --append;
10574 jghali 212
                if (inList || inNote || inNoteBody)
4327 cbradney 213
                {
214
                        if (styleNames.size() != 0)
215
                                styleNames.pop_back();
216
                }
439 tsoots 217
                else
218
                        styleNames.clear();
411 Franz 219
        }
220
        else if (name == "text:span")
221
        {
222
                inSpan = false;
223
                currentStyle = pstyle;
224
                if (styleNames.size() != 0)
439 tsoots 225
                        styleNames.pop_back(); 
411 Franz 226
                currentStyle = sreader->getStyle(getName());
227
        }
10574 jghali 228
        else if (name == "text:note")
229
                inNote = false;
230
        else if (name == "text:note-body")
231
                inNoteBody = false;
411 Franz 232
        else if (name == "text:line-break")
10796 avox 233
                write(SpecialChars::LINEBREAK);
411 Franz 234
        else if (name == "text:tab-stop")
235
                write("\t");
236
        else if ((name == "text:unordered-list") || (name == "text:ordered-list"))
237
        {
238
                --listLevel;
439 tsoots 239
                styleNames.clear();
411 Franz 240
                if (listLevel == 0)
241
                {
242
                        inList = false;
243
                        listIndex2.clear();
244
                }
245
                else
439 tsoots 246
                {
411 Franz 247
                        currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
439 tsoots 248
                        styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
249
                }
411 Franz 250
        }
251
        else if ((name == "style:style") && (inT))
252
        {
253
                inT = false;
254
                tName = "";
255
        }
256
        return true;
257
}
258
 
259
void ContentReader::write(const QString& text)
260
{
10574 jghali 261
        if (!inNote && !inNoteBody) // Disable notes import for now
262
        {
263
                if (importTextOnly)
12895 jghali 264
                        writer->appendUnstyled(text);
10574 jghali 265
                else if (inSpan)
266
                        writer->append(text, currentStyle, false);
267
                else
268
                        writer->append(text, currentStyle);
269
        }
411 Franz 270
        lastStyle = currentStyle;
271
}
272
 
273
void ContentReader::parse(QString fileName)
274
{
275
        sreader->parse(fileName);
7277 jghali 276
#if defined(_WIN32)
16577 craig 277
        QString fname = QDir::toNativeSeparators(fileName);
10723 jghali 278
        QByteArray fn = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) ? fname.toUtf8() : fname.toLocal8Bit();
7277 jghali 279
#else
10493 fschmid 280
        QByteArray fn(fileName.toLocal8Bit());
7277 jghali 281
#endif
282
        xmlSAXParseFile(cSAXHandler, fn.data(), 1);
411 Franz 283
}
284
 
285
xmlSAXHandler cSAXHandlerStruct = {
286
        NULL, // internalSubset,
287
        NULL, // isStandalone,
288
        NULL, // hasInternalSubset,
289
        NULL, // hasExternalSubset,
290
        NULL, // resolveEntity,
291
        NULL, // getEntity,
292
        NULL, // entityDecl,
293
        NULL, // notationDecl,
294
        NULL, // attributeDecl,
295
        NULL, // elementDecl,
296
        NULL, // unparsedEntityDecl,
297
        NULL, // setDocumentLocator,
298
        NULL, // startDocument,
299
        NULL, // endDocument,
300
        ContentReader::startElement,
301
        ContentReader::endElement,
302
        NULL, // reference,
303
        ContentReader::characters,
304
        NULL, // ignorableWhitespace,
305
        NULL, // processingInstruction,
306
        NULL, // comment,
307
        NULL, // warning,
308
        NULL, // error,
309
        NULL, // fatalError,
310
        NULL, // getParameterEntity,
311
        NULL, // cdata,
312
        NULL,
313
        1
314
#ifdef HAVE_XML26
315
        ,
316
        NULL,
317
        NULL,
318
        NULL,
319
        NULL
320
#endif
321
};
322
 
323
xmlSAXHandlerPtr cSAXHandler = &cSAXHandlerStruct;
324
 
1157 tsoots 325
void ContentReader::startElement(void*, const xmlChar *fullname, const xmlChar ** atts)
411 Franz 326
{
12147 jghali 327
        QString name(QString((const char*) fullname).toLower());
328
        QXmlAttributes attrs;
411 Franz 329
        if (atts)
330
        {
331
                for(const xmlChar** cur = atts; cur && *cur; cur += 2)
12147 jghali 332
                        attrs.append(QString((char*)*cur), NULL, QString((char*)*cur), QString((char*)*(cur + 1)));
411 Franz 333
        }
12147 jghali 334
        creader->startElement(NULL, NULL, name, attrs);
411 Franz 335
}
336
 
1157 tsoots 337
void ContentReader::characters(void*, const xmlChar *ch, int len)
411 Franz 338
{
339
        QString chars = QString::fromUtf8((const char*) ch, len);
340
        creader->characters(chars);
341
}
342
 
1157 tsoots 343
void ContentReader::endElement(void*, const xmlChar *name)
411 Franz 344
{
12147 jghali 345
        QString nname(QString((const char*) name).toLower());
346
        creader->endElement(NULL, NULL, nname);
411 Franz 347
}
348
 
349
QString ContentReader::getName()
350
{
351
        QString s = "";
352
        for (uint i = 0; i < styleNames.size(); ++i)
353
                s += styleNames[i];
354
        return s;
355
}
356
 
357
void ContentReader::getStyle()
358
{
11935 jghali 359
        gtStyle *style = NULL, *tmp = NULL;
439 tsoots 360
        if (styleNames.size() == 0)
11935 jghali 361
                style = sreader->getStyle("default-style");
439 tsoots 362
        else
11935 jghali 363
                style = sreader->getStyle(styleNames[0]);
364
        assert (style != NULL);
365
        gtParagraphStyle* par = dynamic_cast<gtParagraphStyle*>(style);
366
        if (par)
367
                tmp = new gtParagraphStyle(*par);
368
        else
369
                tmp = new gtStyle(*style);
411 Franz 370
        for (uint i = 1; i < styleNames.size(); ++i)
371
        {
372
                Properties& p = tmap[styleNames[i]];
373
                for (uint j = 0; j < p.size(); ++j)
374
                        sreader->updateStyle(tmp, sreader->getStyle(styleNames[i - 1]), p[j].first, p[j].second);
375
        }
376
        currentStyle = tmp;
377
        sreader->setStyle(getName(), tmp);
378
}
379
 
380
ContentReader::~ContentReader()
381
{
382
        creader = NULL;
383
        delete defaultStyle;
384
}
385
 
386
#endif // HAVE_XML