aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Makemodule.am2
-rw-r--r--src/FbTk/Menu.cc134
-rw-r--r--src/FbTk/Menu.hh9
-rw-r--r--src/FbTk/MenuSearch.cc221
-rw-r--r--src/FbTk/MenuSearch.hh60
-rw-r--r--src/FbTk/Resource.cc12
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
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;
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 @@
37namespace FbTk { 37namespace FbTk {
38 38
39template <typename T> class Command; 39template <typename T> class Command;
40template <typename T> class RefCount;
40class MenuItem; 41class MenuItem;
42class MenuSearch;
41class ImageControl; 43class ImageControl;
42template <typename T> class RefCount;
43 44
44/// Base class for menus 45/// Base class for menus
45class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer { 46class 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
6namespace {
7
8size_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'
13size_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
34size_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
86size_t (*search_str)(const std::string&, const std::string&) = search_str_textstart;
87
88} // anonymous
89
90
91
92namespace FbTk {
93
94
95void 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
107MenuSearch::MenuSearch(const std::vector<FbTk::MenuItem*>& items) :
108 m_items(items) {
109}
110
111size_t MenuSearch::size() const {
112 return pattern.size();
113}
114
115void MenuSearch::clear() {
116 pattern.clear();
117}
118
119void MenuSearch::add(char c) {
120 pattern.push_back(c);
121}
122
123void 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?
131bool 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?
145bool 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
158size_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
175bool 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
193template<>
194std::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
206template<>
207void 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
8namespace FbTk {
9
10class 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
19class MenuSearch {
20public:
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;
53private:
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
34using std::cerr; 30using std::cerr;
35using std::endl; 31using std::endl;
@@ -38,9 +34,9 @@ using std::string;
38namespace FbTk { 34namespace FbTk {
39 35
40ResourceManager::ResourceManager(const char *filename, bool lock_db) : 36ResourceManager::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) {