Fix crashes that can occur when selecting/copying text (#4153)
This commit is contained in:
+53
-17
@@ -1,25 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
struct SelectionItem {
|
||||
int messageIndex;
|
||||
int charIndex;
|
||||
uint32_t messageIndex{0};
|
||||
uint32_t charIndex{0};
|
||||
|
||||
SelectionItem()
|
||||
SelectionItem() = default;
|
||||
|
||||
SelectionItem(uint32_t _messageIndex, uint32_t _charIndex)
|
||||
: messageIndex(_messageIndex)
|
||||
, charIndex(_charIndex)
|
||||
{
|
||||
this->messageIndex = 0;
|
||||
this->charIndex = 0;
|
||||
}
|
||||
|
||||
SelectionItem(int _messageIndex, int _charIndex)
|
||||
{
|
||||
this->messageIndex = _messageIndex;
|
||||
|
||||
this->charIndex = _charIndex;
|
||||
}
|
||||
|
||||
bool operator<(const SelectionItem &b) const
|
||||
@@ -75,14 +71,54 @@ struct Selection {
|
||||
return this->selectionMin.messageIndex ==
|
||||
this->selectionMax.messageIndex;
|
||||
}
|
||||
|
||||
// Shift all message selection indices `offset` back
|
||||
void shiftMessageIndex(uint32_t offset)
|
||||
{
|
||||
if (offset > this->selectionMin.messageIndex)
|
||||
{
|
||||
this->selectionMin.messageIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->selectionMin.messageIndex -= offset;
|
||||
}
|
||||
|
||||
if (offset > this->selectionMax.messageIndex)
|
||||
{
|
||||
this->selectionMax.messageIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->selectionMax.messageIndex -= offset;
|
||||
}
|
||||
|
||||
if (offset > this->start.messageIndex)
|
||||
{
|
||||
this->start.messageIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->start.messageIndex -= offset;
|
||||
}
|
||||
|
||||
if (offset > this->end.messageIndex)
|
||||
{
|
||||
this->end.messageIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->end.messageIndex -= offset;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct DoubleClickSelection {
|
||||
int originalStart = 0;
|
||||
int originalEnd = 0;
|
||||
int origMessageIndex;
|
||||
bool selectingLeft = false;
|
||||
bool selectingRight = false;
|
||||
uint32_t originalStart{0};
|
||||
uint32_t originalEnd{0};
|
||||
uint32_t origMessageIndex{0};
|
||||
bool selectingLeft{false};
|
||||
bool selectingRight{false};
|
||||
SelectionItem origStartItem;
|
||||
SelectionItem origEndItem;
|
||||
};
|
||||
|
||||
@@ -442,7 +442,7 @@ int MessageLayout::getSelectionIndex(QPoint position)
|
||||
return this->container_->getSelectionIndex(position);
|
||||
}
|
||||
|
||||
void MessageLayout::addSelectionText(QString &str, int from, int to,
|
||||
void MessageLayout::addSelectionText(QString &str, uint32_t from, uint32_t to,
|
||||
CopyMode copymode)
|
||||
{
|
||||
this->container_->addSelectionText(str, from, to, copymode);
|
||||
|
||||
@@ -59,7 +59,8 @@ public:
|
||||
int getLastCharacterIndex() const;
|
||||
int getFirstMessageCharacterIndex() const;
|
||||
int getSelectionIndex(QPoint position);
|
||||
void addSelectionText(QString &str, int from = 0, int to = INT_MAX,
|
||||
void addSelectionText(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX,
|
||||
CopyMode copymode = CopyMode::Everything);
|
||||
|
||||
// Misc
|
||||
|
||||
@@ -798,10 +798,10 @@ int MessageLayoutContainer::getFirstMessageCharacterIndex() const
|
||||
return index;
|
||||
}
|
||||
|
||||
void MessageLayoutContainer::addSelectionText(QString &str, int from, int to,
|
||||
CopyMode copymode)
|
||||
void MessageLayoutContainer::addSelectionText(QString &str, uint32_t from,
|
||||
uint32_t to, CopyMode copymode)
|
||||
{
|
||||
int index = 0;
|
||||
uint32_t index = 0;
|
||||
bool first = true;
|
||||
|
||||
for (auto &element : this->elements_)
|
||||
@@ -819,7 +819,9 @@ void MessageLayoutContainer::addSelectionText(QString &str, int from, int to,
|
||||
if (element->getCreator().getFlags().hasAny(
|
||||
{MessageElementFlag::Timestamp,
|
||||
MessageElementFlag::Username, MessageElementFlag::Badges}))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto indexCount = element->getSelectionIndexCount();
|
||||
|
||||
@@ -81,7 +81,8 @@ struct MessageLayoutContainer {
|
||||
int getSelectionIndex(QPoint point);
|
||||
int getLastCharacterIndex() const;
|
||||
int getFirstMessageCharacterIndex() const;
|
||||
void addSelectionText(QString &str, int from, int to, CopyMode copymode);
|
||||
void addSelectionText(QString &str, uint32_t from, uint32_t to,
|
||||
CopyMode copymode);
|
||||
|
||||
bool isCollapsed();
|
||||
|
||||
|
||||
@@ -108,8 +108,8 @@ ImageLayoutElement::ImageLayoutElement(MessageElement &creator, ImagePtr image,
|
||||
this->trailingSpace = creator.hasTrailingSpace();
|
||||
}
|
||||
|
||||
void ImageLayoutElement::addCopyTextToString(QString &str, int from,
|
||||
int to) const
|
||||
void ImageLayoutElement::addCopyTextToString(QString &str, uint32_t from,
|
||||
uint32_t to) const
|
||||
{
|
||||
const auto *emoteElement =
|
||||
dynamic_cast<EmoteElement *>(&this->getCreator());
|
||||
@@ -272,8 +272,8 @@ void TextLayoutElement::listenToLinkChanges()
|
||||
});
|
||||
}
|
||||
|
||||
void TextLayoutElement::addCopyTextToString(QString &str, int from,
|
||||
int to) const
|
||||
void TextLayoutElement::addCopyTextToString(QString &str, uint32_t from,
|
||||
uint32_t to) const
|
||||
{
|
||||
str += this->getText().mid(from, to - from);
|
||||
|
||||
@@ -387,8 +387,8 @@ TextIconLayoutElement::TextIconLayoutElement(MessageElement &creator,
|
||||
{
|
||||
}
|
||||
|
||||
void TextIconLayoutElement::addCopyTextToString(QString &str, int from,
|
||||
int to) const
|
||||
void TextIconLayoutElement::addCopyTextToString(QString &str, uint32_t from,
|
||||
uint32_t to) const
|
||||
{
|
||||
}
|
||||
|
||||
@@ -513,14 +513,12 @@ int ReplyCurveLayoutElement::getXFromIndex(int index)
|
||||
{
|
||||
return this->getRect().left();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->getRect().right();
|
||||
}
|
||||
|
||||
return this->getRect().right();
|
||||
}
|
||||
|
||||
void ReplyCurveLayoutElement::addCopyTextToString(QString &str, int from,
|
||||
int to) const
|
||||
void ReplyCurveLayoutElement::addCopyTextToString(QString &str, uint32_t from,
|
||||
uint32_t to) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPen>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <climits>
|
||||
|
||||
#include "common/FlagsEnum.hpp"
|
||||
#include "messages/Link.hpp"
|
||||
#include "messages/MessageColor.hpp"
|
||||
#include "messages/MessageElement.hpp"
|
||||
|
||||
#include <QPen>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <pajlada/signals/signalholder.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
|
||||
class QPainter;
|
||||
|
||||
namespace chatterino {
|
||||
@@ -41,8 +42,8 @@ public:
|
||||
MessageLayoutElement *setLink(const Link &link_);
|
||||
MessageLayoutElement *setText(const QString &text_);
|
||||
|
||||
virtual void addCopyTextToString(QString &str, int from = 0,
|
||||
int to = INT_MAX) const = 0;
|
||||
virtual void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const = 0;
|
||||
virtual int getSelectionIndexCount() const = 0;
|
||||
virtual void paint(QPainter &painter) = 0;
|
||||
virtual void paintAnimated(QPainter &painter, int yOffset) = 0;
|
||||
@@ -72,8 +73,8 @@ public:
|
||||
const QSize &size);
|
||||
|
||||
protected:
|
||||
void addCopyTextToString(QString &str, int from = 0,
|
||||
int to = INT_MAX) const override;
|
||||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
@@ -124,8 +125,8 @@ public:
|
||||
void listenToLinkChanges();
|
||||
|
||||
protected:
|
||||
void addCopyTextToString(QString &str, int from = 0,
|
||||
int to = INT_MAX) const override;
|
||||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
@@ -148,8 +149,8 @@ public:
|
||||
const QString &line2, float scale, const QSize &size);
|
||||
|
||||
protected:
|
||||
void addCopyTextToString(QString &str, int from = 0,
|
||||
int to = INT_MAX) const override;
|
||||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
@@ -173,8 +174,8 @@ protected:
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
void addCopyTextToString(QString &str, int from = 0,
|
||||
int to = INT_MAX) const override;
|
||||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user