aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/TextBox.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/TextBox.cc')
-rw-r--r--src/FbTk/TextBox.cc291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc
new file mode 100644
index 0000000..519b56e
--- /dev/null
+++ b/src/FbTk/TextBox.cc
@@ -0,0 +1,291 @@
1// TextBox.cc for FbTk - fluxbox toolkit
2// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22// $Id: TextBox.cc,v 1.3 2003/10/05 07:20:47 rathnor Exp $
23
24#include "TextBox.hh"
25#include "Font.hh"
26#include "EventManager.hh"
27#include "App.hh"
28#include "KeyUtil.hh"
29
30#include <cctype>
31#include <X11/keysym.h>
32#include <X11/Xutil.h>
33
34namespace FbTk {
35
36TextBox::TextBox(int screen_num,
37 const Font &font, const std::string &text):
38 FbWindow(screen_num, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask),
39 m_font(&font),
40 m_text(text),
41 m_gc(0),
42 m_cursor_pos(0),
43 m_start_pos(0),
44 m_end_pos(0) {
45
46 FbTk::EventManager::instance()->add(*this, *this);
47}
48
49TextBox::TextBox(const FbWindow &parent,
50 const Font &font, const std::string &text):
51 FbWindow(parent, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask),
52 m_font(&font),
53 m_text(text),
54 m_gc(0),
55 m_cursor_pos(0),
56 m_start_pos(0),
57 m_end_pos(0) {
58
59 FbTk::EventManager::instance()->add(*this, *this);
60}
61
62TextBox::~TextBox() {
63
64}
65
66void TextBox::setText(const std::string &text) {
67 m_text = text;
68 cursorEnd();
69 adjustStartPos();
70}
71
72void TextBox::setFont(const Font &font) {
73 m_font = &font;
74}
75
76void TextBox::setGC(GC gc) {
77 m_gc = gc;
78}
79
80void TextBox::setInputFocus() {
81 XSetInputFocus(FbTk::App::instance()->display(),
82 window(),
83 RevertToParent,
84 CurrentTime);
85}
86
87void TextBox::cursorHome() {
88 m_start_pos = m_cursor_pos = 0;
89}
90
91void TextBox::cursorEnd() {
92 m_cursor_pos = m_end_pos = text().size();
93}
94
95void TextBox::cursorForward() {
96 if (m_start_pos + cursorPosition() < m_end_pos)
97 m_cursor_pos++;
98 else if (m_end_pos < text().size()) {
99 m_cursor_pos++;
100 m_end_pos++;
101 adjustStartPos();
102 }
103}
104
105void TextBox::cursorBackward() {
106 if (cursorPosition())
107 m_cursor_pos--;
108 else if (m_start_pos) {
109 m_start_pos--;
110 adjustEndPos();
111 }
112}
113
114void TextBox::backspace() {
115 if (m_start_pos || cursorPosition()) {
116 m_text.erase(m_start_pos + cursorPosition() - 1, 1);
117 if (cursorPosition())
118 setCursorPosition(cursorPosition() - 1);
119 else
120 m_start_pos--;
121 adjustEndPos();
122 }
123}
124
125void TextBox::deleteForward() {
126 if (m_start_pos + m_cursor_pos < m_end_pos) {
127 m_text.erase(m_start_pos + m_cursor_pos, 1);
128 adjustEndPos();
129 }
130}
131
132void TextBox::insertText(const std::string &val) {
133 m_text.insert(m_start_pos + cursorPosition(), val);
134 m_cursor_pos += val.size();
135 m_end_pos += val.size();
136 if (m_start_pos + cursorPosition() < m_end_pos)
137 adjustEndPos();
138 else
139 adjustStartPos();
140}
141
142void TextBox::killToEnd() {
143 if (cursorPosition() < text().size()) {
144 m_text.erase(cursorPosition());
145 setText(m_text);
146 }
147}
148
149void TextBox::clear() {
150 FbWindow::clear();
151 // center text by default
152 int center_pos = (height() + font().ascent())/2;
153 if (gc() == 0)
154 setGC(DefaultGC(FbTk::App::instance()->display(), screenNumber()));
155
156 font().drawText(window(), screenNumber(),
157 gc(),
158 text().c_str() + m_start_pos,
159 m_end_pos - m_start_pos,
160 0, center_pos); // pos
161
162 // draw cursor position
163 int cursor_pos = font().textWidth(text().c_str() + m_start_pos, m_cursor_pos) + 1;
164 drawLine(gc(), cursor_pos, 0, cursor_pos, font().height());
165}
166
167void TextBox::moveResize(int x, int y,
168 unsigned int width, unsigned int height) {
169 FbWindow::moveResize(x, y, width, height);
170 clear();
171}
172
173void TextBox::resize(unsigned int width, unsigned int height) {
174 FbWindow::resize(width, height);
175 clear();
176}
177
178void TextBox::exposeEvent(XExposeEvent &event) {
179 clear();
180}
181
182void TextBox::buttonPressEvent(XButtonEvent &event) {
183 setInputFocus();
184}
185
186void TextBox::keyPressEvent(XKeyEvent &event) {
187 // strip numlock and scrolllock mask
188 event.state = KeyUtil::cleanMods(event.state);
189
190 KeySym ks;
191 char keychar[1];
192 XLookupString(&event, keychar, 1, &ks, 0);
193 // a modifier key by itself doesn't do anything
194 if (IsModifierKey(ks)) return;
195
196 if (event.state) { // handle keybindings without state
197 if (event.state == ControlMask) {
198
199 switch (ks) {
200 case XK_b:
201 cursorBackward();
202 break;
203 case XK_f:
204 cursorForward();
205 break;
206 case XK_a:
207 cursorHome();
208 break;
209 case XK_e:
210 cursorEnd();
211 break;
212 case XK_d:
213 deleteForward();
214 break;
215 case XK_k:
216 killToEnd();
217 break;
218 }
219 } else if (event.state == ShiftMask) {
220 if (isprint(keychar[0])) {
221 std::string val;
222 val += keychar[0];
223 insertText(val);
224 }
225 }
226
227 } else { // no state
228
229 switch (ks) {
230 case XK_BackSpace:
231 backspace();
232 break;
233 case XK_Home:
234 cursorHome();
235 break;
236 case XK_End:
237 cursorEnd();
238 break;
239 case XK_Left:
240 cursorBackward();
241 break;
242 case XK_Right:
243 cursorForward();
244 break;
245 default:
246 if (isprint(keychar[0])) {
247 std::string val;
248 val += keychar[0];
249 insertText(val);
250 }
251 }
252 }
253 clear();
254}
255
256void TextBox::setCursorPosition(int pos) {
257 m_cursor_pos = pos;
258 if (m_cursor_pos > text().size())
259 cursorEnd();
260 else if (m_cursor_pos < 0)
261 cursorHome();
262}
263
264void TextBox::adjustEndPos() {
265 m_end_pos = text().size();
266 int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
267 while (text_width > width()) {
268 m_end_pos--;
269 text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
270 }
271}
272
273void TextBox::adjustStartPos() {
274 int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
275 if (text_width < width())
276 return;
277
278 int start_pos = 0;
279 text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos);
280 while (text_width > width()) {
281 start_pos++;
282 text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos);
283 }
284 // adjust cursorPosition() according relative to change to m_start_pos
285 m_cursor_pos -= start_pos - m_start_pos;
286 m_start_pos = start_pos;
287}
288
289
290
291}; // end namespace FbTk