aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/TextBox.cc
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2010-09-08 18:17:21 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2010-09-08 18:17:21 (GMT)
commit690d926ac444243611cd875fb84fabb4e6db2cf2 (patch)
treec8ef84056b295071f9a9207ffea5393c6cf4ad4d /src/FbTk/TextBox.cc
parent1e8fe2bc14856fa16508686a28a85e72cb0e422c (diff)
downloadfluxbox_pavel-690d926ac444243611cd875fb84fabb4e6db2cf2.zip
fluxbox_pavel-690d926ac444243611cd875fb84fabb4e6db2cf2.tar.bz2
introduced FbTk::BidiString
a 'BidiString' holds both the logical content and the visual reordered version of the content of a string. this helps to reduce the number of calls to reorder the string before drawing it (as introduced in the patch from Ken Bloom) and to be more consistent in menus and textboxes (drawing cursors and underlining text).
Diffstat (limited to 'src/FbTk/TextBox.cc')
-rw-r--r--src/FbTk/TextBox.cc63
1 files changed, 37 insertions, 26 deletions
diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc
index 87e18e8..74771a6 100644
--- a/src/FbTk/TextBox.cc
+++ b/src/FbTk/TextBox.cc
@@ -75,7 +75,7 @@ TextBox::~TextBox() {
75 75
76} 76}
77 77
78void TextBox::setText(const std::string &text) { 78void TextBox::setText(const FbTk::BiDiString &text) {
79 m_text = text; 79 m_text = text;
80 m_start_pos = 0; 80 m_start_pos = 0;
81 cursorEnd(); 81 cursorEnd();
@@ -129,7 +129,9 @@ void TextBox::cursorBackward() {
129 129
130void TextBox::backspace() { 130void TextBox::backspace() {
131 if (m_start_pos || cursorPosition()) { 131 if (m_start_pos || cursorPosition()) {
132 m_text.erase(m_start_pos + cursorPosition() - 1, 1); 132 FbString t = text();
133 t.erase(m_start_pos + cursorPosition() - 1, 1);
134 m_text.setLogical(t);
133 if (cursorPosition()) 135 if (cursorPosition())
134 setCursorPosition(cursorPosition() - 1); 136 setCursorPosition(cursorPosition() - 1);
135 else 137 else
@@ -140,23 +142,28 @@ void TextBox::backspace() {
140 142
141void TextBox::deleteForward() { 143void TextBox::deleteForward() {
142 if (m_start_pos + m_cursor_pos < m_end_pos) { 144 if (m_start_pos + m_cursor_pos < m_end_pos) {
143 m_text.erase(m_start_pos + m_cursor_pos, 1); 145 FbString t = text();
146 t.erase(m_start_pos + m_cursor_pos, 1);
147 m_text.setLogical(t);
144 adjustEndPos(); 148 adjustEndPos();
145 } 149 }
146} 150}
147 151
148void TextBox::insertText(const std::string &val) { 152void TextBox::insertText(const std::string &val) {
149 m_text.insert(m_start_pos + cursorPosition(), val); 153 FbString t = text();
154 t.insert(m_start_pos + cursorPosition(), val);
155 m_text.setLogical(t);
150 m_cursor_pos += val.size(); 156 m_cursor_pos += val.size();
151 m_end_pos += val.size(); 157 m_end_pos += val.size();
152 158
153 adjustPos(); 159 adjustPos();
154} 160}
155 161
156void TextBox::killToEnd() { 162void TextBox::killToEnd() {
157 if (cursorPosition() >= 0 && cursorPosition() < static_cast<signed>(text().size())) { 163 if (cursorPosition() >= 0 && cursorPosition() < static_cast<signed>(text().size())) {
158 m_text.erase(cursorPosition()); 164 FbString t = text();
159 setText(m_text); 165 t.erase(cursorPosition());
166 setText(t);
160 } 167 }
161} 168}
162 169
@@ -168,13 +175,13 @@ void TextBox::clear() {
168 setGC(DefaultGC(FbTk::App::instance()->display(), screenNumber())); 175 setGC(DefaultGC(FbTk::App::instance()->display(), screenNumber()));
169 176
170 font().drawText(*this, screenNumber(), 177 font().drawText(*this, screenNumber(),
171 gc(), 178 gc(),
172 text().c_str() + m_start_pos, 179 m_text.visual().c_str() + m_start_pos,
173 m_end_pos - m_start_pos, 180 m_end_pos - m_start_pos,
174 0, center_pos); // pos 181 0, center_pos); // pos
175 182
176 // draw cursor position 183 // draw cursor position
177 int cursor_pos = font().textWidth(text().c_str() + m_start_pos, m_cursor_pos) + 1; 184 int cursor_pos = font().textWidth(m_text.visual().c_str() + m_start_pos, m_cursor_pos) + 1;
178 drawLine(gc(), cursor_pos, center_pos, cursor_pos, center_pos - font().height()); 185 drawLine(gc(), cursor_pos, center_pos, cursor_pos, center_pos - font().height());
179} 186}
180 187
@@ -202,9 +209,7 @@ void TextBox::buttonPressEvent(XButtonEvent &event) {
202 int tmp = 0; 209 int tmp = 0;
203 for(i = m_start_pos; i <= m_end_pos; i++) { 210 for(i = m_start_pos; i <= m_end_pos; i++) {
204 tmp = abs(static_cast<int> 211 tmp = abs(static_cast<int>
205 (event.x - font(). 212 (event.x - font().textWidth(m_text.visual().c_str() + m_start_pos, i - m_start_pos)));
206 textWidth(m_text.c_str() + m_start_pos,
207 i - m_start_pos)));
208 213
209 if (tmp < delta) { 214 if (tmp < delta) {
210 delta = tmp; 215 delta = tmp;
@@ -244,7 +249,7 @@ void TextBox::keyPressEvent(XKeyEvent &event) {
244 } 249 }
245 break; 250 break;
246 case XK_Right: 251 case XK_Right:
247 if (m_text.size() && m_cursor_pos < m_text.size()){ 252 if (!m_text.logical().empty() && m_cursor_pos < m_text.logical().size()){
248 unsigned int pos = findEmptySpaceRight(); 253 unsigned int pos = findEmptySpaceRight();
249 if (pos > m_start_pos) 254 if (pos > m_start_pos)
250 pos -= m_start_pos; 255 pos -= m_start_pos;
@@ -264,7 +269,9 @@ void TextBox::keyPressEvent(XKeyEvent &event) {
264 269
265 case XK_BackSpace: { 270 case XK_BackSpace: {
266 unsigned int pos = findEmptySpaceLeft(); 271 unsigned int pos = findEmptySpaceLeft();
267 m_text.erase(pos, m_cursor_pos - pos + m_start_pos); 272 FbString t = text();
273 t.erase(pos, m_cursor_pos - pos + m_start_pos);
274 m_text.setLogical(t);
268 275
269 if (pos < m_start_pos){ 276 if (pos < m_start_pos){
270 m_start_pos = pos; 277 m_start_pos = pos;
@@ -278,10 +285,12 @@ void TextBox::keyPressEvent(XKeyEvent &event) {
278 } 285 }
279 break; 286 break;
280 case XK_Delete: { 287 case XK_Delete: {
281 if (!m_text.size() || m_cursor_pos >= m_text.size()) 288 if (text().empty() || m_cursor_pos >= text().size())
282 break; 289 break;
283 unsigned int pos = findEmptySpaceRight(); 290 unsigned int pos = findEmptySpaceRight();
284 m_text.erase(m_cursor_pos + m_start_pos, pos - (m_cursor_pos + m_start_pos)); 291 FbString t = text();
292 t.erase(m_cursor_pos + m_start_pos, pos - (m_cursor_pos + m_start_pos));
293 m_text.setLogical(t);
285 adjustPos(); 294 adjustPos();
286 } 295 }
287 break; 296 break;
@@ -368,15 +377,17 @@ void TextBox::adjustEndPos() {
368} 377}
369 378
370void TextBox::adjustStartPos() { 379void TextBox::adjustStartPos() {
371 380
372 int text_width = font().textWidth(text(), m_end_pos); 381 const char* visual = m_text.visual().c_str();
382
383 int text_width = font().textWidth(visual, m_end_pos);
373 if (text_width < static_cast<signed>(width())) 384 if (text_width < static_cast<signed>(width()))
374 return; 385 return;
375 386
376 int start_pos = 0; 387 int start_pos = 0;
377 while (text_width > static_cast<signed>(width())) { 388 while (text_width > static_cast<signed>(width())) {
378 start_pos++; 389 start_pos++;
379 text_width = font().textWidth(text().c_str() + start_pos, m_end_pos - start_pos); 390 text_width = font().textWidth(visual + start_pos, m_end_pos - start_pos);
380 } 391 }
381 392
382 // adjust cursorPosition() according relative to change to m_start_pos 393 // adjust cursorPosition() according relative to change to m_start_pos
@@ -387,12 +398,12 @@ void TextBox::adjustStartPos() {
387unsigned int TextBox::findEmptySpaceLeft(){ 398unsigned int TextBox::findEmptySpaceLeft(){
388 399
389 // found the first left space symbol 400 // found the first left space symbol
390 int pos = m_text.rfind(' ', (m_start_pos + m_cursor_pos) > 0 ? 401 int pos = text().rfind(' ', (m_start_pos + m_cursor_pos) > 0 ?
391 m_start_pos + m_cursor_pos - 1 : 0); 402 m_start_pos + m_cursor_pos - 1 : 0);
392 403
393 // do we have one more space symbol near? 404 // do we have one more space symbol near?
394 int next_pos = -1; 405 int next_pos = -1;
395 while (pos > 0 && (next_pos = m_text.rfind(' ', pos - 1)) > -1){ 406 while (pos > 0 && (next_pos = text().rfind(' ', pos - 1)) > -1){
396 if (next_pos + 1 < pos) 407 if (next_pos + 1 < pos)
397 break; 408 break;
398 pos = next_pos; 409 pos = next_pos;
@@ -406,18 +417,18 @@ unsigned int TextBox::findEmptySpaceLeft(){
406unsigned int TextBox::findEmptySpaceRight(){ 417unsigned int TextBox::findEmptySpaceRight(){
407 418
408 // found the first right space symbol 419 // found the first right space symbol
409 int pos = m_text.find(' ', m_start_pos + m_cursor_pos); 420 int pos = text().find(' ', m_start_pos + m_cursor_pos);
410 421
411 // do we have one more space symbol near? 422 // do we have one more space symbol near?
412 int next_pos = -1; 423 int next_pos = -1;
413 while (pos > -1 && pos < static_cast<signed>(m_text.size()) && (next_pos = m_text.find(' ', pos + 1)) > -1 ){ 424 while (pos > -1 && pos < static_cast<signed>(text().size()) && (next_pos = text().find(' ', pos + 1)) > -1 ){
414 425
415 if (next_pos - 1 > pos) 426 if (next_pos - 1 > pos)
416 break; 427 break;
417 pos = next_pos; 428 pos = next_pos;
418 } 429 }
419 if (pos < 0) 430 if (pos < 0)
420 pos = m_text.size() - 1; 431 pos = text().size() - 1;
421 432
422 return pos + 1; // (+1) - sets cursor at the right. 433 return pos + 1; // (+1) - sets cursor at the right.
423 434