diff options
Diffstat (limited to 'src/FbTk')
-rw-r--r-- | src/FbTk/Makemodule.am | 2 | ||||
-rw-r--r-- | src/FbTk/Menu.cc | 134 | ||||
-rw-r--r-- | src/FbTk/Menu.hh | 9 | ||||
-rw-r--r-- | src/FbTk/MenuSearch.cc | 221 | ||||
-rw-r--r-- | src/FbTk/MenuSearch.hh | 60 | ||||
-rw-r--r-- | src/FbTk/Resource.cc | 12 |
6 files changed, 292 insertions, 146 deletions
diff --git a/src/FbTk/Makemodule.am b/src/FbTk/Makemodule.am index 57f70f2..3433429 100644 --- a/src/FbTk/Makemodule.am +++ b/src/FbTk/Makemodule.am | |||
@@ -102,6 +102,8 @@ libFbTk_a_SOURCES = \ | |||
102 | src/FbTk/Menu.hh \ | 102 | src/FbTk/Menu.hh \ |
103 | src/FbTk/MenuItem.cc \ | 103 | src/FbTk/MenuItem.cc \ |
104 | src/FbTk/MenuItem.hh \ | 104 | src/FbTk/MenuItem.hh \ |
105 | src/FbTk/MenuSearch.hh \ | ||
106 | src/FbTk/MenuSearch.cc \ | ||
105 | src/FbTk/MenuSeparator.cc \ | 107 | src/FbTk/MenuSeparator.cc \ |
106 | src/FbTk/MenuSeparator.hh \ | 108 | src/FbTk/MenuSeparator.hh \ |
107 | src/FbTk/MenuTheme.cc \ | 109 | src/FbTk/MenuTheme.cc \ |
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; |
diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 39440a8..8bb5fdd 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh | |||
@@ -37,9 +37,10 @@ | |||
37 | namespace FbTk { | 37 | namespace FbTk { |
38 | 38 | ||
39 | template <typename T> class Command; | 39 | template <typename T> class Command; |
40 | template <typename T> class RefCount; | ||
40 | class MenuItem; | 41 | class MenuItem; |
42 | class MenuSearch; | ||
41 | class ImageControl; | 43 | class ImageControl; |
42 | template <typename T> class RefCount; | ||
43 | 44 | ||
44 | /// Base class for menus | 45 | /// Base class for menus |
45 | class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer { | 46 | class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer { |
@@ -187,10 +188,8 @@ private: | |||
187 | 188 | ||
188 | Menu *m_parent; | 189 | Menu *m_parent; |
189 | 190 | ||
190 | class TypeSearch; | 191 | std::vector<MenuItem*> m_items; |
191 | 192 | std::auto_ptr<MenuSearch> m_search; | |
192 | std::vector<MenuItem *> m_items; | ||
193 | std::auto_ptr<TypeSearch> m_search; | ||
194 | 193 | ||
195 | struct State { | 194 | struct State { |
196 | bool moving; | 195 | bool moving; |
diff --git a/src/FbTk/MenuSearch.cc b/src/FbTk/MenuSearch.cc new file mode 100644 index 0000000..da903f4 --- /dev/null +++ b/src/FbTk/MenuSearch.cc | |||
@@ -0,0 +1,221 @@ | |||
1 | #include "MenuSearch.hh" | ||
2 | #include "MenuItem.hh" | ||
3 | #include "StringUtil.hh" | ||
4 | #include "Resource.hh" | ||
5 | |||
6 | namespace { | ||
7 | |||
8 | size_t search_str_nowhere(const std::string& text, const std::string& pattern) { | ||
9 | return std::string::npos; | ||
10 | } | ||
11 | |||
12 | // finds 'pattern' at beginning of 'text' | ||
13 | size_t search_str_textstart(const std::string& text, const std::string& pattern) { | ||
14 | |||
15 | size_t l = std::min(text.size(), pattern.size()); | ||
16 | if (l == 0) { | ||
17 | return std::string::npos; | ||
18 | } | ||
19 | |||
20 | size_t i; | ||
21 | for (i = l; i > 0; i--) { | ||
22 | if (std::tolower(text[i-1]) != std::tolower(pattern[i-1])) { | ||
23 | return std::string::npos; | ||
24 | } | ||
25 | } | ||
26 | |||
27 | return i; | ||
28 | } | ||
29 | |||
30 | // finds 'pattern' in 'text', case insensitive. | ||
31 | // returns position or std::string::npos if not found. | ||
32 | // | ||
33 | // implements Boyer–Moore–Horspool | ||
34 | size_t search_str_bmh(const std::string& text, const std::string& pattern) { | ||
35 | |||
36 | if (pattern.empty()) { | ||
37 | return 0; | ||
38 | } | ||
39 | if (text.empty() || pattern.size() > text.size()) { | ||
40 | return std::string::npos; | ||
41 | } | ||
42 | |||
43 | size_t t; | ||
44 | size_t tlen = text.size(); | ||
45 | |||
46 | // simple case, no need to be too clever | ||
47 | if (pattern.size() == 1) { | ||
48 | int b = std::tolower(pattern[0]); | ||
49 | for (t = 0; t < tlen; t++) { | ||
50 | if (b == std::tolower(text[t])) { | ||
51 | return t; | ||
52 | } | ||
53 | } | ||
54 | return std::string::npos; | ||
55 | } | ||
56 | |||
57 | |||
58 | size_t plast = pattern.size() - 1; | ||
59 | size_t p; | ||
60 | |||
61 | // prepare skip-table | ||
62 | // | ||
63 | size_t skip[256]; | ||
64 | for (p = 0; p < sizeof(skip)/sizeof(skip[0]); p++) { | ||
65 | skip[p] = plast + 1; | ||
66 | } | ||
67 | for (p = 0; p < plast; p++) { | ||
68 | skip[std::tolower(pattern[p])] = plast - p; | ||
69 | } | ||
70 | |||
71 | // match | ||
72 | for (t = 0; t + plast < tlen; ) { | ||
73 | for (p = plast; std::tolower(text[t+p]) == std::tolower(pattern[p]); p--) { | ||
74 | if (p == 0) { | ||
75 | return t+p; | ||
76 | } | ||
77 | } | ||
78 | t += skip[std::tolower(text[t+p])]; | ||
79 | } | ||
80 | |||
81 | return std::string::npos; | ||
82 | } | ||
83 | |||
84 | |||
85 | // actually search function, depends on Mode | ||
86 | size_t (*search_str)(const std::string&, const std::string&) = search_str_textstart; | ||
87 | |||
88 | } // anonymous | ||
89 | |||
90 | |||
91 | |||
92 | namespace FbTk { | ||
93 | |||
94 | |||
95 | void MenuSearch::setMode(MenuSearch::Mode m) { | ||
96 | if (m == NOWHERE) { | ||
97 | search_str = search_str_nowhere; | ||
98 | } else if (m == SOMEWHERE) { | ||
99 | search_str = search_str_bmh; | ||
100 | } else { | ||
101 | search_str = search_str_textstart; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | |||
106 | |||
107 | MenuSearch::MenuSearch(const std::vector<FbTk::MenuItem*>& items) : | ||
108 | m_items(items) { | ||
109 | } | ||
110 | |||
111 | size_t MenuSearch::size() const { | ||
112 | return pattern.size(); | ||
113 | } | ||
114 | |||
115 | void MenuSearch::clear() { | ||
116 | pattern.clear(); | ||
117 | } | ||
118 | |||
119 | void MenuSearch::add(char c) { | ||
120 | pattern.push_back(c); | ||
121 | } | ||
122 | |||
123 | void MenuSearch::backspace() { | ||
124 | size_t s = pattern.size(); | ||
125 | if (s > 0) { | ||
126 | pattern.erase(s - 1, 1); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | // is 'pattern' matching something? | ||
131 | bool MenuSearch::has_match() { | ||
132 | size_t l = m_items.size(); | ||
133 | size_t i; | ||
134 | for (i = 0; i < l; i++) { | ||
135 | if (!m_items[i]->isEnabled()) | ||
136 | continue; | ||
137 | if (search_str(m_items[i]->iTypeString(), pattern) != std::string::npos) { | ||
138 | return true; | ||
139 | } | ||
140 | } | ||
141 | return false; | ||
142 | } | ||
143 | |||
144 | // would 'the_pattern' match something? | ||
145 | bool MenuSearch::would_match(const std::string& the_pattern) { | ||
146 | size_t l = m_items.size(); | ||
147 | size_t i; | ||
148 | for (i = 0; i < l; i++) { | ||
149 | if (!m_items[i]->isEnabled()) | ||
150 | continue; | ||
151 | if (search_str(m_items[i]->iTypeString(), the_pattern) != std::string::npos) { | ||
152 | return true; | ||
153 | } | ||
154 | } | ||
155 | return false; | ||
156 | } | ||
157 | |||
158 | size_t MenuSearch::num_matches() { | ||
159 | size_t l = m_items.size(); | ||
160 | size_t i, n; | ||
161 | for (i = 0, n = 0; i < l; i++) { | ||
162 | if (!m_items[i]->isEnabled()) | ||
163 | continue; | ||
164 | if (search_str(m_items[i]->iTypeString(), pattern) != std::string::npos) { | ||
165 | n++; | ||
166 | } | ||
167 | } | ||
168 | return n; | ||
169 | } | ||
170 | |||
171 | |||
172 | // returns true if m_text matches against m_items[i] and stores | ||
173 | // the position where it matches in the string. an empty | ||
174 | // 'pattern' always matches | ||
175 | bool MenuSearch::get_match(size_t i, size_t& idx) { | ||
176 | if (i > m_items.size()) { | ||
177 | return false; | ||
178 | } | ||
179 | |||
180 | if (pattern.empty()) | ||
181 | return true; | ||
182 | |||
183 | idx = search_str(m_items[i]->iTypeString(), pattern); | ||
184 | return idx != std::string::npos; | ||
185 | } | ||
186 | |||
187 | |||
188 | |||
189 | |||
190 | // | ||
191 | // resource-implementation related | ||
192 | |||
193 | template<> | ||
194 | std::string FbTk::Resource<FbTk::MenuSearch::Mode>::getString() const { | ||
195 | |||
196 | switch (m_value) { | ||
197 | case FbTk::MenuSearch::NOWHERE: | ||
198 | return "nowhere"; | ||
199 | case FbTk::MenuSearch::SOMEWHERE: | ||
200 | return "somewhere"; | ||
201 | default: | ||
202 | return "itemstart"; | ||
203 | }; | ||
204 | } | ||
205 | |||
206 | template<> | ||
207 | void FbTk::Resource<FbTk::MenuSearch::Mode>::setFromString(const char *strval) { | ||
208 | |||
209 | std::string val = FbTk::StringUtil::toLower(strval); | ||
210 | if (val == "nowhere") { | ||
211 | m_value = FbTk::MenuSearch::NOWHERE; | ||
212 | } else if (val == "somewhere") { | ||
213 | m_value = FbTk::MenuSearch::SOMEWHERE; | ||
214 | } else { | ||
215 | setDefaultValue(); | ||
216 | } | ||
217 | |||
218 | std::cerr << "** " << val << " " << m_value << "\n"; | ||
219 | } | ||
220 | |||
221 | } | ||
diff --git a/src/FbTk/MenuSearch.hh b/src/FbTk/MenuSearch.hh new file mode 100644 index 0000000..d642929 --- /dev/null +++ b/src/FbTk/MenuSearch.hh | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef _MENU_SEARCH_HH_ | ||
2 | #define _MENU_SEARCH_HH_ | ||
3 | |||
4 | #include <vector> | ||
5 | #include <string> | ||
6 | #include <cstddef> | ||
7 | |||
8 | namespace FbTk { | ||
9 | |||
10 | class MenuItem; | ||
11 | |||
12 | |||
13 | // a small helper which applies search operations on a list of MenuItems*. | ||
14 | // the former incarnation of this class was FbTk::TypeAhead in combination with | ||
15 | // the now non-existent FbTk::SearchResults, but the complexity of these | ||
16 | // are not needed for our use case. as a bonus we have less lose parts | ||
17 | // flying around. | ||
18 | |||
19 | class MenuSearch { | ||
20 | public: | ||
21 | |||
22 | enum Mode { | ||
23 | NOWHERE, | ||
24 | ITEMSTART, | ||
25 | SOMEWHERE, | ||
26 | |||
27 | DEFAULT = ITEMSTART | ||
28 | }; | ||
29 | |||
30 | static void setMode(Mode m); | ||
31 | |||
32 | |||
33 | MenuSearch(const std::vector<FbTk::MenuItem*>& items); | ||
34 | |||
35 | size_t size() const; | ||
36 | void clear(); | ||
37 | void add(char c); | ||
38 | void backspace(); | ||
39 | |||
40 | // is 'pattern' matching something? | ||
41 | bool has_match(); | ||
42 | |||
43 | // would 'the_pattern' match something? | ||
44 | bool would_match(const std::string& the_pattern); | ||
45 | |||
46 | size_t num_matches(); | ||
47 | |||
48 | // returns true if m_text matches against m_items[i] and stores | ||
49 | // the position where it matches in the string | ||
50 | bool get_match(size_t i, size_t& idx); | ||
51 | |||
52 | std::string pattern; | ||
53 | private: | ||
54 | const std::vector<FbTk::MenuItem*>& m_items; | ||
55 | }; | ||
56 | |||
57 | } | ||
58 | |||
59 | |||
60 | #endif | ||
diff --git a/src/FbTk/Resource.cc b/src/FbTk/Resource.cc index 4be85de..af0c4c2 100644 --- a/src/FbTk/Resource.cc +++ b/src/FbTk/Resource.cc | |||
@@ -25,11 +25,7 @@ | |||
25 | #include "StringUtil.hh" | 25 | #include "StringUtil.hh" |
26 | 26 | ||
27 | #include <iostream> | 27 | #include <iostream> |
28 | #ifdef HAVE_CASSERT | 28 | #include <cassert> |
29 | #include <cassert> | ||
30 | #else | ||
31 | #include <assert.h> | ||
32 | #endif | ||
33 | 29 | ||
34 | using std::cerr; | 30 | using std::cerr; |
35 | using std::endl; | 31 | using std::endl; |
@@ -38,9 +34,9 @@ using std::string; | |||
38 | namespace FbTk { | 34 | namespace FbTk { |
39 | 35 | ||
40 | ResourceManager::ResourceManager(const char *filename, bool lock_db) : | 36 | ResourceManager::ResourceManager(const char *filename, bool lock_db) : |
41 | m_db_lock(0), | 37 | m_db_lock(0), |
42 | m_database(0), | 38 | m_database(0), |
43 | m_filename(filename ? filename : "") | 39 | m_filename(filename ? filename : "") |
44 | { | 40 | { |
45 | static bool xrm_initialized = false; | 41 | static bool xrm_initialized = false; |
46 | if (!xrm_initialized) { | 42 | if (!xrm_initialized) { |