void FlatTextarea::getMentionHashtagStart(QString &start) const {
	int32 pos = textCursor().position();
	if (textCursor().anchor() != pos) return;

	QTextDocument *doc(document());
	QTextBlock block = doc->findBlock(pos);
	for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
		QTextFragment fr(iter.fragment());
		if (!fr.isValid()) continue;

		int32 p = fr.position(), e = (p + fr.length());
		if (p >= pos || e < pos) continue;

		QTextCharFormat f = fr.charFormat();
		if (f.isImageFormat()) continue;

		QString t(fr.text());
		for (int i = pos - p; i > 0; --i) {
			if (t.at(i - 1) == '@') {
				if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
					start = t.mid(i - 1, pos - p - i + 1);
				}
				return;
			} else if (t.at(i - 1) == '#') {
				if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
					start = t.mid(i - 1, pos - p - i + 1);
				}
				return;
			}
			if (pos - p - i > 63) break;
			if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
		}
		return;
	}
}
Beispiel #2
0
void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
    int32 emojiPosition = 0, emojiLen = 0;
    const EmojiData *emoji = 0;

    QTextDocument *doc(document());

    while (true) {
        int32 start = position, end = position + charsAdded;
        QTextBlock from = doc->findBlock(start), till = doc->findBlock(end);
        if (till.isValid()) till = till.next();

        for (QTextBlock b = from; b != till; b = b.next()) {
            for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
                QTextFragment fragment(iter.fragment());
                if (!fragment.isValid()) continue;

                int32 fp = fragment.position(), fe = fp + fragment.length();
                if (fp >= end || fe <= start) {
                    continue;
                }

                QString t(fragment.text());
                const QChar *ch = t.constData(), *e = ch + t.size();
                for (; ch != e; ++ch) {
                    emoji = emojiFromText(ch, e, emojiLen);
                    if (emoji) {
                        emojiPosition = fp + (ch - t.constData());
                        break;
                    }
                    if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
                }
                if (emoji) break;
            }
            if (emoji) break;
        }
        if (emoji) {
            if (!document()->pageSize().isNull()) {
                document()->setPageSize(QSizeF(0, 0));
            }

            QTextCursor c(doc->docHandle(), emojiPosition);
            c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor);
            int32 removedUpto = c.position();

            insertEmoji(emoji, c);

            charsAdded -= removedUpto - position;
            position = emojiPosition + 1;

            emoji = 0;
            emojiPosition = 0;
        } else {
            break;
        }
    }
}
Beispiel #3
0
QString Text::extractImgTooltip(int pos) const
{
    for (QTextBlock::Iterator itr = doc->firstBlock().begin(); itr != doc->firstBlock().end(); ++itr) {
        if (itr.fragment().contains(pos) && itr.fragment().charFormat().isImageFormat()) {
            QTextImageFormat imgFmt = itr.fragment().charFormat().toImageFormat();
            return imgFmt.toolTip();
        }
    }

    return QString();
}
Beispiel #4
0
QString FlatTextarea::getMentionHashtagBotCommandPart(bool &start) const {
	start = false;

	int32 pos = textCursor().position();
	if (textCursor().anchor() != pos) return QString();

	// check mention / hashtag / bot command
	QTextDocument *doc(document());
	QTextBlock block = doc->findBlock(pos);
	for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
		QTextFragment fr(iter.fragment());
		if (!fr.isValid()) continue;

		int32 p = fr.position(), e = (p + fr.length());
		if (p >= pos || e < pos) continue;

		QTextCharFormat f = fr.charFormat();
		if (f.isImageFormat()) continue;

		bool mentionInCommand = false;
		QString t(fr.text());
		for (int i = pos - p; i > 0; --i) {
			if (t.at(i - 1) == '@') {
				if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
					start = (i == 1) && (p == 0);
					return t.mid(i - 1, pos - p - i + 1);
				} else if ((pos - p - i < 1 || t.at(i).isLetter()) && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
					mentionInCommand = true;
					--i;
					continue;
				}
				return QString();
			} else if (t.at(i - 1) == '#') {
				if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
					start = (i == 1) && (p == 0);
					return t.mid(i - 1, pos - p - i + 1);
				}
				return QString();
			} else if (t.at(i - 1) == '/') {
				if (i < 2) {
					start = (i == 1) && (p == 0);
					return t.mid(i - 1, pos - p - i + 1);
				}
				return QString();
			}
			if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
			if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
		}
		break;
	}
	return QString();
}
bool FlatTextarea::hasText() const {
	QTextDocument *doc(document());
	QTextBlock from = doc->begin(), till = doc->end();

	if (from == till) return false;

	for (QTextBlock::Iterator iter = from.begin(); !iter.atEnd(); ++iter) {
		QTextFragment fragment(iter.fragment());
		if (!fragment.isValid()) continue;
		if (!fragment.text().isEmpty()) return true;
	}
	return (from.next() != till);
}
Beispiel #6
0
void FlatTextarea::onMentionHashtagOrBotCommandInsert(QString str) {
	QTextCursor c(textCursor());
	int32 pos = c.position();

	QTextDocument *doc(document());
	QTextBlock block = doc->findBlock(pos);
	for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
		QTextFragment fr(iter.fragment());
		if (!fr.isValid()) continue;

		int32 p = fr.position(), e = (p + fr.length());
		if (p >= pos || e < pos) continue;

		QTextCharFormat f = fr.charFormat();
		if (f.isImageFormat()) continue;

		bool mentionInCommand = false;
		QString t(fr.text());
		for (int i = pos - p; i > 0; --i) {
			if (t.at(i - 1) == '@' || t.at(i - 1) == '#' || t.at(i - 1) == '/') {
				if ((i == pos - p || (t.at(i - 1) == '/' ? t.at(i).isLetterOrNumber() : t.at(i).isLetter()) || t.at(i - 1) == '#') && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
					c.setPosition(p + i - 1, QTextCursor::MoveAnchor);
					int till = p + i;
					for (; (till < e) && (till - p - i + 1 < str.size()); ++till) {
						if (t.at(till - p).toLower() != str.at(till - p - i + 1).toLower()) {
							break;
						}
					}
					if (till - p - i + 1 == str.size() && till < e && t.at(till - p) == ' ') {
						++till;
					}
					c.setPosition(till, QTextCursor::KeepAnchor);
					c.insertText(str + ' ');
					return;
				} else if ((i == pos - p || t.at(i).isLetter()) && t.at(i - 1) == '@' && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
					mentionInCommand = true;
					--i;
					continue;
				}
				break;
			}
			if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
			if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
		}
		break;
	}
	c.insertText(str + ' ');
}
void FlatTextarea::onMentionOrHashtagInsert(QString mentionOrHashtag) {
	QTextCursor c(textCursor());
	int32 pos = c.position();

	QTextDocument *doc(document());
	QTextBlock block = doc->findBlock(pos);
	for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
		QTextFragment fr(iter.fragment());
		if (!fr.isValid()) continue;

		int32 p = fr.position(), e = (p + fr.length());
		if (p >= pos || e < pos) continue;

		QTextCharFormat f = fr.charFormat();
		if (f.isImageFormat()) continue;

		QString t(fr.text());
		for (int i = pos - p; i > 0; --i) {
			if (t.at(i - 1) == '@' || t.at(i - 1) == '#') {
				if ((i == pos - p || t.at(i).isLetter() || t.at(i - 1) == '#') && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
					c.setPosition(p + i - 1, QTextCursor::MoveAnchor);
					int till = p + i;
					for (; (till < e) && (till - p - i + 1 < mentionOrHashtag.size()); ++till) {
						if (t.at(till - p).toLower() != mentionOrHashtag.at(till - p - i + 1).toLower()) {
							break;
						}
					}
					if (till - p - i + 1 == mentionOrHashtag.size() && till < e && t.at(till - p) == ' ') {
						++till;
					}
					c.setPosition(till, QTextCursor::KeepAnchor);
					c.insertText(mentionOrHashtag + ' ');
					return;
				}
				break;
			}
			if (pos - p - i > 63) break;
			if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
		}
	}
	c.insertText(mentionOrHashtag + ' ');
}
Beispiel #8
0
QString Text::extractSanitizedText(int from, int to) const
{
    if (!doc)
        return "";

    QString txt;

    QTextBlock begin = doc->findBlock(from);
    QTextBlock end = doc->findBlock(to);
    for (QTextBlock block = begin; block != end.next() && block.isValid(); block = block.next()) {
        for (QTextBlock::Iterator itr = block.begin(); itr != block.end(); ++itr) {
            int pos =
                itr.fragment()
                    .position(); // fragment position -> position of the first character in the fragment

            if (itr.fragment().charFormat().isImageFormat()) {
                QTextImageFormat imgFmt = itr.fragment().charFormat().toImageFormat();
                QString key = imgFmt.name(); // img key (eg. key::D for :D)
                QString rune = key.mid(4);

                if (pos >= from && pos < to) {
                    txt += rune;
                    ++pos;
                }
            } else {
                for (QChar c : itr.fragment().text()) {
                    if (pos >= from && pos < to)
                        txt += c;

                    ++pos;
                }
            }
        }

        txt += '\n';
    }

    txt.chop(1);

    return txt;
}
void FlatTextarea::getSingleEmojiFragment(QString &text, QTextFragment &fragment) const {
	int32 end = textCursor().position(), start = end - 1;
	if (textCursor().anchor() != end) return;

	if (start < 0) start = 0;

	QTextDocument *doc(document());
	QTextBlock from = doc->findBlock(start), till = doc->findBlock(end);
	if (till.isValid()) till = till.next();

	for (QTextBlock b = from; b != till; b = b.next()) {
		for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
			QTextFragment fr(iter.fragment());
			if (!fr.isValid()) continue;

			int32 p = fr.position(), e = (p + fr.length());
			if (p >= end || e <= start) {
				continue;
			}

			QTextCharFormat f = fr.charFormat();
			QString t(fr.text());
			if (p < start) {
				t = t.mid(start - p, end - start);
			} else if (e > end) {
				t = t.mid(0, end - p);
			}
			if (f.isImageFormat() && !t.isEmpty() && t.at(0).unicode() == QChar::ObjectReplacementCharacter) {
				QString imageName = static_cast<QTextImageFormat*>(&f)->name();
				if (imageName.startsWith(QLatin1String("emoji://e."))) {
					fragment = fr;
					text = t;
					return;
				}
			}
			return;
		}
	}
	return;
}
QString FlatTextarea::getText(int32 start, int32 end) const {
	if (end >= 0 && end <= start) return QString();

	if (start < 0) start = 0;
	bool full = (start == 0) && (end < 0);

	QTextDocument *doc(document());
	QTextBlock from = full ? doc->begin() : doc->findBlock(start), till = (end < 0) ? doc->end() : doc->findBlock(end);
	if (till.isValid()) till = till.next();

	int32 possibleLen = 0;
	for (QTextBlock b = from; b != till; b = b.next()) {
		possibleLen += b.length();
	}
	QString result;
	result.reserve(possibleLen + 1);
	if (!full && end < 0) {
		end = possibleLen;
	}

	for (QTextBlock b = from; b != till; b = b.next()) {
		for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
			QTextFragment fragment(iter.fragment());
			if (!fragment.isValid()) continue;

			int32 p = full ? 0 : fragment.position(), e = full ? 0 : (p + fragment.length());
			if (!full) {
				if (p >= end || e <= start) {
					continue;
				}
			}

			QTextCharFormat f = fragment.charFormat();
			QString emojiText;
			QString t(fragment.text());
			if (!full) {
				if (p < start) {
					t = t.mid(start - p, end - start);
				} else if (e > end) {
					t = t.mid(0, end - p);
				}
			}
			QChar *ub = t.data(), *uc = ub, *ue = uc + t.size();
			for (; uc != ue; ++uc) {
				switch (uc->unicode()) {
				case 0xfdd0: // QTextBeginningOfFrame
				case 0xfdd1: // QTextEndOfFrame
				case QChar::ParagraphSeparator:
				case QChar::LineSeparator:
					*uc = QLatin1Char('\n');
					break;
				case QChar::Nbsp:
					*uc = QLatin1Char(' ');
					break;
				case QChar::ObjectReplacementCharacter:
					if (emojiText.isEmpty() && f.isImageFormat()) {
						QString imageName = static_cast<QTextImageFormat*>(&f)->name();
						if (imageName.startsWith(QLatin1String("emoji://e."))) {
							if (EmojiPtr emoji = emojiFromUrl(imageName)) {
								emojiText = textEmojiString(emoji);
							}
						}
					}
					if (uc > ub) result.append(ub, uc - ub);
					if (!emojiText.isEmpty()) result.append(emojiText);
					ub = uc + 1;
				break;
				}
			}
			if (uc > ub) result.append(ub, uc - ub);
		}
		result.append('\n');
	}
	result.chop(1);
	return result;
}
Beispiel #11
0
void InputField::processDocumentContentsChange(int position, int charsAdded) {
	int32 emojiPosition = 0, emojiLen = 0;
	const EmojiData *emoji = 0;

	static QString space(' ');

	QTextDocument *doc(_inner.document());
	QTextCursor c(_inner.textCursor());
	c.joinPreviousEditBlock();
	while (true) {
		int32 start = position, end = position + charsAdded;
		QTextBlock from = doc->findBlock(start), till = doc->findBlock(end);
		if (till.isValid()) till = till.next();

		for (QTextBlock b = from; b != till; b = b.next()) {
			for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
				QTextFragment fragment(iter.fragment());
				if (!fragment.isValid()) continue;

				int32 fp = fragment.position(), fe = fp + fragment.length();
				if (fp >= end || fe <= start) {
					continue;
				}

				QString t(fragment.text());
				const QChar *ch = t.constData(), *e = ch + t.size();
				for (; ch != e; ++ch) {
					// QTextBeginningOfFrame // QTextEndOfFrame
					if (ch->unicode() == 0xfdd0 || ch->unicode() == 0xfdd1 || ch->unicode() == QChar::ParagraphSeparator || ch->unicode() == QChar::LineSeparator || ch->unicode() == '\n' || ch->unicode() == '\r') {
						if (!_inner.document()->pageSize().isNull()) {
							_inner.document()->setPageSize(QSizeF(0, 0));
						}
						int32 nlPosition = fp + (ch - t.constData());
						QTextCursor c(doc->docHandle(), nlPosition);
						c.setPosition(nlPosition + 1, QTextCursor::KeepAnchor);
						c.insertText(space);
						position = nlPosition + 1;
						emoji = TwoSymbolEmoji; // just a flag
						break;
					}
					emoji = emojiFromText(ch, e, emojiLen);
					if (emoji) {
						emojiPosition = fp + (ch - t.constData());
						break;
					}
					if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) ++ch;
				}
				if (emoji) break;
			}
			if (emoji) break;
			if (b.next() != doc->end()) {
				int32 nlPosition = b.next().position() - 1;
				QTextCursor c(doc->docHandle(), nlPosition);
				c.setPosition(nlPosition + 1, QTextCursor::KeepAnchor);
				c.insertText(space);
				position = nlPosition + 1;
				emoji = TwoSymbolEmoji; // just a flag
				break;
			}
		}
		if (emoji == TwoSymbolEmoji) { // just skip
			emoji = 0;
			emojiPosition = 0;
		} else if (emoji) {
			if (!_inner.document()->pageSize().isNull()) {
				_inner.document()->setPageSize(QSizeF(0, 0));
			}

			QTextCursor c(doc->docHandle(), emojiPosition);
			c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor);
			int32 removedUpto = c.position();

			insertEmoji(emoji, c);

			for (Insertions::iterator i = _insertions.begin(), e = _insertions.end(); i != e; ++i) {
				if (i->first >= removedUpto) {
					i->first -= removedUpto - emojiPosition - 1;
				} else if (i->first >= emojiPosition) {
					i->second -= removedUpto - emojiPosition;
					i->first = emojiPosition + 1;
				} else if (i->first + i->second > emojiPosition + 1) {
					i->second -= qMin(removedUpto, i->first + i->second) - emojiPosition;
				}
			}

			charsAdded -= removedUpto - position;
			position = emojiPosition + 1;

			emoji = 0;
			emojiPosition = 0;
		} else {
			break;
		}
	}
	c.endEditBlock();
}
Beispiel #12
0
void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
	int32 replacePosition = -1, replaceLen = 0;
	const EmojiData *emoji = 0;

	static QString regular = qsl("Open Sans"), semibold = qsl("Open Sans Semibold");
	bool checkTilde = !cRetina() && (font().pixelSize() == 13) && (font().family() == regular), wasTildeFragment = false;

	QTextDocument *doc(document());
	while (true) {
		int32 start = position, end = position + charsAdded;
		QTextBlock from = doc->findBlock(start), till = doc->findBlock(end);
		if (till.isValid()) till = till.next();

		for (QTextBlock b = from; b != till; b = b.next()) {
			for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
				QTextFragment fragment(iter.fragment());
				if (!fragment.isValid()) continue;

				int32 fp = fragment.position(), fe = fp + fragment.length();
				if (fp >= end || fe <= start) {
					continue;
				}

				if (checkTilde) {
					wasTildeFragment = (fragment.charFormat().fontFamily() == semibold);
				}

				QString t(fragment.text());
				const QChar *ch = t.constData(), *e = ch + t.size();
				for (; ch != e; ++ch, ++fp) {
					int32 emojiLen = 0;
					emoji = emojiFromText(ch, e, &emojiLen);
					if (emoji) {
						if (replacePosition >= 0) {
							emoji = 0; // replace tilde char format first
						} else {
							replacePosition = fp;
							replaceLen = emojiLen;
						}
						break;
					}

					if (checkTilde && fp >= position) { // tilde fix in OpenSans
						bool tilde = (ch->unicode() == '~');
						if ((tilde && !wasTildeFragment) || (!tilde && wasTildeFragment)) {
							if (replacePosition < 0) {
								replacePosition = fp;
								replaceLen = 1;
							} else {
								++replaceLen;
							}
						} else if (replacePosition >= 0) {
							break;
						}
					}

					if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) {
						++ch;
						++fp;
					}
				}
				if (replacePosition >= 0) break;
			}
			if (replacePosition >= 0) break;
		}
		if (replacePosition >= 0) {
			if (!document()->pageSize().isNull()) {
				document()->setPageSize(QSizeF(0, 0));
			}
			QTextCursor c(doc->docHandle(), replacePosition);
			c.setPosition(replacePosition + replaceLen, QTextCursor::KeepAnchor);
			if (emoji) {
				insertEmoji(emoji, c);
			} else {
				QTextCharFormat format;
				format.setFontFamily(wasTildeFragment ? regular : semibold);
				c.mergeCharFormat(format);
			}
			charsAdded -= replacePosition + replaceLen - position;
			position = replacePosition + (emoji ? 1 : replaceLen);

			emoji = 0;
			replacePosition = -1;
		} else {
			break;
		}
	}
}
Beispiel #13
0
void HtmlExporter::emitBlock( const QTextBlock &block )
{
    // save and later restore, in case we 'change' the default format by
    // emitting block char format information

    // NOTE the bottom line is commented, to use default charFormat, which can be set from outside.
    //QTextCharFormat oldDefaultCharFormat = defaultCharFormat;

    QString blockTag;
    bool isBlockQuote = false;
    const QTextBlockFormat blockFormat = block.blockFormat();

    if ( blockFormat.hasProperty( BilboTextFormat::IsBlockQuote ) && 
         blockFormat.boolProperty( BilboTextFormat::IsBlockQuote ) ) {
        isBlockQuote = true;
    }
    QTextList *list = block.textList();
    if ( list ) {
        if ( list->itemNumber( block ) == 0 ) { // first item? emit <ul> or appropriate
//    qDebug() << "first item" << endl;
            if ( isBlockQuote ) {
                html += QLatin1String( "<blockquote>" );
            }
            const QTextListFormat format = list->format();
            const int style = format.style();
            switch ( style ) {
                case QTextListFormat::ListDecimal:
                    html += QLatin1String( "<ol" );
                    break;
                case QTextListFormat::ListDisc:
                    html += QLatin1String( "<ul" );
                    break;
                case QTextListFormat::ListCircle:
                    html += QLatin1String( "<ul type=\"circle\"" );
                    break;
                case QTextListFormat::ListSquare:
                    html += QLatin1String( "<ul type=\"square\"" );
                    break;
                case QTextListFormat::ListLowerAlpha:
                    html += QLatin1String( "<ol type=\"a\"" );
                    break;
                case QTextListFormat::ListUpperAlpha:
                    html += QLatin1String( "<ol type=\"A\"" );
                    break;
                default:
                    html += QLatin1String( "<ul" ); // ### should not happen
                    //qDebug() << html;
            }
            /*
            if (format.hasProperty(QTextFormat::ListIndent)) {
                html += QLatin1String(" style=\"-qt-list-indent: ");
                html += QString::number(format.indent());
                html += QLatin1String(";\"");
            }*/

            html += QLatin1Char( '>' );
        }
        blockTag = QLatin1String( "li" );
//         html += QLatin1String( "<li " );
    }

//     const QTextBlockFormat blockFormat = block.blockFormat();
    if ( blockFormat.hasProperty( QTextFormat::BlockTrailingHorizontalRulerWidth ) ) { 
        if ( ( blockFormat.hasProperty( BilboTextFormat::IsHtmlTagSign ) ) && 
            ( blockFormat.boolProperty( BilboTextFormat::IsHtmlTagSign ) ) ) {
            html += QLatin1String( "<!--split-->" );
            return;
        } else {
            html += QLatin1String( "<hr" );
    
            QTextLength width = blockFormat.lengthProperty( QTextFormat::BlockTrailingHorizontalRulerWidth );
            if ( width.type() != QTextLength::VariableLength ) {
                emitTextLength( "width", width );
            } else {
                html += QLatin1Char( ' ' );
            }
    
            html += QLatin1String( "/>" );
            return;
        }
    }

    const bool pre = blockFormat.nonBreakableLines();
    if ( pre ) {
//   qDebug() << "NonBreakable lines" << endl;
//         if (list) {
//             html += QLatin1Char('>');
//   }
//         html += QLatin1String( "<pre" );
//         emitBlockAttributes( block );
//         html += QLatin1Char( '>' );
        blockTag = QLatin1String( "pre" );

    } else {
        if (!list) {
            if ( isBlockQuote ) {
                html += QLatin1String( "<blockquote>" );
            }

            if ( ( blockFormat.hasProperty( BilboTextFormat::HtmlHeading ) ) && (
                blockFormat.intProperty( BilboTextFormat::HtmlHeading ) ) ) {
                const int index = blockFormat.intProperty( BilboTextFormat::HtmlHeading );
                blockTag = QLatin1Char( 'h' ) + QString::number( index );
            } else {
                //html += QLatin1String("<div");
//                 html += QLatin1String( "<p" );
                blockTag = QLatin1String( "p" );
            }
        }
    }
    if ( !blockTag.isEmpty() ) {
        html += QLatin1Char( '<' ) + blockTag;
        emitBlockAttributes( block );
        html += QLatin1Char( '>' );
    }

    QTextBlock::Iterator it = block.begin();

    for ( ; !it.atEnd(); ++it ) {
        emitFragment( it.fragment(), blockFormat );
    }

    if ( !blockTag.isEmpty() ) {
        html += QLatin1String( "</" ) + blockTag + QLatin1String( ">\n" );
    }

//     if ( pre ) {
//         html += QLatin1String( "</pre>\n" );
//     } else {
//         if ( list ) {
//             html += QLatin1String( "</li>\n" );
//         } else {
//             if ( blockFormat::boolProperty( BilboTextFormat::IsHtmlHeading ) ) {
//                 const int index = format.intProperty( QTextFormat::FontSizeAdjustment );
//                 switch ( index ) {
//                     case -2:
//                        html += QLatin1String( "</h6>" );
//                        break;
//                     case -1:
//                        html += QLatin1String( "</h5>" );
//                        break;
//                     case 0:
//                        html += QLatin1String( "</h4>" );
//                        break;
//                     case 1:
//                        html += QLatin1String( "</h3>" );
//                        break;
//                     case 2:
//                        html += QLatin1String( "<h2" );
//                        break;
//                     case 3:
//                        html += QLatin1String( "<h1" );
//                        break;
//                 }
//             } else {
//                 html += QLatin1String( "</p>\n" );
//             }
//         }
//     }
    // HACK html.replace( QRegExp("<br[\\s]*/>[\\n]*<br[\\s]*/>[\\n]*"),"<br />&nbsp;<br />" );

    if ( list ) {
        if ( list->itemNumber( block ) == list->count() - 1 ) { // last item? close list
            if ( isOrderedList( list->format().style() ) ) {
                html += QLatin1String( "</ol>\n" );
            } else {
                html += QLatin1String( "</ul>\n" );
            }
            if ( isBlockQuote ) {
                html += QLatin1String( "</blockquote>\n" );
            }
        }
    } else {
        if ( isBlockQuote ) {
            html += QLatin1String( "</blockquote>\n" );
        }
    }
    // NOTE the bottom line is commented, to use default charFormat, which can be set from outside.
    //defaultCharFormat = oldDefaultCharFormat;
}
Beispiel #14
0
void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
	int32 emojiPosition = 0, emojiLen = 0;
	const EmojiData *emoji = 0;

	QTextDocument *doc(document());

	while (true) {
		int32 start = position, end = position + charsAdded;
		QTextBlock from = doc->findBlock(start), till = doc->findBlock(end);
		if (till.isValid()) till = till.next();

		for (QTextBlock b = from; b != till; b = b.next()) {
			for (QTextBlock::Iterator iter = b.begin(); !iter.atEnd(); ++iter) {
				QTextFragment fragment(iter.fragment());
				if (!fragment.isValid()) continue;

				int32 p = fragment.position(), e = p + fragment.length();
				if (p >= end || e <= start) {
					continue;
				}

				QString t(fragment.text());
				for (const QChar *ch = t.constData(), *e = ch + t.size(); ch != e; ++ch) {
					if (ch + 1 < e && (ch->isHighSurrogate() || (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3))) {
						emoji = getEmoji((ch->unicode() << 16) | (ch + 1)->unicode());
						if (emoji) {
							if (emoji->len == 4 && (ch + 3 >= e || ((uint32((ch + 2)->unicode()) << 16) | uint32((ch + 3)->unicode())) != emoji->code2)) {
								emoji = 0;
							} else {
								emojiPosition = p + (ch - t.constData());
								emojiLen = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
								break;
							}
						}
						++ch;
					} else {
						emoji = getEmoji(ch->unicode());
						if (emoji) {
							emojiPosition = p + (ch - t.constData());
							emojiLen = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
							break;
						}
					}
				}
				if (emoji) break;
			}
			if (emoji) break;
		}
		if (emoji) {
			QTextCursor c(doc->docHandle(), emojiPosition);
			c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor);
			int32 removedUpto = c.position();

			insertEmoji(emoji, c);

			for (Insertions::iterator i = _insertions.begin(), e = _insertions.end(); i != e; ++i) {
				if (i->first >= removedUpto) {
					i->first -= removedUpto - emojiPosition - 1;
				} else if (i->first >= emojiPosition) {
					i->second -= removedUpto - emojiPosition;
					i->first = emojiPosition + 1;
				} else if (i->first + i->second > emojiPosition + 1) {
					i->second -= qMin(removedUpto, i->first + i->second) - emojiPosition;
				}
			}

			charsAdded -= removedUpto - position;
			position = emojiPosition + 1;

			emoji = 0;
			emojiPosition = 0;
		} else {
			break;
		}
	}
}