const RecentEmojiPack &cGetRecentEmojis() { if (cRecentEmojis().isEmpty()) { RecentEmojiPack r; if (!cRecentEmojisPreload().isEmpty()) { RecentEmojiPreload p(cRecentEmojisPreload()); cSetRecentEmojisPreload(RecentEmojiPreload()); r.reserve(p.size()); for (RecentEmojiPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) { uint32 code = ((i->first & 0xFFFFU) == 0xFE0FU) ? ((i->first >> 16) & 0xFFFFU) : i->first; EmojiPtr ep(getEmoji(code)); if (!ep) continue; if (ep->postfix) { int32 j = 0, l = r.size(); for (; j < l; ++j) { if (r[j].first->code == code) { break; } } if (j < l) { continue; } } r.push_back(qMakePair(ep, i->second)); } }
EmojiPtr FlatTextarea::getSingleEmoji() const { QString text; QTextFragment fragment; getSingleEmojiFragment(text, fragment); if (!text.isEmpty()) { QTextCharFormat format = fragment.charFormat(); QString imageName = static_cast<const QTextImageFormat*>(&format)->name(); return getEmoji(imageName.mid(8).toUInt(0, 16)); } return 0; }
void EmojiBox::fillBlocks() { BlockRow currentRow; currentRow.reserve(replacesInRow); for (int32 i = 0; i < replacesCount; ++i) { Block block(getEmoji(replaces[i].code), QString::fromUtf8(replaces[i].replace)); currentRow.push_back(block); if (currentRow.size() == replacesInRow) { _blocks.push_back(currentRow); currentRow.resize(0); } } if (currentRow.size()) { _blocks.push_back(currentRow); } }
const RecentEmojiPack &cGetRecentEmojis() { if (cRecentEmojis().isEmpty() && !cRecentEmojisPreload().isEmpty()) { RecentEmojiPreload p(cRecentEmojisPreload()); cSetRecentEmojisPreload(RecentEmojiPreload()); RecentEmojiPack r; r.reserve(p.size()); for (RecentEmojiPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) { EmojiPtr ep(getEmoji(i->first)); if (ep) { r.push_back(qMakePair(ep, i->second)); } } cSetRecentEmojis(r); } return cRecentEmojis(); }
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; } } }
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.midRef(0, 8) == qsl("emoji://")) { uint32 index = imageName.mid(8).toUInt(0, 16); const EmojiData *emoji = getEmoji(index); if (emoji) { 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; }