1// Scintilla source code edit control
2/** @file KeyMap.cxx
3 ** Defines a mapping between keystrokes and commands.
4 **/
5// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6// The License.txt file describes the conditions under which this software may be distributed.
7
8#include <cstdlib>
9
10#include <stdexcept>
11#include <string_view>
12#include <vector>
13#include <map>
14#include <optional>
15#include <memory>
16
17#include "ScintillaTypes.h"
18#include "ScintillaMessages.h"
19
20#include "Debugging.h"
21
22#include "KeyMap.h"
23
24using namespace Scintilla;
25using namespace Scintilla::Internal;
26
27KeyMap::KeyMap() {
28 for (int i = 0; static_cast<int>(MapDefault[i].key); i++) {
29 AssignCmdKey(MapDefault[i].key,
30 MapDefault[i].modifiers,
31 MapDefault[i].msg);
32 }
33}
34
35void KeyMap::Clear() noexcept {
36 kmap.clear();
37}
38
39void KeyMap::AssignCmdKey(Keys key, KeyMod modifiers, Message msg) {
40 kmap[KeyModifiers(key, modifiers)] = msg;
41}
42
43Message KeyMap::Find(Keys key, KeyMod modifiers) const {
44 std::map<KeyModifiers, Message>::const_iterator it = kmap.find(KeyModifiers(key, modifiers));
45 return (it == kmap.end()) ? static_cast<Message>(0) : it->second;
46}
47
48const std::map<KeyModifiers, Message> &KeyMap::GetKeyMap() const noexcept {
49 return kmap;
50}
51
52#if PLAT_GTK_MACOSX
53#define OS_X_KEYS 1
54#else
55#define OS_X_KEYS 0
56#endif
57
58// Define a modifier that is exactly Ctrl key on all platforms
59// Most uses of Ctrl map to Cmd on OS X but some can't so use SCI_[S]CTRL_META
60#if OS_X_KEYS
61#define SCI_CTRL_META SCI_META
62#define SCI_SCTRL_META (SCI_META | SCI_SHIFT)
63#else
64#define SCI_CTRL_META SCI_CTRL
65#define SCI_SCTRL_META (SCI_CTRL | SCI_SHIFT)
66#endif
67
68namespace {
69
70constexpr Keys Key(char ch) noexcept {
71 return static_cast<Keys>(ch);
72}
73
74}
75
76const KeyToCommand KeyMap::MapDefault[] = {
77
78#if OS_X_KEYS
79 {Keys::Down, SCI_CTRL, Message::DocumentEnd},
80 {Keys::Down, SCI_CSHIFT, Message::DocumentEndExtend},
81 {Keys::Up, SCI_CTRL, Message::DocumentStart},
82 {Keys::Up, SCI_CSHIFT, Message::DocumentStartExtend},
83 {Keys::Left, SCI_CTRL, Message::VCHome},
84 {Keys::Left, SCI_CSHIFT, Message::VCHomeExtend},
85 {Keys::Right, SCI_CTRL, Message::LineEnd},
86 {Keys::Right, SCI_CSHIFT, Message::LineEndExtend},
87#endif
88
89 {Keys::Down, SCI_NORM, Message::LineDown},
90 {Keys::Down, SCI_SHIFT, Message::LineDownExtend},
91 {Keys::Down, SCI_CTRL_META, Message::LineScrollDown},
92 {Keys::Down, SCI_ASHIFT, Message::LineDownRectExtend},
93 {Keys::Up, SCI_NORM, Message::LineUp},
94 {Keys::Up, SCI_SHIFT, Message::LineUpExtend},
95 {Keys::Up, SCI_CTRL_META, Message::LineScrollUp},
96 {Keys::Up, SCI_ASHIFT, Message::LineUpRectExtend},
97 {Key('['), SCI_CTRL, Message::ParaUp},
98 {Key('['), SCI_CSHIFT, Message::ParaUpExtend},
99 {Key(']'), SCI_CTRL, Message::ParaDown},
100 {Key(']'), SCI_CSHIFT, Message::ParaDownExtend},
101 {Keys::Left, SCI_NORM, Message::CharLeft},
102 {Keys::Left, SCI_SHIFT, Message::CharLeftExtend},
103 {Keys::Left, SCI_CTRL_META, Message::WordLeft},
104 {Keys::Left, SCI_SCTRL_META, Message::WordLeftExtend},
105 {Keys::Left, SCI_ASHIFT, Message::CharLeftRectExtend},
106 {Keys::Right, SCI_NORM, Message::CharRight},
107 {Keys::Right, SCI_SHIFT, Message::CharRightExtend},
108 {Keys::Right, SCI_CTRL_META, Message::WordRight},
109 {Keys::Right, SCI_SCTRL_META, Message::WordRightExtend},
110 {Keys::Right, SCI_ASHIFT, Message::CharRightRectExtend},
111 {Key('/'), SCI_CTRL, Message::WordPartLeft},
112 {Key('/'), SCI_CSHIFT, Message::WordPartLeftExtend},
113 {Key('\\'), SCI_CTRL, Message::WordPartRight},
114 {Key('\\'), SCI_CSHIFT, Message::WordPartRightExtend},
115 {Keys::Home, SCI_NORM, Message::VCHome},
116 {Keys::Home, SCI_SHIFT, Message::VCHomeExtend},
117 {Keys::Home, SCI_CTRL, Message::DocumentStart},
118 {Keys::Home, SCI_CSHIFT, Message::DocumentStartExtend},
119 {Keys::Home, SCI_ALT, Message::HomeDisplay},
120 {Keys::Home, SCI_ASHIFT, Message::VCHomeRectExtend},
121 {Keys::End, SCI_NORM, Message::LineEnd},
122 {Keys::End, SCI_SHIFT, Message::LineEndExtend},
123 {Keys::End, SCI_CTRL, Message::DocumentEnd},
124 {Keys::End, SCI_CSHIFT, Message::DocumentEndExtend},
125 {Keys::End, SCI_ALT, Message::LineEndDisplay},
126 {Keys::End, SCI_ASHIFT, Message::LineEndRectExtend},
127 {Keys::Prior, SCI_NORM, Message::PageUp},
128 {Keys::Prior, SCI_SHIFT, Message::PageUpExtend},
129 {Keys::Prior, SCI_ASHIFT, Message::PageUpRectExtend},
130 {Keys::Next, SCI_NORM, Message::PageDown},
131 {Keys::Next, SCI_SHIFT, Message::PageDownExtend},
132 {Keys::Next, SCI_ASHIFT, Message::PageDownRectExtend},
133 {Keys::Delete, SCI_NORM, Message::Clear},
134 {Keys::Delete, SCI_SHIFT, Message::Cut},
135 {Keys::Delete, SCI_CTRL, Message::DelWordRight},
136 {Keys::Delete, SCI_CSHIFT, Message::DelLineRight},
137 {Keys::Insert, SCI_NORM, Message::EditToggleOvertype},
138 {Keys::Insert, SCI_SHIFT, Message::Paste},
139 {Keys::Insert, SCI_CTRL, Message::Copy},
140 {Keys::Escape, SCI_NORM, Message::Cancel},
141 {Keys::Back, SCI_NORM, Message::DeleteBack},
142 {Keys::Back, SCI_SHIFT, Message::DeleteBack},
143 {Keys::Back, SCI_CTRL, Message::DelWordLeft},
144 {Keys::Back, SCI_ALT, Message::Undo},
145 {Keys::Back, SCI_CSHIFT, Message::DelLineLeft},
146 {Key('Z'), SCI_CTRL, Message::Undo},
147#if OS_X_KEYS
148 {Key('Z'), SCI_CSHIFT, Message::Redo},
149#else
150 {Key('Y'), SCI_CTRL, Message::Redo},
151#endif
152 {Key('X'), SCI_CTRL, Message::Cut},
153 {Key('C'), SCI_CTRL, Message::Copy},
154 {Key('V'), SCI_CTRL, Message::Paste},
155 {Key('A'), SCI_CTRL, Message::SelectAll},
156 {Keys::Tab, SCI_NORM, Message::Tab},
157 {Keys::Tab, SCI_SHIFT, Message::BackTab},
158 {Keys::Return, SCI_NORM, Message::NewLine},
159 {Keys::Return, SCI_SHIFT, Message::NewLine},
160 {Keys::Add, SCI_CTRL, Message::ZoomIn},
161 {Keys::Subtract, SCI_CTRL, Message::ZoomOut},
162 {Keys::Divide, SCI_CTRL, Message::SetZoom},
163 {Key('L'), SCI_CTRL, Message::LineCut},
164 {Key('L'), SCI_CSHIFT, Message::LineDelete},
165 {Key('T'), SCI_CSHIFT, Message::LineCopy},
166 {Key('T'), SCI_CTRL, Message::LineTranspose},
167 {Key('D'), SCI_CTRL, Message::SelectionDuplicate},
168 {Key('U'), SCI_CTRL, Message::LowerCase},
169 {Key('U'), SCI_CSHIFT, Message::UpperCase},
170 {Key(0),SCI_NORM,static_cast<Message>(0)},
171};
172
173