1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://sam.zoy.org/wtfpl/COPYING for more details.
21 static const tKeyCN keyList
[] = {
22 {Qt::Key_Escape
, "ESC"},
24 //{Qt::Key_Backtab, "???"},
25 {Qt::Key_Backspace
, "BSP"},
26 {Qt::Key_Return
, "RET"},
27 //{Qt::Key_Enter, "RET"},
28 {Qt::Key_Enter
, "KPRET"},
29 {Qt::Key_Insert
, "INS"},
30 {Qt::Key_Delete
, "DEL"},
31 {Qt::Key_Home
, "HOME"},
33 {Qt::Key_Left
, "LEFT"},
35 {Qt::Key_Right
, "RIGHT"},
36 {Qt::Key_Down
, "DOWN"},
37 {Qt::Key_PageUp
, "PRIOR"},
38 {Qt::Key_PageDown
, "NEXT"},
86 QString
KeyComboList::normalizeKbd (const QString
&kbd
, bool strictShift
) {
87 unsigned char mods
= 0;
88 QString
s(kbd
.trimmed()), res
, t
;
89 if (s
.isEmpty()) return QString();
91 while (pos
+1 < s
.length() && s
.at(pos
+1) == '-') {
92 switch (s
.at(pos
).unicode()) {
93 case 'C': mFlag
= emCtrl
; break;
94 case 'M': mFlag
= emMeta
; break;
95 case 'S': mFlag
= emShift
; break;
96 case 'H': mFlag
= emHyper
; break;
99 if (!mFlag
|| (mods
& mFlag
)) return QString();
103 if (pos
) s
= s
.mid(pos
);
104 if (s
.length() == 1) {
105 if (mods
& emShift
) {
108 } else if (strictShift
) s
= s
.toLower();
109 if (mods
== emCtrl
) s
= s
.toLower();
111 if (mods
& emCtrl
) res
+= "C-";
112 if (mods
& emMeta
) res
+= "M-";
113 if (mods
& emHyper
) res
+= "H-";
114 if (mods
& emShift
) res
+= "S-";
115 //qDebug() << "key:" << t << "rmod:" << res;
116 if (s
.length() > 1) {
117 for (int f
= 0; keyList
[f
].key
; f
++) {
118 QString
kn(keyList
[f
].name
);
119 if (kn
.compare(s
, Qt::CaseInsensitive
) == 0) {
122 //qDebug() << "res:" << res;
128 //qDebug() << "res:" << res;
131 //qDebug() << "wtf?";
136 QString
KeyComboList::event2Kbd (QKeyEvent
*keyev
) {
139 Qt::KeyboardModifiers md
= keyev
->modifiers();
140 if (md
& Qt::ControlModifier
) res
+= "C-";
141 if (md
& Qt::AltModifier
) res
+= "M-";
142 if (md
& Qt::MetaModifier
) res
+= "H-";
143 if (md
& Qt::ShiftModifier
) res
+= "S-";
144 int k
= keyev
->key();
145 if (k
>= 32 && k
<= 0xff00) {
146 res
+= QChar((uint
)k
);
147 return normalizeKbd(res
, true);
149 for (int f
= 0; keyList
[f
].key
; f
++) {
150 if (keyList
[f
].key
== k
) {
151 res
+= keyList
[f
].name
;
152 return normalizeKbd(res
, true);
159 ///////////////////////////////////////////////////////////////////////////////
160 KeyComboList::KeyComboList () {
165 KeyComboList::~KeyComboList () {
169 void KeyComboList::clear () {
176 bool KeyComboList::bind (const QString
&kn
, const QString
&cmd
) {
178 QStringList
cl(kn
.split(' ', QString::SkipEmptyParts
));
180 foreach (const QString
&s
, cl
) {
181 QString
t(normalizeKbd(s
));
182 //qDebug() << "s:" << s << "t:" << t;
184 qWarning() << "invalid keycombo:" << s
;
187 if (!newK
.isEmpty()) newK
+= ' ';
192 int f
; while ((f
= mCombos
.indexOf(newK
)) >= 0) mCombos
.removeAt(f
);
195 if (mCombos
.indexOf(newK
) < 0) mCombos
<< newK
;
201 QString
KeyComboList::process (QKeyEvent
*keyev
) {
202 //qDebug() << "key:" << keyev->key();
203 QString
e(event2Kbd(keyev
));
204 if (e
.isEmpty()) return QString();
205 qDebug() << "ev:" << e
<< "cmb:" << mCurCombo
<< "cond:" << mCurCombo
+" "+e
;
206 mCurComboText
+= keyev
->text();
207 bool first
= mCurCombo
.isEmpty();
208 if (!first
) mCurCombo
+= ' ';
210 bool hasMore
= false;
211 QString
ee(mCurCombo
+' ');
212 //qDebug() << "first:" << first << "cmb:" << mCurCombo;
213 for (int f
= 0, len
= mCombos
.length(); f
< len
; f
++) {
214 //qDebug() << "at f:" << mCombos[f] << "cur:" << mCurCombo;
215 if (mCombos
[f
] == mCurCombo
) {
217 mLastCombo
= mCurCombo
;
218 mLastComboText
= mCurComboText
;
220 return mBinds
[mLastCombo
];
222 if (mCombos
[f
].startsWith(ee
)) hasMore
= true;
227 if (first
) return QString();
228 return QString(" ?");
230 //qDebug() << "HAS MORE";
235 void KeyComboList::reset () {
237 mCurComboText
.clear();
242 static QString
quoteStr (const QString
&s
) {
244 res
.reserve(s
.size()+2); // at least
246 for (int f
= 0; f
< s
.size(); ++f
) {
248 if (ch
== '"' || ch
== '\\') { res
+= '\\'; res
+= ch
; }
249 else if (ch
== '\t') res
+= "\\t";
250 else if (ch
== '\n') res
+= "\\n";
251 else if (ch
.unicode() <= 32 || ch
.unicode() >= 0xff00) res
+= ' ';
259 QStringList
KeyComboList::toString () const {
261 foreach (const QString
&kk
, mCombos
) {
263 res
<< quoteStr(mBinds
[kk
]);
269 bool KeyComboList::isProcessing () const {
270 return !(mCurCombo
.isEmpty());
274 void KeyComboList::appendFrom (KeyComboList
*kl
) {
276 foreach (const QString
&kk
, kl
->mCombos
) bind(kk
, kl
->mBinds
[kk
]);