1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QTEXTDOCUMENTFRAGMENT_P_H
41 #define QTEXTDOCUMENTFRAGMENT_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtGui/private/qtguiglobal_p.h>
55 #include "QtGui/qtextdocument.h"
56 #include "private/qtexthtmlparser_p.h"
57 #include "private/qtextdocument_p.h"
58 #include "QtGui/qtexttable.h"
59 #include "QtCore/qatomic.h"
60 #include "QtCore/qlist.h"
61 #include "QtCore/qmap.h"
62 #include "QtCore/qpointer.h"
63 #include "QtCore/qvarlengtharray.h"
64 #include "QtCore/qdatastream.h"
65 
66 QT_BEGIN_NAMESPACE
67 
68 class QTextDocumentFragmentPrivate;
69 
70 class QTextCopyHelper
71 {
72 public:
73     QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat = false, const QTextCharFormat &fmt = QTextCharFormat());
74 
75     void copy();
76 
77 private:
78     void appendFragments(int pos, int endPos);
79     int appendFragment(int pos, int endPos, int objectIndex = -1);
80     int convertFormatIndex(const QTextFormat &oldFormat, int objectIndexToSet = -1);
81     inline int convertFormatIndex(int oldFormatIndex, int objectIndexToSet = -1)
82     { return convertFormatIndex(src->formatCollection()->format(oldFormatIndex), objectIndexToSet); }
convertFormat(const QTextFormat & fmt)83     inline QTextFormat convertFormat(const QTextFormat &fmt)
84     { return dst->formatCollection()->format(convertFormatIndex(fmt)); }
85 
86     int insertPos;
87 
88     bool forceCharFormat;
89     int primaryCharFormatIndex;
90 
91     QTextCursor cursor;
92     QTextDocumentPrivate *dst;
93     QTextDocumentPrivate *src;
94     QTextFormatCollection &formatCollection;
95     const QString originalText;
96     QMap<int, int> objectIndexMap;
97 };
98 
99 class QTextDocumentFragmentPrivate
100 {
101 public:
102     QTextDocumentFragmentPrivate(const QTextCursor &cursor = QTextCursor());
~QTextDocumentFragmentPrivate()103     inline ~QTextDocumentFragmentPrivate() { delete doc; }
104 
105     void insert(QTextCursor &cursor) const;
106 
107     QAtomicInt ref;
108     QTextDocument *doc;
109 
110     uint importedFromPlainText : 1;
111 private:
112     Q_DISABLE_COPY_MOVE(QTextDocumentFragmentPrivate)
113 };
114 
115 #ifndef QT_NO_TEXTHTMLPARSER
116 
117 class QTextHtmlImporter : public QTextHtmlParser
118 {
119     struct Table;
120 public:
121     enum ImportMode {
122         ImportToFragment,
123         ImportToDocument
124     };
125 
126     QTextHtmlImporter(QTextDocument *_doc, const QString &html,
127                       ImportMode mode,
128                       const QTextDocument *resourceProvider = nullptr);
129 
130     void import();
131 
132 private:
133     bool closeTag();
134 
135     Table scanTable(int tableNodeIdx);
136 
137     enum ProcessNodeResult { ContinueWithNextNode, ContinueWithCurrentNode, ContinueWithNextSibling };
138 
139     void appendBlock(const QTextBlockFormat &format, QTextCharFormat charFmt = QTextCharFormat());
140     bool appendNodeText();
141 
142     ProcessNodeResult processBlockNode();
143     ProcessNodeResult processSpecialNodes();
144 
145     struct List
146     {
ListList147         inline List() : listNode(0) {}
148         QTextListFormat format;
149         int listNode;
150         QPointer<QTextList> list;
151     };
152     friend class QTypeInfo<List>;
153     QVector<List> lists;
154     int indent;
155     int headingLevel;
156 
157     // insert a named anchor the next time we emit a char format,
158     // either in a block or in regular text
159     QStringList namedAnchors;
160 
161 #ifdef Q_CC_SUN
162     friend struct QTextHtmlImporter::Table;
163 #endif
164     struct TableCellIterator
165     {
tableTableCellIterator166         inline TableCellIterator(QTextTable *t = nullptr) : table(t), row(0), column(0) {}
167 
168         inline TableCellIterator &operator++() {
169             if (atEnd())
170                 return *this;
171             do {
172                 const QTextTableCell cell = table->cellAt(row, column);
173                 if (!cell.isValid())
174                     break;
175                 column += cell.columnSpan();
176                 if (column >= table->columns()) {
177                     column = 0;
178                     ++row;
179                 }
180             } while (row < table->rows() && table->cellAt(row, column).row() != row);
181 
182             return *this;
183         }
184 
atEndTableCellIterator185         inline bool atEnd() const { return table == nullptr || row >= table->rows(); }
186 
cellTableCellIterator187         QTextTableCell cell() const { return table->cellAt(row, column); }
188 
189         QTextTable *table;
190         int row;
191         int column;
192     };
193     friend class QTypeInfo<TableCellIterator>;
194 
195     friend struct Table;
196     struct Table
197     {
TableTable198         Table() : isTextFrame(false), rows(0), columns(0), currentRow(0), lastIndent(0) {}
199         QPointer<QTextFrame> frame;
200         bool isTextFrame;
201         int rows;
202         int columns;
203         int currentRow; // ... for buggy html (see html_skipCell testcase)
204         TableCellIterator currentCell;
205         int lastIndent;
206     };
207     friend class QTypeInfo<Table>;
208     QVector<Table> tables;
209 
210     struct RowColSpanInfo
211     {
212         int row, col;
213         int rowSpan, colSpan;
214     };
215     friend class QTypeInfo<RowColSpanInfo>;
216 
217     enum WhiteSpace
218     {
219         RemoveWhiteSpace,
220         CollapseWhiteSpace,
221         PreserveWhiteSpace
222     };
223 
224     WhiteSpace compressNextWhitespace;
225 
226     QTextDocument *doc;
227     QTextCursor cursor;
228     QTextHtmlParserNode::WhiteSpaceMode wsm;
229     ImportMode importMode;
230     bool hasBlock;
231     bool forceBlockMerging;
232     bool blockTagClosed;
233     int currentNodeIdx;
234     const QTextHtmlParserNode *currentNode;
235 };
236 Q_DECLARE_TYPEINFO(QTextHtmlImporter::List, Q_MOVABLE_TYPE);
237 Q_DECLARE_TYPEINFO(QTextHtmlImporter::TableCellIterator, Q_PRIMITIVE_TYPE);
238 Q_DECLARE_TYPEINFO(QTextHtmlImporter::Table, Q_MOVABLE_TYPE);
239 Q_DECLARE_TYPEINFO(QTextHtmlImporter::RowColSpanInfo, Q_PRIMITIVE_TYPE);
240 
241 QT_END_NAMESPACE
242 #endif // QT_NO_TEXTHTMLPARSER
243 
244 #endif // QTEXTDOCUMENTFRAGMENT_P_H
245