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 | |
15 | using namespace KateVi; |
16 | |
17 | void 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 | |
34 | void 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 | |
58 | void Registers::setInsertStopped(const QString &text) |
59 | { |
60 | set(reg: InsertStoppedRegister, text); |
61 | } |
62 | |
63 | void Registers::set(const QChar ®, 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 | |
89 | QString Registers::getContent(const QChar ®) const |
90 | { |
91 | return getRegister(reg).first; |
92 | } |
93 | |
94 | OperationMode Registers::getFlag(const QChar ®) const |
95 | { |
96 | return getRegister(reg).second; |
97 | } |
98 | |
99 | Registers::Register Registers::getRegister(const QChar ®) 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 | |
130 | void Registers::setNumberedRegister(const QChar ®, 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 | |