1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://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 http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free 20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22 ** following information to ensure the GNU Lesser General Public License 23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 ** 26 ** As a special exception, The Qt Company gives you certain additional 27 ** rights. These rights are described in The Qt Company LGPL Exception 28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 ** 30 ** GNU General Public License Usage 31 ** Alternatively, this file may be used under the terms of the GNU 32 ** General Public License version 3.0 as published by the Free Software 33 ** Foundation and appearing in the file LICENSE.GPL included in the 34 ** packaging of this file. Please review the following information to 35 ** ensure the GNU General Public License version 3.0 requirements will be 36 ** met: http://www.gnu.org/copyleft/gpl.html. 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 isListStartQTextHtmlParserNode203 inline bool isListStart() const 204 { return id == Html_ol || id == Html_ul; } isTableCellQTextHtmlParserNode205 inline bool isTableCell() const 206 { return id == Html_td || id == Html_th; } isBlockQTextHtmlParserNode207 inline bool isBlock() const 208 { return displayMode == QTextHtmlElement::DisplayBlock; } 209 isNotSelfNestingQTextHtmlParserNode210 inline bool isNotSelfNesting() const 211 { return id == Html_p || id == Html_li; } 212 allowedInContextQTextHtmlParserNode213 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 mayNotHaveChildrenQTextHtmlParserNode235 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 uncollapsedMarginQTextHtmlParserNode240 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 at(int i)274 inline const QTextHtmlParserNode &at(int i) const { return nodes.at(i); } 275 inline QTextHtmlParserNode &operator[](int i) { return nodes[i]; } count()276 inline int count() const { return nodes.count(); } last()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; leftMargin(int i)281 inline int leftMargin(int i) const { return margin(i, MarginLeft); } rightMargin(int i)282 inline int rightMargin(int i) const { return margin(i, MarginRight); } 283 topPadding(int i)284 inline int topPadding(int i) const { return at(i).padding[MarginTop]; } bottomPadding(int i)285 inline int bottomPadding(int i) const { return at(i).padding[MarginBottom]; } leftPadding(int i)286 inline int leftPadding(int i) const { return at(i).padding[MarginLeft]; } rightPadding(int i)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 { ExternalStyleSheetExternalStyleSheet327 inline ExternalStyleSheet() {} ExternalStyleSheetExternalStyleSheet328 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 345