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.cc287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc
new file mode 100644
index 0000000..817c4f6
--- /dev/null
+++ b/src/FbTk/TextBox.cc
@@ -0,0 +1,287 @@
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.1 2003/08/26 23:24:48 fluxgen Exp $
23
24#include "TextBox.hh"
25#include "Font.hh"
26#include "EventManager.hh"
27#include "App.hh"
28
29#include <cctype>
30#include <X11/keysym.h>
31#include <X11/Xutil.h>
32
33namespace FbTk {
34
35TextBox::TextBox(int screen_num,
36 const Font &font, const std::string &text):
37 FbWindow(screen_num, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask),
38 m_font(&font),
39 m_text(text),
40 m_gc(0),
41 m_cursor_pos(0),
42 m_start_pos(0),
43 m_end_pos(0) {
44
45 FbTk::EventManager::instance()->add(*this, *this);
46}
47
48TextBox::TextBox(const FbWindow &parent,
49 const Font &font, const std::string &text):
50 FbWindow(parent, 0, 0, 1, 1, ExposureMask | KeyPressMask | ButtonPressMask),
51 m_font(&font),
52 m_text(text),
53 m_gc(0),
54 m_cursor_pos(0),
55 m_start_pos(0),
56 m_end_pos(0) {
57
58 FbTk::EventManager::instance()->add(*this, *this);
59}
60
61TextBox::~TextBox() {
62
63}
64
65void TextBox::setText(const std::string &text) {
66 m_text = text;
67 cursorEnd();
68 adjustStartPos();
69}
70
71void TextBox::setFont(const Font &font) {
72 m_font = &font;
73}
74
75void TextBox::setGC(GC gc) {
76 m_gc = gc;
77}
78
79void TextBox::setInputFocus() {
80 XSetInputFocus(FbTk::App::instance()->display(),
81 window(),
82 RevertToParent,
83 CurrentTime);
84}
85
86void TextBox::cursorHome() {
87 m_start_pos = m_cursor_pos = 0;
88}
89
90void TextBox::cursorEnd() {
91 m_cursor_pos = m_end_pos = text().size();
92}
93
94void TextBox::cursorForward() {
95 if (m_start_pos + cursorPosition() < m_end_pos)
96 m_cursor_pos++;
97 else if (m_end_pos < text().size()) {
98 m_cursor_pos++;
99 m_end_pos++;
100 adjustStartPos();
101 }
102}
103
104void TextBox::cursorBackward() {
105 if (cursorPosition())
106 m_cursor_pos--;
107 else if (m_start_pos) {
108 m_start_pos--;
109 adjustEndPos();
110 }
111}
112
113void TextBox::backspace() {
114 if (m_start_pos || cursorPosition()) {
115 m_text.erase(m_start_pos + cursorPosition() - 1, 1);
116 if (cursorPosition())
117 setCursorPosition(cursorPosition() - 1);
118 else
119 m_start_pos--;
120 adjustEndPos();
121 }
122}
123
124void TextBox::deleteForward() {
125 if (m_start_pos + m_cursor_pos < m_end_pos) {
126 m_text.erase(m_start_pos + m_cursor_pos, 1);
127 adjustEndPos();
128 }
129}
130
131void TextBox::insertText(const std::string &val) {
132 m_text.insert(m_start_pos + cursorPosition(), val);
133 m_cursor_pos += val.size();
134 m_end_pos += val.size();
135 if (m_start_pos + cursorPosition() < m_end_pos)
136 adjustEndPos();
137 else
138 adjustStartPos();
139}
140
141void TextBox::killToEnd() {
142 if (cursorPosition() < text().size()) {
143 m_text.erase(cursorPosition());
144 setText(m_text);
145 }
146}
147
148void TextBox::clear() {
149 FbWindow::clear();
150 // center text by default
151 int center_pos = (height() + font().ascent())/2;
152 if (gc() == 0)
153 setGC(DefaultGC(FbTk::App::instance()->display(), screenNumber()));
154
155 font().drawText(window(), screenNumber(),
156 gc(),
157 text().c_str() + m_start_pos,
158 m_end_pos - m_start_pos,
159 0, center_pos); // pos
160
161 // draw cursor position
162 int cursor_pos = font().textWidth(text().c_str() + m_start_pos, m_cursor_pos) + 1;
163 drawLine(gc(), cursor_pos, 0, cursor_pos, font().height());
164}
165
166void TextBox::moveResize(int x, int y,
167 unsigned int width, unsigned int height) {
168 FbWindow::moveResize(x, y, width, height);
169 clear();
170}
171
172void TextBox::resize(unsigned int width, unsigned int height) {
173 FbWindow::resize(width, height);
174 clear();
175}
176
177void TextBox::exposeEvent(XExposeEvent &event) {
178 clear();
179}
180
181void TextBox::buttonPressEvent(XButtonEvent &event) {
182 setInputFocus();
183}
184
185void TextBox::keyPressEvent(XKeyEvent &event) {
186 KeySym ks;
187 char keychar[1];
188 XLookupString(&event, keychar, 1, &ks, 0);
189 // a modifier key by itself doesn't do anything
190 if (IsModifierKey(ks)) return;
191
192 if (event.state) { // handle keybindings without state
193 if (event.state == ControlMask) {
194
195 switch (ks) {
196 case XK_b:
197 cursorBackward();
198 break;
199 case XK_f:
200 cursorForward();
201 break;
202 case XK_a:
203 cursorHome();
204 break;
205 case XK_e:
206 cursorEnd();
207 break;
208 case XK_d:
209 deleteForward();
210 break;
211 case XK_k:
212 killToEnd();
213 break;
214 }
215 } else if (event.state == ShiftMask) {
216 if (isprint(keychar[0])) {
217 std::string val;
218 val += keychar[0];
219 insertText(val);
220 }
221 }
222
223 } else { // no state
224
225 switch (ks) {
226 case XK_BackSpace:
227 backspace();
228 break;
229 case XK_Home:
230 cursorHome();
231 break;
232 case XK_End:
233 cursorEnd();
234 break;
235 case XK_Left:
236 cursorBackward();
237 break;
238 case XK_Right:
239 cursorForward();
240 break;
241 default:
242 if (isprint(keychar[0])) {
243 std::string val;
244 val += keychar[0];
245 insertText(val);
246 }
247 }
248 }
249 clear();
250}
251
252void TextBox::setCursorPosition(int pos) {
253 m_cursor_pos = pos;
254 if (m_cursor_pos > text().size())
255 cursorEnd();
256 else if (m_cursor_pos < 0)
257 cursorHome();
258}
259
260void TextBox::adjustEndPos() {
261 m_end_pos = text().size();
262 int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
263 while (text_width > width()) {
264 m_end_pos--;
265 text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
266 }
267}
268
269void TextBox::adjustStartPos() {
270 int text_width = font().textWidth(text().c_str() + m_start_pos, m_end_pos - m_start_pos);
271 if (text_width < width())
272 return;
273
274 int start_pos = 0;
275 text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos);
276 while (text_width > width()) {
277 start_pos++;
278 text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos);
279 }
280 // adjust cursorPosition() according relative to change to m_start_pos
281 m_cursor_pos -= start_pos - m_start_pos;
282 m_start_pos = start_pos;
283}
284
285
286
287}; // end namespace FbTk