1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#ifndef QTEXTHTMLPARSER_P_H
43
#define QTEXTHTMLPARSER_P_H
44
45
//
46
//  W A R N I N G
47
//  -------------
48
//
49
// This file is not part of the Qt API.  It exists purely as an
50
// implementation detail.  This header file may change from version to
51
// version without notice, or even be removed.
52
//
53
// We mean it.
54
//
55
56
#include "QtCore/qvector.h"
57
#include "QtGui/qbrush.h"
58
#include "QtGui/qcolor.h"
59
#include "QtGui/qfont.h"
60
#include "QtGui/qtextdocument.h"
61
#include "QtGui/qtextcursor.h"
62
#include "private/qtextformat_p.h"
63
#include "private/qtextdocument_p.h"
64
#include "private/qcssparser_p.h"
65
66
#ifndef QT_NO_TEXTHTMLPARSER
67
68
QT_BEGIN_NAMESPACE
69
70
enum QTextHTMLElements {
71
    Html_unknown = -1,
72
    Html_qt = 0,
73
    Html_body,
74
75
    Html_a,
76
    Html_em,
77
    Html_i,
78
    Html_big,
79
    Html_small,
80
    Html_strong,
81
    Html_b,
82
    Html_cite,
83
    Html_address,
84
    Html_var,
85
    Html_dfn,
86
87
    Html_h1,
88
    Html_h2,
89
    Html_h3,
90
    Html_h4,
91
    Html_h5,
92
    Html_h6,
93
    Html_p,
94
    Html_center,
95
96
    Html_font,
97
98
    Html_ul,
99
    Html_ol,
100
    Html_li,
101
102
    Html_code,
103
    Html_tt,
104
    Html_kbd,
105
    Html_samp,
106
107
    Html_img,
108
    Html_br,
109
    Html_hr,
110
111
    Html_sub,
112
    Html_sup,
113
114
    Html_pre,
115
    Html_blockquote,
116
    Html_head,
117
    Html_div,
118
    Html_span,
119
    Html_dl,
120
    Html_dt,
121
    Html_dd,
122
    Html_u,
123
    Html_s,
124
    Html_nobr,
125
126
    // tables
127
    Html_table,
128
    Html_tr,
129
    Html_td,
130
    Html_th,
131
    Html_thead,
132
    Html_tbody,
133
    Html_tfoot,
134
    Html_caption,
135
136
    // misc...
137
    Html_html,
138
    Html_style,
139
    Html_title,
140
    Html_meta,
141
    Html_link,
142
    Html_script,
143
144
    Html_NumElements
145
};
146
147
struct QTextHtmlElement
148
{
149
    const char *name;
150
    QTextHTMLElements id;
151
    enum DisplayMode { DisplayBlock, DisplayInline, DisplayTable, DisplayNone } displayMode;
152
};
153
154
class QTextHtmlParser;
155
156
struct QTextHtmlParserNode {
157
    enum WhiteSpaceMode {
158
        WhiteSpaceNormal,
159
        WhiteSpacePre,
160
        WhiteSpaceNoWrap,
161
        WhiteSpacePreWrap,
162
        WhiteSpaceModeUndefined = -1
163
    };
164
165
    QTextHtmlParserNode();
166
    QString tag;
167
    QString text;
168
    QStringList attributes;
169
    int parent;
170
    QVector<int> children;
171
    QTextHTMLElements id;
172
    QTextCharFormat charFormat;
173
    QTextBlockFormat blockFormat;
174
    uint cssFloat : 2;
175
    uint hasOwnListStyle : 1;
176
    uint hasCssListIndent : 1;
177
    uint isEmptyParagraph : 1;
178
    uint isTextFrame : 1;
179
    uint isRootFrame : 1;
180
    uint displayMode : 3; // QTextHtmlElement::DisplayMode
181
    uint hasHref : 1;
182
    QTextListFormat::Style listStyle;
183
    QString textListNumberPrefix;
184
    QString textListNumberSuffix;
185
    QString imageName;
186
    qreal imageWidth;
187
    qreal imageHeight;
188
    QTextLength width;
189
    QTextLength height;
190
    qreal tableBorder;
191
    int tableCellRowSpan;
192
    int tableCellColSpan;
193
    qreal tableCellSpacing;
194
    qreal tableCellPadding;
195
    QBrush borderBrush;
196
    QTextFrameFormat::BorderStyle borderStyle;
197
    int userState;
198
199
    int cssListIndent;
200
201
    WhiteSpaceMode wsm;
202
203
    inline bool isListStart() const
204
    { return id == Html_ol || id == Html_ul; }
205
    inline bool isTableCell() const
206
    { return id == Html_td || id == Html_th; }
207
    inline bool isBlock() const
208
    { return displayMode == QTextHtmlElement::DisplayBlock; }
209
210
    inline bool isNotSelfNesting() const
211
    { return id == Html_p || id == Html_li; }
212
213
    inline bool allowedInContext(int parentId) const
214
    {
215
        switch (id) {
216
            case Html_dd:
217
            case Html_dt: return (parentId == Html_dl);
218
            case Html_tr: return (parentId == Html_table
219
                                  || parentId == Html_thead
220
                                  || parentId == Html_tbody
221
                                  || parentId == Html_tfoot
222
                                 );
223
            case Html_th:
224
            case Html_td: return (parentId == Html_tr);
225
            case Html_thead:
226
            case Html_tbody:
227
            case Html_tfoot: return (parentId == Html_table);
228
            case Html_caption: return (parentId == Html_table);
229
            case Html_body: return parentId != Html_head;
230
            default: break;
231
        }
232
        return true;
233
    }
234
235
    inline bool mayNotHaveChildren() const
236
    { return id == Html_img || id == Html_hr || id == Html_br || id == Html_meta; }
237
238
    void initializeProperties(const QTextHtmlParserNode *parent, const QTextHtmlParser *parser);
239
240
    inline int uncollapsedMargin(int mar) const { return margin[mar]; }
241
242
    bool isNestedList(const QTextHtmlParser *parser) const;
243
244
    void parseStyleAttribute(const QString &value, const QTextDocument *resourceProvider);
245
246
#ifndef QT_NO_CSSPARSER
247
    void applyCssDeclarations(const QVector<QCss::Declaration> &declarations, const QTextDocument *resourceProvider);
248
249
    void setListStyle(const QVector<QCss::Value> &cssValues);
250
#endif
251
252
    void applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider);
