From 5df63f9c2e6d78f4799447b0a22cdb9fb70c3fea Mon Sep 17 00:00:00 2001 From: Anthony Bilinski Date: Wed, 31 Jan 2018 19:48:25 -0800 Subject: [PATCH] fix(chatlog): parse multi-length emoji properly Before, when multi-length emoji were next to any other character, they would not be transformed into images. With this change, emoji are replaced with images no matter where they are in the string. Parsing is now done by checking to see if two-character blocks are valid as a single UTF-32 character, or if they are truly two distinct characters. Because we no longer need white space before emoji, I also removed our addition of spaces on either side of an emoji when a user sends them. --- src/persistence/smileypack.cpp | 30 +++++++++++++++++------------- src/widget/emoticonswidget.cpp | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/persistence/smileypack.cpp b/src/persistence/smileypack.cpp index 97c68cdeb..5a27c7e07 100644 --- a/src/persistence/smileypack.cpp +++ b/src/persistence/smileypack.cpp @@ -258,21 +258,25 @@ QString SmileyPack::smileyfied(const QString& msg) { QMutexLocker locker(&loadingMutex); QString result(msg); - QRegularExpression exp("\\S+"); - QRegularExpressionMatchIterator iter = exp.globalMatch(result); - int replaceDiff = 0; - while (iter.hasNext()) { - QRegularExpressionMatch match = iter.next(); - QString key = match.captured(); - int startPos = match.capturedStart(); - int keyLength = key.length(); - if (emoticonToPath.find(key) != emoticonToPath.end()) { - QString imgRichText = getAsRichText(key); - result.replace(startPos + replaceDiff, keyLength, imgRichText); - replaceDiff += imgRichText.length() - keyLength; + int replaceDiff = 0; // how much we have increased message size by replacing emoji with image tags + int curCharLength; + QStringRef curChar; // the current UTF-32 which we are examining, which may look like a 2-length QString + for (int strIndex = 0; strIndex < msg.length(); strIndex += curCharLength) { + if ((msg.length() - strIndex >= 2) && ((curChar = msg.midRef(strIndex, 2)).toUcs4().length() == 1)) { + // if converting two characters to UTF-32 gives us a single valid character, this is actually a single + // 4-byte character, with a QString length of 2 + curCharLength = 2; + } + else { + curChar = msg.midRef(strIndex, 1); + curCharLength = 1; + } + if (emoticonToPath.find(curChar.toString()) != emoticonToPath.end()) { + QString imgRichText = getAsRichText(curChar.toString()); + result.replace(strIndex + replaceDiff, curCharLength, imgRichText); + replaceDiff += imgRichText.length() - curCharLength; } } - return result; } diff --git a/src/widget/emoticonswidget.cpp b/src/widget/emoticonswidget.cpp index 1b5ffb8a1..f36cada4f 100644 --- a/src/widget/emoticonswidget.cpp +++ b/src/widget/emoticonswidget.cpp @@ -131,7 +131,7 @@ void EmoticonsWidget::onSmileyClicked() if (sender) { QString sequence = sender->property("sequence").toString().replace("<", "<").replace(">", ">"); - emit insertEmoticon(' ' + sequence + ' '); + emit insertEmoticon(sequence); } }