aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Menu.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/Menu.cc')
-rw-r--r--src/FbTk/Menu.cc134
1 files changed, 1 insertions, 133 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index 539c72c..cfbf049 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -69,143 +69,11 @@ void renderMenuPixmap(Pixmap& pm, FbTk::FbWindow* win, int width, int height, co
69 } 69 }
70} 70}
71 71
72
73// finds 'pattern' in 'text', case insensitive.
74// returns position or std::string::npos if not found.
75//
76// implements Boyer–Moore–Horspool
77size_t search_string(const std::string& text, const std::string& pattern) {
78
79 if (pattern.empty()) {
80 return 0;
81 }
82 if (text.empty() || pattern.size() > text.size()) {
83 return std::string::npos;
84 }
85
86 size_t t;
87 size_t tlen = text.size();
88
89 // simple case, no need to be too clever
90 if (pattern.size() == 1) {
91 int b = std::tolower(pattern[0]);
92 for (t = 0; t < tlen; t++) {
93 if (b == std::tolower(text[t])) {
94 return t;
95 }
96 }
97 return std::string::npos;
98 }
99
100
101 size_t plast = pattern.size() - 1;
102 size_t p;
103
104 // prepare skip-table
105 //
106 size_t skip[256];
107 for (p = 0; p < sizeof(skip)/sizeof(skip[0]); p++) {
108 skip[p] = plast + 1;
109 }
110 for (p = 0; p < plast; p++) {
111 skip[std::tolower(pattern[p])] = plast - p;
112 }
113
114 // match
115 for (t = 0; t + plast < tlen; ) {
116 for (p = plast; std::tolower(text[t+p]) == std::tolower(pattern[p]); p--) {
117 if (p == 0) {
118 return t+p;
119 }
120 }
121 t += skip[std::tolower(text[t+p])];
122 }
123
124 return std::string::npos;
125}
126
127} // end of anonymous namespace 72} // end of anonymous namespace
128 73
129 74
130namespace FbTk { 75namespace FbTk {
131 76
132// a small helper which applies search operations on a list of MenuItems*.
133// the former incarnation of this class was FbTk::TypeAhead in combination with
134// the now non-existent FbTk::SearchResults, but the complexity of these
135// are not needed for our use case. as a bonus we have less lose parts
136// flying around.
137class FbTk::Menu::TypeSearch {
138public:
139 TypeSearch(std::vector<FbTk::MenuItem*>& items) : m_items(items) { }
140
141 size_t size() const { return pattern.size(); }
142 void clear() { pattern.clear(); }
143 void add(char c) { pattern.push_back(c); }
144 void backspace() {
145 size_t s = pattern.size();
146 if (s > 0) {
147 pattern.erase(s - 1, 1);
148 }
149 }
150
151 // is 'pattern' matching something?
152 bool has_match() {
153 size_t l = m_items.size();
154 size_t i;
155 for (i = 0; i < l; i++) {
156 if (!m_items[i]->isEnabled())
157 continue;
158 if (search_string(m_items[i]->iTypeString(), pattern) != std::string::npos) {
159 return true;
160 }
161 }
162 return false;
163 }
164
165 // would 'the_pattern' match something?
166 bool would_match(const std::string& the_pattern) {
167 size_t l = m_items.size();
168 size_t i;
169 for (i = 0; i < l; i++) {
170 if (!m_items[i]->isEnabled())
171 continue;
172 if (search_string(m_items[i]->iTypeString(), the_pattern) != std::string::npos) {
173 return true;
174 }
175 }
176 return false;
177 }
178
179 size_t num_matches() {
180 size_t l = m_items.size();
181 size_t i, n;
182 for (i = 0, n = 0; i < l; i++) {
183 if (!m_items[i]->isEnabled())
184 continue;
185 if (search_string(m_items[i]->iTypeString(), pattern) != std::string::npos) {
186 n++;
187 }
188 }
189 return n;
190 }
191
192
193 // returns true if m_text matches against m_items[i] and stores
194 // the position where it matches in the string
195 bool get_match(size_t i, size_t& idx) {
196 if (i > m_items.size()) {
197 return false;
198 }
199 idx = search_string(m_items[i]->iTypeString(), pattern);
200 return idx != std::string::npos;
201 }
202
203 std::string pattern;
204private:
205 const std::vector<FbTk::MenuItem*>& m_items;
206};
207
208
209 77
210Menu* s_shown = 0; // if there's a menu open at all 78Menu* s_shown = 0; // if there's a menu open at all
211Menu* s_focused = 0; // holds currently focused menu 79Menu* s_focused = 0; // holds currently focused menu
@@ -250,7 +118,7 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
250 m_internal_menu = false; 118 m_internal_menu = false;
251 m_state.moving = m_state.closing = m_state.torn = m_state.visible = false; 119 m_state.moving = m_state.closing = m_state.torn = m_state.visible = false;
252 120
253 m_search.reset(new TypeSearch(m_items)); 121 m_search.reset(new MenuSearch(m_items));
254 122
255 m_x_move = m_y_move = 0; 123 m_x_move = m_y_move = 0;
256 m_which_sub = -1; 124 m_which_sub = -1;