253
254
    bool hasOnlyWhitespace() const;
255
256
    int margin[4];
257
    int padding[4];
258
259
    friend class QTextHtmlParser;
260
};
261
Q_DECLARE_TYPEINFO(QTextHtmlParserNode, Q_MOVABLE_TYPE);
262
263
264
class QTextHtmlParser
265
{
266
public:
267
    enum Margin {
268
        MarginTop,
269
        MarginRight,
270
        MarginBottom,
271
        MarginLeft
272
    };
273
274
    inline const QTextHtmlParserNode &at(int i) const { return nodes.at(i); }
275
    inline QTextHtmlParserNode &operator[](int i) { return nodes[i]; }
276
    inline int count() const { return nodes.count(); }
277
    inline int last() const { return nodes.count()-1; }
278
    int depth(int i) const;
279
    int topMargin(int i) const;
280
    int bottomMargin(int i) const;
281
    inline int leftMargin(int i) const { return margin(i, MarginLeft); }
282
    inline int rightMargin(int i) const { return margin(i, MarginRight); }
283
284
    inline int topPadding(int i) const { return at(i).padding[MarginTop]; }
285
    inline int bottomPadding(int i) const { return at(i).padding[MarginBottom]; }
286
    inline int leftPadding(int i) const { return at(i).padding[MarginLeft]; }
287
    inline int rightPadding(int i) const { return at(i).padding[MarginRight]; }
288
289
    void dumpHtml();
290
291
    void parse(const QString &text, const QTextDocument *resourceProvider);
292
293
    static int lookupElement(const QString &element);
294
protected:
295
    QTextHtmlParserNode *newNode(int parent);
296
    QVector<QTextHtmlParserNode> nodes;
297
    QString txt;
298
    int pos, len;
299
300
    bool textEditMode;
301
302
    void parse();
303
    void parseTag();
304
    void parseCloseTag();
305
    void parseExclamationTag();
306
    QString parseEntity();
307
    QString parseWord();
308
    QTextHtmlParserNode *resolveParent();
309
    void resolveNode();
310
    QStringList parseAttributes();
311
    void applyAttributes(const QStringList &attributes);
312
    void eatSpace();
313
    inline bool hasPrefix(QChar c, int lookahead = 0) const
314
        {return pos + lookahead < len && txt.at(pos) == c; }
315
    int margin(int i, int mar) const;
316
317
    bool nodeIsChildOf(int i, QTextHTMLElements id) const;
318
319
320
#ifndef QT_NO_CSSPARSER
321
    QVector<QCss::Declaration> declarationsForNode(int node) const;
322
    void resolveStyleSheetImports(const QCss::StyleSheet &sheet);
323
    void importStyleSheet(const QString &href);
324
325
    struct ExternalStyleSheet
326
    {
327
        inline ExternalStyleSheet() {}
328
        inline ExternalStyleSheet(const QString &_url, const QCss::StyleSheet &_sheet)
329
            : url(_url), sheet(_sheet) {}
330
        QString url;
331
        QCss::StyleSheet sheet;
332
    };
333
    QVector<ExternalStyleSheet> externalStyleSheets;
334
    QVector<QCss::StyleSheet> inlineStyleSheets;
335
#endif
336
337
    const QTextDocument *resourceProvider;
338
};
339
340
QT_END_NAMESPACE
341
342
#endif // QT_NO_TEXTHTMLPARSER
343
344
#endif // QTEXTHTMLPARSER_P_H