1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTEXTDOCUMENTFRAGMENT_P_H
5#define QTEXTDOCUMENTFRAGMENT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19#include "QtGui/qtextdocument.h"
20#include "private/qtexthtmlparser_p.h"
21#include "private/qtextdocument_p.h"
22#include "QtGui/qtexttable.h"
23#include "QtCore/qatomic.h"
24#include "QtCore/qlist.h"
25#include "QtCore/qmap.h"
26#include "QtCore/qpointer.h"
27#include "QtCore/qvarlengtharray.h"
28#include "QtCore/qdatastream.h"
29
30QT_BEGIN_NAMESPACE
31
32class QTextDocumentFragmentPrivate;
33
34class QTextCopyHelper
35{
36public:
37 QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat = false, const QTextCharFormat &fmt = QTextCharFormat());
38
39 void copy();
40
41private:
42 void appendFragments(int pos, int endPos);
43 int appendFragment(int pos, int endPos, int objectIndex = -1);
44 int convertFormatIndex(const QTextFormat &oldFormat, int objectIndexToSet = -1);
45 inline int convertFormatIndex(int oldFormatIndex, int objectIndexToSet = -1)
46 { return convertFormatIndex(oldFormat: src->formatCollection()->format(idx: oldFormatIndex), objectIndexToSet); }
47 inline QTextFormat convertFormat(const QTextFormat &fmt)
48 { return dst->formatCollection()->format(idx: convertFormatIndex(oldFormat: fmt)); }
49
50 int insertPos;
51
52 bool forceCharFormat;
53 int primaryCharFormatIndex;
54
55 QTextCursor cursor;
56 QTextDocumentPrivate *dst;
57 QTextDocumentPrivate *src;
58 QTextFormatCollection &formatCollection;
59 const QString originalText;
60 QMap<int, int> objectIndexMap;
61};
62
63class QTextDocumentFragmentPrivate
64{
65public:
66 QTextDocumentFragmentPrivate(const QTextCursor &cursor = QTextCursor());
67 inline ~QTextDocumentFragmentPrivate() { delete doc; }
68
69 void insert(QTextCursor &cursor) const;
70
71 QAtomicInt ref;
72 QTextDocument *doc;
73
74 uint importedFromPlainText : 1;
75private:
76 Q_DISABLE_COPY_MOVE(QTextDocumentFragmentPrivate)
77};
78
79#ifndef QT_NO_TEXTHTMLPARSER
80
81class QTextHtmlImporter : public QTextHtmlParser
82{
83 struct Table;
84public:
85 enum ImportMode {
86 ImportToFragment,
87 ImportToDocument
88 };
89
90 QTextHtmlImporter(QTextDocument *_doc, const QString &html,
91 ImportMode mode,
92 const QTextDocument *resourceProvider = nullptr);
93
94 void import();
95
96private:
97 bool closeTag();
98
99 Table scanTable(int tableNodeIdx);
100
101 enum ProcessNodeResult { ContinueWithNextNode, ContinueWithCurrentNode, ContinueWithNextSibling };
102
103 void appendBlock(const QTextBlockFormat &format, QTextCharFormat charFmt = QTextCharFormat());
104 bool appendNodeText();
105
106 ProcessNodeResult processBlockNode();
107 ProcessNodeResult processSpecialNodes();
108
109 struct List
110 {
111 inline List() : listNode(0) {}
112 QTextListFormat format;
113 int listNode;
114 QPointer<QTextList> list;
115 };
116 friend class QTypeInfo<List>;
117 QList<List> lists;
118 int indent;
119 int headingLevel;
120
121 // insert a named anchor the next time we emit a char format,
122 // either in a block or in regular text
123 QStringList namedAnchors;
124
125#ifdef Q_CC_SUN
126 friend struct QTextHtmlImporter::Table;
127#endif
128 struct TableCellIterator
129 {
130 inline TableCellIterator(QTextTable *t = nullptr) : table(t), row(0), column(0) {}
131
132 inline TableCellIterator &operator++() {
133 if (atEnd())
134 return *this;
135 do {
136 const QTextTableCell cell = table->cellAt(row, col: column);
137 if (!cell.isValid())
138 break;
139 column += cell.columnSpan();
140 if (column >= table->columns()) {
141 column = 0;
142 ++row;
143 }
144 } while (row < table->rows() && table->cellAt(row, col: column).row() != row);
145
146 return *this;
147 }
148
149 inline bool atEnd() const { return table == nullptr || row >= table->rows(); }
150
151 QTextTableCell cell() const { return table->cellAt(row, col: column); }
152
153 QTextTable *table;
154 int row;
155 int column;
156 };
157 friend class QTypeInfo<TableCellIterator>;
158
159 friend struct Table;
160 struct Table
161 {
162 Table() : isTextFrame(false), rows(0), columns(0), currentRow(0), lastIndent(0) {}
163 QPointer<QTextFrame> frame;
164 bool isTextFrame;
165 int rows;
166 int columns;
167 int currentRow; // ... for buggy html (see html_skipCell testcase)
168 TableCellIterator currentCell;
169 int lastIndent;
170 };
171 friend class QTypeInfo<Table>;
172 QList<Table> tables;
173
174 struct RowColSpanInfo
175 {
176 int row, col;
177 int rowSpan, colSpan;
178 };
179 friend class QTypeInfo<RowColSpanInfo>;
180
181 enum WhiteSpace
182 {
183 RemoveWhiteSpace,
184 CollapseWhiteSpace,
185 PreserveWhiteSpace
186 };
187
188 WhiteSpace compressNextWhitespace;
189
190 QTextDocument *doc;
191 QTextCursor cursor;
192 QTextHtmlParserNode::WhiteSpaceMode wsm;
193 ImportMode importMode;
194 bool hasBlock;
195 bool forceBlockMerging;
196 bool blockTagClosed;
197 int currentNodeIdx;
198 const QTextHtmlParserNode *currentNode;
199};
200Q_DECLARE_TYPEINFO(QTextHtmlImporter::List, Q_RELOCATABLE_TYPE);
201Q_DECLARE_TYPEINFO(QTextHtmlImporter::TableCellIterator, Q_PRIMITIVE_TYPE);
202Q_DECLARE_TYPEINFO(QTextHtmlImporter::Table, Q_RELOCATABLE_TYPE);
203Q_DECLARE_TYPEINFO(QTextHtmlImporter::RowColSpanInfo, Q_PRIMITIVE_TYPE);
204
205QT_END_NAMESPACE
206#endif // QT_NO_TEXTHTMLPARSER
207
208#endif // QTEXTDOCUMENTFRAGMENT_P_H
209

source code of qtbase/src/gui/text/qtextdocumentfragment_p.h