1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef KEYSET_H
4 #define KEYSET_H
5 
6 #include <string>
7 #include <deque>
8 #include "System/Misc/SpringTime.h"
9 
10 
11 class CKeySet {
12 	public:
CKeySet()13 		CKeySet() { Reset(); }
14 		CKeySet(int key, bool release);
15 
16 		void Reset();
17 		void SetAnyBit();
18 		void ClearModifiers();
19 		bool Parse(const std::string& token, bool showerror = true);
20 
21 		std::string GetString(bool useDefaultKeysym) const;
22 
23 		enum CKeySetModifiers {
24 			KS_ALT     = (1 << 0),
25 			KS_CTRL    = (1 << 1),
26 			KS_META    = (1 << 2),
27 			KS_SHIFT   = (1 << 3),
28 			KS_ANYMOD  = (1 << 4),
29 			KS_RELEASE = (1 << 5)
30 		};
31 
Key()32 		int  Key()     const { return key; }
Mod()33 		unsigned char Mod() const { return modifiers; }
Alt()34 		bool Alt()     const { return !!(modifiers & KS_ALT); }
Ctrl()35 		bool Ctrl()    const { return !!(modifiers & KS_CTRL); }
Meta()36 		bool Meta()    const { return !!(modifiers & KS_META); }
Shift()37 		bool Shift()   const { return !!(modifiers & KS_SHIFT); }
AnyMod()38 		bool AnyMod()  const { return !!(modifiers & KS_ANYMOD); }
Release()39 		bool Release() const { return !!(modifiers & KS_RELEASE); }
40 
41 		bool IsPureModifier() const;
42 
43 		bool operator<(const CKeySet& ks) const
44 		{
45 			if (key < ks.key) { return true; }
46 			if (key > ks.key) { return false; }
47 			if (modifiers < ks.modifiers) { return true; }
48 			if (modifiers > ks.modifiers) { return false; }
49 			return false;
50 		}
51 
fit(const CKeySet & ks)52 		bool fit(const CKeySet& ks) const
53 		{
54 			return (key == ks.key) && ((modifiers == ks.modifiers) || AnyMod() || ks.AnyMod());
55 		}
56 
57 		bool operator==(const CKeySet& ks) const
58 		{
59 			return ((key == ks.key) && (modifiers == ks.modifiers));
60 		}
61 
62 		bool operator!=(const CKeySet& ks) const
63 		{
64 			return ((key != ks.key) || (modifiers != ks.modifiers));
65 		}
66 
67 	protected:
68 		bool ParseModifier(std::string& s, const std::string& token, const std::string& abbr);
69 
70 	protected:
71 		int key;
72 		unsigned char modifiers;
73 };
74 
75 
76 class CKeyChain : public std::deque<CKeySet>
77 {
78 	public:
79 		bool operator<(const CKeyChain& kc) const
80 		{
81 			if (size() < kc.size()) { return true;  }
82 			if (size() > kc.size()) { return false; }
83 			if (empty())            { return false; }
84 			return (back() < kc.back());
85 		}
86 
87 		bool operator==(const CKeyChain& needle) const
88 		{
89 			if (size() != needle.size())
90 				return false;
91 
92 			return std::equal(needle.rbegin(), needle.rend(), rbegin());
93 		}
94 
fit(const CKeyChain & needle)95 		bool fit(const CKeyChain& needle) const
96 		{
97 			// Scans the chain (*this) for a needle from the _back_
98 			// e.g. chain=a,b,c,d will fit needle=b,c,d but won't fit needle=a,b,c!
99 
100 			if (size() < needle.size())
101 				return false;
102 
103 			return std::equal(needle.rbegin(), needle.rend(), rbegin(), [](const CKeySet& a, const CKeySet& b) { return b.fit(a); });
104 		}
105 
GetString()106 		std::string GetString() const
107 		{
108 			std::string s;
109 			for (const CKeySet& ks: *this) {
110 				if (!s.empty()) s += ",";
111 				s += ks.GetString(true);
112 			}
113 			return s;
114 		}
115 };
116 
117 
118 class CTimedKeyChain : public CKeyChain
119 {
120 	public:
121 		std::deque<spring_time> times;
122 
clear()123 		void clear()
124 		{
125 			CKeyChain::clear();
126 			times.clear();
127 		}
128 
129 		void push_back(const int key, const spring_time t, const bool isRepeat);
emplace_back(const CKeySet & ks,const spring_time t)130 		void emplace_back(const CKeySet& ks, const spring_time t) { assert(false); }
131 };
132 
133 
134 #endif /* KEYSET_H */
135