1/*
2 SPDX-FileCopyrightText: KDE Developers
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "registers.h"
8#include "katepartdebug.h"
9
10#include <KConfigGroup>
11
12#include <QApplication>
13#include <QClipboard>
14
15using namespace KateVi;
16
17void Registers::readConfig(const KConfigGroup &config)
18{
19 const QStringList names = config.readEntry(key: "ViRegisterNames", aDefault: QStringList());
20 const QStringList contents = config.readEntry(key: "ViRegisterContents", aDefault: QStringList());
21 const QList<int> flags = config.readEntry(key: "ViRegisterFlags", defaultValue: QList<int>());
22
23 if (names.size() != contents.size() || contents.size() != flags.size()) {
24 return;
25 }
26
27 for (int i = 0; i < names.size(); i++) {
28 if (!names.at(i).isEmpty()) {
29 set(reg: names.at(i).at(i: 0), text: contents.at(i), flag: (OperationMode)(flags.at(i)));
30 }
31 }
32}
33
34void Registers::writeConfig(KConfigGroup &config) const
35{
36 if (m_registers.empty()) {
37 return;
38 }
39
40 QStringList names;
41 QStringList contents;
42 QList<int> flags;
43 for (const auto &[name, reg] : m_registers) {
44 if (reg.first.length() <= 1000) {
45 names << name;
46 contents << reg.first;
47 flags << int(reg.second);
48 } else {
49 qCDebug(LOG_KTE) << "Did not save contents of register " << name << ": contents too long (" << reg.first.length() << " characters)";
50 }
51 }
52
53 config.writeEntry(key: "ViRegisterNames", value: names);
54 config.writeEntry(key: "ViRegisterContents", value: contents);
55 config.writeEntry(key: "ViRegisterFlags", list: flags);
56}
57
58void Registers::setInsertStopped(const QString &text)
59{
60 set(reg: InsertStoppedRegister, text);
61}
62
63void Registers::set(const QChar &reg, const QString &text, OperationMode flag)
64{
65 if (reg == BlackHoleRegister) {
66 return;
67 }
68
69 if (reg == PrependNumberedRegister || (reg >= FirstNumberedRegister && reg <= LastNumberedRegister)) { // "kill ring" registers
70 setNumberedRegister(reg, text, flag);
71 } else if (reg == SystemClipboardRegister) {
72 QApplication::clipboard()->setText(text, mode: QClipboard::Clipboard);
73 } else if (reg == SystemSelectionRegister) {
74 QApplication::clipboard()->setText(text, mode: QClipboard::Selection);
75 } else {
76 const QChar lowercase_reg = reg.toLower();
77 if (reg != lowercase_reg) {
78 m_registers[lowercase_reg].first.append(s: text);
79 } else {
80 m_registers.insert_or_assign(k: lowercase_reg, obj: Register(text, flag));
81 }
82 }
83
84 if (reg == ZeroRegister || reg == PrependNumberedRegister || reg == SmallDeleteRegister) {
85 m_default = reg;
86 }
87}
88
89QString Registers::getContent(const QChar &reg) const
90{
91 return getRegister(reg).first;
92}
93
94OperationMode Registers::getFlag(const QChar &reg) const
95{
96 return getRegister(reg).second;
97}
98
99Registers::Register Registers::getRegister(const QChar &reg) const
100{
101 Register regPair;
102 QChar _reg = (reg != UnnamedRegister ? reg : m_default);
103
104 if (_reg >= FirstNumberedRegister && _reg <= LastNumberedRegister) {
105 int index = _reg.digitValue() - 1;
106 if (m_numbered.size() > index) {
107 regPair = m_numbered.at(i: index);
108 }
109 } else if (_reg == PrependNumberedRegister) {
110 if (!m_numbered.isEmpty()) {
111 regPair = m_numbered.front();
112 }
113 } else if (_reg == SystemClipboardRegister) {
114 QString regContent = QApplication::clipboard()->text(mode: QClipboard::Clipboard);
115 regPair = Register(regContent, CharWise);
116 } else if (_reg == SystemSelectionRegister) {
117 QString regContent = QApplication::clipboard()->text(mode: QClipboard::Selection);
118 regPair = Register(regContent, CharWise);
119 } else {
120 const QChar lowercase_reg = _reg.toLower();
121 auto it = m_registers.find(x: lowercase_reg);
122 if (it != m_registers.end()) {
123 return it->second;
124 }
125 }
126
127 return regPair;
128}
129
130void Registers::setNumberedRegister(const QChar &reg, const QString &text, OperationMode flag)
131{
132 int index = reg.digitValue() - 1;
133 if (reg == PrependNumberedRegister || index > m_numbered.size()) {
134 if (m_numbered.size() == 9) {
135 m_numbered.removeLast();
136 }
137
138 // register 0 is used for the last yank command, so insert at position 1
139 m_numbered.prepend(t: Register(text, flag));
140 } else {
141 m_numbered[index].first = text;
142 m_numbered[index].second = flag;
143 }
144}
145

source code of ktexteditor/src/vimode/registers.cpp