forked from qt-creator/qt-creator
fakevim: Clipboard data format compatible with Vim
Store clipboard data that can be used by Vim and vice versa. Change-Id: If1eb436fa371afeff39fd37353fe0841dafe169a Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -141,6 +141,10 @@ enum {
|
|||||||
const int ParagraphSeparator = 0x00002029;
|
const int ParagraphSeparator = 0x00002029;
|
||||||
typedef QLatin1String _;
|
typedef QLatin1String _;
|
||||||
|
|
||||||
|
/* Clipboard MIME types used by Vim. */
|
||||||
|
static const QString vimMimeText = "_VIM_TEXT";
|
||||||
|
static const QString vimMimeTextEncoded = "_VIMENC_TEXT";
|
||||||
|
|
||||||
using namespace Qt;
|
using namespace Qt;
|
||||||
|
|
||||||
/*! A \e Mode represents one of the basic modes of operation of FakeVim.
|
/*! A \e Mode represents one of the basic modes of operation of FakeVim.
|
||||||
@@ -406,6 +410,29 @@ static QRegExp vimPatternToQtPattern(QString needle, bool smartcase)
|
|||||||
return QRegExp(pattern);
|
return QRegExp(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setClipboardData(const QString &content, RangeMode mode,
|
||||||
|
QClipboard::Mode clipboardMode)
|
||||||
|
{
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
char vimRangeMode = mode;
|
||||||
|
|
||||||
|
QByteArray bytes1;
|
||||||
|
bytes1.append(vimRangeMode);
|
||||||
|
bytes1.append(content.toUtf8());
|
||||||
|
|
||||||
|
QByteArray bytes2;
|
||||||
|
bytes2.append(vimRangeMode);
|
||||||
|
bytes2.append("utf-8");
|
||||||
|
bytes2.append('\0');
|
||||||
|
bytes2.append(content.toUtf8());
|
||||||
|
|
||||||
|
QMimeData *data = new QMimeData;
|
||||||
|
data->setText(content);
|
||||||
|
data->setData(vimMimeText, bytes1);
|
||||||
|
data->setData(vimMimeTextEncoded, bytes2);
|
||||||
|
clipboard->setMimeData(data, clipboardMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Range::Range()
|
Range::Range()
|
||||||
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
|
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
|
||||||
@@ -1141,9 +1168,8 @@ public:
|
|||||||
|
|
||||||
// register handling
|
// register handling
|
||||||
QString registerContents(int reg) const;
|
QString registerContents(int reg) const;
|
||||||
void setRegisterContents(int reg, const QString &contents);
|
void setRegister(int reg, const QString &contents, RangeMode mode);
|
||||||
RangeMode registerRangeMode(int reg) const;
|
RangeMode registerRangeMode(int reg) const;
|
||||||
void setRegisterRangeMode(int reg, RangeMode mode);
|
|
||||||
void getRegisterType(int reg, bool *isClipboard, bool *isSelection) const;
|
void getRegisterType(int reg, bool *isClipboard, bool *isSelection) const;
|
||||||
|
|
||||||
void recordJump();
|
void recordJump();
|
||||||
@@ -1710,7 +1736,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
|
|||||||
if (m_submode != TransformSubMode) {
|
if (m_submode != TransformSubMode) {
|
||||||
yankText(currentRange(), m_register);
|
yankText(currentRange(), m_register);
|
||||||
if (m_movetype == MoveLineWise)
|
if (m_movetype == MoveLineWise)
|
||||||
setRegisterRangeMode(m_register, RangeLineMode);
|
setRegister(m_register, registerContents(m_register), RangeLineMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_positionPastEnd = m_anchorPastEnd = false;
|
m_positionPastEnd = m_anchorPastEnd = false;
|
||||||
@@ -3744,8 +3770,7 @@ bool FakeVimHandler::Private::handleExDeleteCommand(const ExCommand &cmd)
|
|||||||
removeText(currentRange());
|
removeText(currentRange());
|
||||||
if (!reg.isEmpty()) {
|
if (!reg.isEmpty()) {
|
||||||
const int r = reg.at(0).unicode();
|
const int r = reg.at(0).unicode();
|
||||||
setRegisterContents(r, text);
|
setRegister(r, text, RangeLineMode);
|
||||||
setRegisterRangeMode(r, RangeLineMode);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -4648,8 +4673,7 @@ QString FakeVimHandler::Private::selectText(const Range &range) const
|
|||||||
|
|
||||||
void FakeVimHandler::Private::yankText(const Range &range, int reg)
|
void FakeVimHandler::Private::yankText(const Range &range, int reg)
|
||||||
{
|
{
|
||||||
setRegisterContents(reg, selectText(range));
|
setRegister(reg, selectText(range), range.rangemode);
|
||||||
setRegisterRangeMode(reg, range.rangemode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::transformText(const Range &range,
|
void FakeVimHandler::Private::transformText(const Range &range,
|
||||||
@@ -5387,43 +5411,48 @@ void FakeVimHandler::Private::setMark(int code, int position)
|
|||||||
m_marks[code] = tc;
|
m_marks[code] = tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::setRegisterRangeMode(int reg, RangeMode mode)
|
|
||||||
{
|
|
||||||
g.registers[reg].rangemode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
RangeMode FakeVimHandler::Private::registerRangeMode(int reg) const
|
RangeMode FakeVimHandler::Private::registerRangeMode(int reg) const
|
||||||
{
|
{
|
||||||
bool isClipboard;
|
bool isClipboard;
|
||||||
bool isSelection;
|
bool isSelection;
|
||||||
getRegisterType(reg, &isClipboard, &isSelection);
|
getRegisterType(reg, &isClipboard, &isSelection);
|
||||||
|
|
||||||
|
if (isClipboard || isSelection) {
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
QClipboard::Mode mode = isClipboard ? QClipboard::Clipboard : QClipboard::Selection;
|
||||||
|
|
||||||
|
// Use range mode from Vim's clipboard data if available.
|
||||||
|
const QMimeData *data = clipboard->mimeData(mode);
|
||||||
|
if (data != 0 && data->hasFormat(vimMimeText)) {
|
||||||
|
QByteArray bytes = data->data(vimMimeText);
|
||||||
|
if (bytes.length() > 0)
|
||||||
|
return static_cast<RangeMode>(bytes.at(0));
|
||||||
|
}
|
||||||
|
|
||||||
// If register content is clipboard:
|
// If register content is clipboard:
|
||||||
// - return RangeLineMode if text ends with new line char,
|
// - return RangeLineMode if text ends with new line char,
|
||||||
// - return RangeCharMode otherwise.
|
// - return RangeCharMode otherwise.
|
||||||
if (isClipboard || isSelection) {
|
QString text = clipboard->text(mode);
|
||||||
QString text = QApplication::clipboard()->text(
|
|
||||||
isClipboard ? QClipboard::Clipboard : QClipboard::Selection);
|
|
||||||
return (text.endsWith('\n') || text.endsWith('\r')) ? RangeLineMode : RangeCharMode;
|
return (text.endsWith('\n') || text.endsWith('\r')) ? RangeLineMode : RangeCharMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g.registers[reg].rangemode;
|
return g.registers[reg].rangemode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::setRegisterContents(int reg, const QString &contents)
|
void FakeVimHandler::Private::setRegister(int reg, const QString &contents, RangeMode mode)
|
||||||
{
|
{
|
||||||
bool copyToClipboard;
|
bool copyToClipboard;
|
||||||
bool copyToSelection;
|
bool copyToSelection;
|
||||||
getRegisterType(reg, ©ToClipboard, ©ToSelection);
|
getRegisterType(reg, ©ToClipboard, ©ToSelection);
|
||||||
|
|
||||||
if (copyToClipboard || copyToSelection) {
|
if (copyToClipboard || copyToSelection) {
|
||||||
QClipboard *clipboard = QApplication::clipboard();
|
|
||||||
if (copyToClipboard)
|
if (copyToClipboard)
|
||||||
clipboard->setText(contents, QClipboard::Clipboard);
|
setClipboardData(contents, mode, QClipboard::Clipboard);
|
||||||
if (copyToSelection)
|
if (copyToSelection)
|
||||||
clipboard->setText(contents, QClipboard::Selection);
|
setClipboardData(contents, mode, QClipboard::Selection);
|
||||||
} else {
|
} else {
|
||||||
g.registers[reg].contents = contents;
|
g.registers[reg].contents = contents;
|
||||||
|
g.registers[reg].rangemode = mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,10 +41,12 @@ namespace Internal {
|
|||||||
|
|
||||||
enum RangeMode
|
enum RangeMode
|
||||||
{
|
{
|
||||||
|
// Reordering first three enum items here will break
|
||||||
|
// compatibility with clipboard format stored by Vim.
|
||||||
RangeCharMode, // v
|
RangeCharMode, // v
|
||||||
RangeLineMode, // V
|
RangeLineMode, // V
|
||||||
RangeLineModeExclusive,
|
|
||||||
RangeBlockMode, // Ctrl-v
|
RangeBlockMode, // Ctrl-v
|
||||||
|
RangeLineModeExclusive,
|
||||||
RangeBlockAndTailMode // Ctrl-v for D and X
|
RangeBlockAndTailMode // Ctrl-v for D and X
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user