diff options
Diffstat (limited to 'src/FbTk/Menu.cc')
-rw-r--r-- | src/FbTk/Menu.cc | 134 |
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 | ||
77 | size_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 | ||
130 | namespace FbTk { | 75 | namespace 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. | ||
137 | class FbTk::Menu::TypeSearch { | ||
138 | public: | ||
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; | ||
204 | private: | ||
205 | const std::vector<FbTk::MenuItem*>& m_items; | ||
206 | }; | ||
207 | |||
208 | |||
209 | 77 | ||
210 | Menu* s_shown = 0; // if there's a menu open at all | 78 | Menu* s_shown = 0; // if there's a menu open at all |
211 | Menu* s_focused = 0; // holds currently focused menu | 79 | Menu* 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; |