3 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "bcclipboard.h"
22 #include "bclistboxitem.h"
23 #include "bcresources.h"
24 #include "bcsignals.h"
25 #include "bctextbox.h"
30 #include "filesystem.h"
41 #define VERTICAL_MARGIN 2
42 #define VERTICAL_MARGIN_NOBORDER 0
43 #define HORIZONTAL_MARGIN 4
44 #define HORIZONTAL_MARGIN_NOBORDER 2
46 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
47 int size, char *text, int has_border, int font)
48 : BC_SubWindow(x, y, w, 0, -1)
52 reset_parameters(rows, has_border, font, size);
55 else // text referenced directly
59 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
60 int size, wchar_t *wtext, int has_border, int font)
61 : BC_SubWindow(x, y, w, 0, -1)
65 wsize = size > 0 ? size : wcslen(wtext);
66 if( size <= 0 ) size = 2*wsize;
67 reset_parameters(rows, has_border, font, size);
68 this->wtext = new wchar_t[wsize+1];
69 wcsncpy(this->wtext, wtext, wsize);
70 this->wtext[wsize] = 0;
73 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
74 const char *text, int has_border, int font, int is_utf8)
75 : BC_SubWindow(x, y, w, 0, -1)
77 this->is_utf8 = is_utf8;
79 reset_parameters(rows, has_border, font, BCTEXTLEN);
83 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
84 const wchar_t *wtext, int has_border, int font, int is_utf8)
85 : BC_SubWindow(x, y, w, 0, -1)
87 this->is_utf8 = is_utf8;
89 reset_parameters(rows, has_border, font, BCTEXTLEN);
91 wtext = new wchar_t[wsize+1];
92 wcsncpy(this->wtext, wtext, wsize);
93 this->wtext[wsize] = 0;
96 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
97 int64_t text, int has_border, int font)
98 : BC_SubWindow(x, y, w, 0, -1)
102 reset_parameters(rows, has_border, font, BCSTRLEN);
103 snprintf(this->text, this->tsize, "%jd", text);
104 dirty = 1; wtext_update();
107 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
108 float text, int has_border, int font, int precision)
109 : BC_SubWindow(x, y, w, 0, -1)
113 reset_parameters(rows, has_border, font, BCSTRLEN);
114 this->precision = precision;
115 snprintf(this->text, this->tsize, "%0.*f", precision, text);
116 dirty = 1; wtext_update();
119 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
120 int text, int has_border, int font)
121 : BC_SubWindow(x, y, w, 0, -1)
125 reset_parameters(rows, has_border, font, BCSTRLEN);
126 snprintf(this->text, this->tsize, "%d", text);
127 dirty = 1; wtext_update();
130 BC_TextBox::~BC_TextBox()
132 if(skip_cursor) delete skip_cursor;
133 delete suggestions_popup;
134 suggestions->remove_all_objects();
141 int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
143 suggestions = new ArrayList<BC_ListBoxItem*>;
144 suggestions_popup = 0;
145 suggestion_column = 0;
148 this->has_border = has_border;
151 this->tsize = size >= 0 ? size : -size;
152 this->text = size > 0 ? new char[size+1] : 0;
153 if( this->text ) this->text[0] = 0;
156 highlight_letter1 = highlight_letter2 = 0;
157 highlight_letter3 = highlight_letter4 = 0;
169 skip_cursor = new Timer;
181 int BC_TextBox::tstrlen()
183 if( !tsize ) return strlen(text);
184 return strnlen(text, tsize);
187 int BC_TextBox::tstrcmp(const char *cp)
189 if( !tsize ) return strcmp(text, cp);
190 return strncmp(text, cp, tsize);
193 char *BC_TextBox::tstrcpy(const char *cp)
198 return strcpy(text, cp);
199 strncpy(text, cp, tsize);
207 char *BC_TextBox::tstrcat(const char *cp)
210 if( !tsize ) return strcat(text, cp);
211 char *result = strncat(text, cp, tsize);
216 int BC_TextBox::wtext_update()
219 const char *src_enc = is_utf8 ? "UTF8" : BC_Resources::encoding;
220 const char *dst_enc = BC_Resources::wide_encoding;
221 int nsize = tsize > 0 ? tsize : strlen(text) + BCTEXTLEN;
222 if( nsize > wsize || !wtext ) {
223 wchar_t *ntext = new wchar_t[nsize+1];
224 memcpy(ntext, wtext, wsize*sizeof(wtext[0]));
225 delete [] wtext; wtext = ntext; wsize = nsize;
227 wlen = BC_Resources::encode(src_enc, dst_enc, text, strlen(text),
228 (char*)wtext, wsize*sizeof(wchar_t)) / sizeof(wchar_t);
235 int BC_TextBox::text_update(const wchar_t *wcp, int wsz, char *tcp, int tsz)
237 const char *src_enc = BC_Resources::wide_encoding;
238 const char *dst_enc = BC_Resources::encoding;
239 if( wsz < 0 ) wsz = wcslen(wcp);
240 int len = BC_Resources::encode(src_enc, dst_enc,
241 (char*)wcp, wsz*sizeof(wchar_t), tcp, tsz);
246 int BC_TextBox::initialize()
249 skip_cursor = new Timer;
250 skip_cursor->update();
252 text_ascent = get_text_ascent(font) + 1;
253 text_descent = get_text_descent(font) + 1;
254 text_height = text_ascent + text_descent;
255 ibeam_letter = wtext_update();
258 left_margin = right_margin = HORIZONTAL_MARGIN;
259 top_margin = bottom_margin = VERTICAL_MARGIN;
263 left_margin = right_margin = HORIZONTAL_MARGIN_NOBORDER;
264 top_margin = bottom_margin = VERTICAL_MARGIN_NOBORDER;
267 text_x = left_margin;
271 // Create the subwindow
272 BC_SubWindow::initialize();
274 BC_Resources *resources = get_resources();
277 back_color = resources->text_background;
278 high_color = resources->text_background_hi;
282 high_color = resources->text_background_noborder_hi;
283 back_color = bg_color;
287 set_cursor(IBEAM_CURSOR, 0, 0);
292 int BC_TextBox::calculate_h(BC_WindowBase *gui,
297 return rows * (gui->get_text_ascent(font) + 1 +
298 gui->get_text_descent(font) + 1) +
299 2 * (has_border ? VERTICAL_MARGIN : VERTICAL_MARGIN_NOBORDER);
302 void BC_TextBox::set_precision(int precision)
304 this->precision = precision;
307 // Compute suggestions for a path
308 int BC_TextBox::calculate_suggestions(ArrayList<BC_ListBoxItem*> *entries, const char *filter)
310 // Let user delete suggestion
311 if(get_last_keypress() != BACKSPACE) {
312 // Compute suggestions
314 ArrayList<char*> suggestions;
315 const char *current_text = get_text();
316 int suggestion_column = 0;
317 char dirname[BCTEXTLEN]; dirname[0] = 0;
318 if( current_text[0] == '/' || current_text[0] == '~' )
319 strncpy(dirname, current_text, sizeof(dirname));
321 getcwd(dirname, sizeof(dirname));
322 // If directory, tabulate it
324 if( filter ) fs.set_filter(filter);
326 strncpy(dirname, current_text, sizeof(dirname));
327 if( (cp=strrchr(dirname, '/')) ||
328 (cp=strrchr(dirname, '~')) ) *++cp = 0;
329 fs.parse_tildas(dirname);
331 cp = (char *)current_text;
332 if( (prefix=strrchr(cp, '/')) ||
333 (prefix=strrchr(cp, '~')) ) ++prefix;
334 suggestion_column = !prefix ? 0 : prefix - cp;
335 int prefix_len = prefix ? strlen(prefix) : 0;
336 // only include items where the filename matches the basename prefix
337 for(int i = 0; i < fs.total_files(); i++) {
338 char *current_name = fs.get_entry(i)->name;
339 if( prefix_len>0 && strncmp(prefix, current_name, prefix_len) ) continue;
340 suggestions.append(current_name);
344 char *prefix = (char *)current_text;
345 int prefix_len = strlen(prefix);
346 for(int i = 0; i < entries->size(); i++) {
347 char *current_name = entries->get(i)->get_text();
348 if( prefix_len>0 && strncmp(prefix, current_name, prefix_len) ) continue;
349 suggestions.append(current_name);
352 set_suggestions(&suggestions, suggestion_column);
358 void BC_TextBox::no_suggestions()
360 if( suggestions_popup ) {
361 delete suggestions_popup;
362 suggestions_popup = 0;
367 void BC_TextBox::set_suggestions(ArrayList<char*> *suggestions, int column)
370 this->suggestions->remove_all_objects();
371 this->suggestion_column = column;
374 for(int i = 0; i < suggestions->size(); i++) {
375 this->suggestions->append(new BC_ListBoxItem(suggestions->get(i)));
378 // Show the popup without taking focus
379 if( suggestions->size() > 1 ) {
380 if( !suggestions_popup ) {
381 suggestions_popup = new BC_TextBoxSuggestions(this, x, y);
382 get_parent()->add_subwindow(suggestions_popup);
383 suggestions_popup->set_is_suggestions(1);
386 suggestions_popup->update(this->suggestions, 0, 0, 1);
388 suggestions_popup->activate(0);
391 // Show the highlighted text
392 if( suggestions->size() == 1 ) {
393 highlight_letter1 = wtext_update();
394 text_update(wtext,wlen, text,tsize);
395 char *current_suggestion = suggestions->get(0);
396 int col = highlight_letter1 - suggestion_column;
397 if( col < 0 ) col = 0;
398 char *cur = current_suggestion + col;
400 highlight_letter2 = wtext_update();
401 //printf("BC_TextBox::set_suggestions %d %d\n", __LINE__, suggestion_column);
409 if( !suggestions || !this->suggestions->size() )
413 void BC_TextBox::wset_selection(int char1, int char2, int ibeam)
415 highlight_letter1 = char1;
416 highlight_letter2 = char2;
417 ibeam_letter = ibeam;
421 // count utf8 chars in text which occur before cp
422 int BC_TextBox::wcpos(const char *text, const char *cp)
425 const unsigned char *bp = (const unsigned char *)text;
426 const unsigned char *ep = (const unsigned char *)cp;
427 while( bp < ep && *bp != 0 ) {
430 if( ch < 0x80 ) continue;
432 int n = i<0? 0 : i<32? 1 : i<48? 2 : i<56? 3 : i<60? 4 : 5;
433 for( i=n; bp < ep && --i>=0 && (*bp&0xc0) == 0x80; ++bp );
438 void BC_TextBox::set_selection(int char1, int char2, int ibeam)
440 const char *cp = get_text();
441 wset_selection(wcpos(cp, cp+char1), wcpos(cp, cp+char2), wcpos(cp, cp+ibeam));
444 int BC_TextBox::update(const char *text)
446 //printf("BC_TextBox::update 1 %d %s %s\n", tstrcmp(text), text, this->text);
447 // Don't update if contents are the same
448 if(!tstrcmp(text)) return 0;
450 int wtext_len = wtext_update();
451 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
452 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
453 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
458 int BC_TextBox::update(const wchar_t *wtext)
460 int wtext_len = wcslen(wtext);
461 if( wtext_len >= wsize ) wtext_len = wsize;
462 wcsncpy(this->wtext, wtext, wtext_len);
464 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
465 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
466 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
471 int BC_TextBox::update(int64_t value)
473 char string[BCTEXTLEN];
474 sprintf(string, "%jd", value);
479 int BC_TextBox::update(float value)
481 char string[BCTEXTLEN];
482 sprintf(string, "%0.*f", precision, value);
487 void BC_TextBox::disable()
496 void BC_TextBox::enable()
506 int BC_TextBox::get_enabled()
511 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
513 return (pixels - 4) /
514 (window->get_text_ascent(font) + 1 +
515 window->get_text_descent(font) + 1);
518 int BC_TextBox::calculate_row_h(int rows,
519 BC_WindowBase *parent_window,
524 (parent_window->get_text_ascent(font) + 1 +
525 parent_window->get_text_descent(font) + 1) +
526 (has_border ? 4 : 0);
529 const char* BC_TextBox::get_text()
531 int wtext_len = wtext_update();
532 text_update(wtext,wtext_len, text,tsize);
536 const wchar_t* BC_TextBox::get_wtext()
542 void BC_TextBox::set_text(char *text, int isz)
544 if( size > 0 || isz < 0 ) return;
553 int BC_TextBox::get_text_rows()
555 int wtext_len = wtext_update();
557 for(int i = 0; i < wtext_len; i++) {
558 if(wtext[i] == '\n') result++;
564 int BC_TextBox::get_row_h(int rows)
566 return rows * text_height + top_margin + bottom_margin;
569 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
572 if(w < 0) w = get_w();
575 new_h = get_row_h(rows);
584 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
585 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
586 BC_WindowBase::reposition_window(x, y, w, new_h);
592 void BC_TextBox::draw_border()
594 BC_Resources *resources = get_resources();
596 set_color(background_color);
597 draw_box(0, 0, left_margin, get_h());
598 draw_box(get_w() - right_margin, 0, right_margin, get_h());
603 draw_3d_border(0, 0, w, h,
604 resources->text_border1,
605 resources->text_border2_hi,
606 resources->text_border3_hi,
607 resources->text_border4);
609 draw_3d_border(0, 0, w, h,
610 resources->text_border1,
611 resources->text_border2,
612 resources->text_border3,
613 resources->text_border4);
617 void BC_TextBox::draw_cursor()
619 // set_color(background_color);
627 draw_box(ibeam_x + text_x,
636 void BC_TextBox::draw(int flush)
639 int row_begin, row_end;
640 int highlight_x1, highlight_x2;
642 BC_Resources *resources = get_resources();
644 //printf("BC_TextBox::draw %d %s\n", __LINE__, text);
647 background_color = resources->text_background;
649 background_color = high_color;
651 background_color = back_color;
652 set_color(background_color);
653 draw_box(0, 0, w, h);
655 int wtext_len = wtext_update();
657 // Draw text with selection
660 for(i=0, j=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
663 wchar_t *wtext_row = &wtext[i];
664 for(j=0; j<BCTEXTLEN-1 && i<wtext_len && wtext[i]!='\n'; ++i, ++j);
665 if( (row_end=i) < wtext_len ) ++i;
667 if(k > top_margin-text_height && k < get_h()-bottom_margin) {
668 // Draw highlighted region of row
669 if( highlight_letter2 > highlight_letter1 &&
670 highlight_letter2 > row_begin &&
671 highlight_letter1 <= row_end ) {
672 int color = active && enabled && get_has_focus() ?
673 resources->text_highlight :
674 resources->text_inactive_highlight;
675 if( unicode_active >= 0 )
678 if(highlight_letter1 >= row_begin &&
679 highlight_letter1 <= row_end)
680 highlight_x1 = get_x_position(highlight_letter1, row_begin);
684 if(highlight_letter2 > row_begin &&
685 highlight_letter2 <= row_end)
686 highlight_x2 = get_x_position(highlight_letter2, row_begin);
688 highlight_x2 = get_w();
690 draw_box(highlight_x1 + text_x, k,
691 highlight_x2 - highlight_x1, text_height);
694 // Draw text over highlight
695 int len = row_end - row_begin;
697 set_color(enabled ? resources->text_default : DMGREY);
698 draw_wtext(text_x, k + text_ascent, wtext_row, len, 0);
701 // Get ibeam location
702 if(ibeam_letter >= row_begin && ibeam_letter <= row_end) {
704 ibeam_y = k - text_y;
705 ibeam_x = get_x_position(ibeam_letter, row_begin);
710 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
712 // ibeam_x = ibeam_y = !wtext_len ? 0 : -1;
713 ibeam_x = 0; ibeam_y = k - text_y;
716 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
726 int BC_TextBox::focus_in_event()
732 int BC_TextBox::focus_out_event()
738 int BC_TextBox::cursor_enter_event()
740 if( top_level->event_win == win && enabled &&
741 !(top_level->get_resources()->textbox_focus_policy & CLICK_ACTIVATE) )
744 top_level->deactivate();
757 int BC_TextBox::cursor_leave_event()
766 if( !suggestions_popup && !get_button_down() &&
767 !(top_level->get_resources()->textbox_focus_policy & CLICK_DEACTIVATE) )
772 int BC_TextBox::button_press_event()
776 if(!enabled) return 0;
777 if(get_buttonpress() != WHEEL_UP &&
778 get_buttonpress() != WHEEL_DOWN &&
779 get_buttonpress() != LEFT_BUTTON &&
780 get_buttonpress() != MIDDLE_BUTTON) return 0;
784 if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
786 int cursor_letter = 0;
787 int wtext_len = wtext_update();
788 int update_scroll = 0;
791 if(top_level->event_win == win)
796 top_level->deactivate();
801 if(get_buttonpress() == WHEEL_UP)
803 text_y += text_height;
804 text_y = MIN(text_y, top_margin);
808 if(get_buttonpress() == WHEEL_DOWN)
810 int min_y = -(get_text_rows() *
814 text_y -= text_height;
815 text_y = MAX(text_y, min_y);
816 text_y = MIN(text_y, top_margin);
822 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
824 //printf("BC_TextBox::button_press_event %d %d\n", __LINE__, cursor_letter);
827 if(get_triple_click())
829 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
831 select_line(highlight_letter1, highlight_letter2, cursor_letter);
832 highlight_letter3 = highlight_letter1;
833 highlight_letter4 = highlight_letter2;
834 ibeam_letter = highlight_letter2;
835 copy_selection(PRIMARY_SELECTION);
838 if(get_double_click())
841 select_word(highlight_letter1, highlight_letter2, cursor_letter);
842 highlight_letter3 = highlight_letter1;
843 highlight_letter4 = highlight_letter2;
844 ibeam_letter = highlight_letter2;
845 copy_selection(PRIMARY_SELECTION);
848 if(get_buttonpress() == MIDDLE_BUTTON)
850 highlight_letter3 = highlight_letter4 =
851 ibeam_letter = highlight_letter1 =
852 highlight_letter2 = cursor_letter;
853 paste_selection(PRIMARY_SELECTION);
858 highlight_letter3 = highlight_letter4 =
859 ibeam_letter = highlight_letter1 =
860 highlight_letter2 = cursor_letter;
864 // Handle scrolling by highlighting text
865 if(text_selected || word_selected || line_selected)
867 set_repeat(top_level->get_resources()->scroll_repeat);
870 if(ibeam_letter < 0) ibeam_letter = 0;
871 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
875 if(update_scroll && yscroll)
877 yscroll->update_length(get_text_rows(),
879 yscroll->get_handlelength(),
887 if( suggestions_popup && (!yscroll || !yscroll->is_event_win())) {
888 if( suggestions_popup->button_press_event() )
889 return suggestions_popup->handle_event();
891 else if( (top_level->get_resources()->textbox_focus_policy & CLICK_DEACTIVATE) )
898 int BC_TextBox::button_release_event()
903 if(text_selected || word_selected || line_selected)
909 // Stop scrolling by highlighting text
910 unset_repeat(top_level->get_resources()->scroll_repeat);
916 int BC_TextBox::cursor_motion_event()
918 int cursor_letter, letter1, letter2;
921 if(text_selected || word_selected || line_selected)
923 cursor_letter = get_cursor_letter(top_level->cursor_x,
924 top_level->cursor_y);
926 //printf("BC_TextBox::cursor_motion_event %d cursor_letter=%d\n", __LINE__, cursor_letter);
930 select_line(letter1, letter2, cursor_letter);
935 select_word(letter1, letter2, cursor_letter);
940 letter1 = letter2 = cursor_letter;
943 if(letter1 <= highlight_letter3)
945 highlight_letter1 = letter1;
946 highlight_letter2 = highlight_letter4;
947 ibeam_letter = letter1;
950 if(letter2 >= highlight_letter4)
952 highlight_letter2 = letter2;
953 highlight_letter1 = highlight_letter3;
954 ibeam_letter = letter2;
957 copy_selection(PRIMARY_SELECTION);
970 int BC_TextBox::activate()
974 top_level->set_active_subwindow(this);
975 top_level->set_repeat(top_level->get_resources()->blink_rate);
981 int BC_TextBox::deactivate()
985 text_selected = word_selected = line_selected = 0;
986 top_level->set_active_subwindow(0);
987 top_level->unset_repeat(top_level->get_resources()->blink_rate);
993 int BC_TextBox::repeat_event(int64_t duration)
996 int cursor_y = get_cursor_y();
997 //int cursor_x = get_cursor_x();
999 if(duration == top_level->get_resources()->tooltip_delay &&
1000 tooltip_text && tooltip_text[0] != 0 && highlighted)
1006 if(duration == top_level->get_resources()->blink_rate &&
1010 // don't flash if keypress
1011 if(skip_cursor->get_difference() < 500)
1013 // printf("BC_TextBox::repeat_event 1 %lld %lld\n",
1014 // skip_cursor->get_difference(),
1020 if(!(text_selected || word_selected || line_selected))
1029 if(duration == top_level->get_resources()->scroll_repeat &&
1030 (text_selected || word_selected || line_selected))
1033 if(get_cursor_y() < top_margin)
1035 difference = get_cursor_y() - top_margin ;
1038 if(get_cursor_y() > get_h() - bottom_margin)
1040 difference = get_cursor_y() -
1041 (get_h() - bottom_margin);
1043 if(difference != 0) {
1044 int min_y = -(get_text_rows() * text_height -
1045 get_h() + bottom_margin);
1047 text_y -= difference;
1048 // printf("BC_TextBox::repeat_event %d %d %d\n",
1052 text_y = MAX(min_y, text_y);
1053 text_y = MIN(text_y, top_margin);
1060 if(get_cursor_x() < left_margin)
1062 int difference = left_margin - get_cursor_x();
1064 text_x += difference;
1065 text_x = MIN(text_x, left_margin);
1069 else if(get_cursor_x() > get_w() - right_margin)
1071 int difference = get_cursor_x() - (get_w() - right_margin);
1072 int new_text_x = text_x - difference;
1074 // Get width of current row
1077 int wtext_len = wtext_update();
1080 for(int i = 0, k = text_y; i < wtext_len; k += text_height)
1083 while(wtext[i] != '\n' && i < wtext_len) {
1087 if(wtext[i] == '\n') i++;
1089 if(cursor_y >= k && cursor_y < k + text_height) {
1090 row_width = get_text_width(font,
1092 row_end - row_begin);
1098 min_x = -row_width + get_w() - left_margin - BCCURSORW;
1099 new_text_x = MAX(new_text_x, min_x);
1100 new_text_x = MIN(new_text_x, left_margin);
1102 if(new_text_x < text_x) text_x = new_text_x;
1111 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
1113 int key = top_level->get_keypress(), len;
1114 if( (key == RETURN) || ( key >= 32 && key <= 255 ) ) {
1115 wchar_t *wkeys = top_level->get_wkeystring(&len);
1116 if( key == RETURN ) { wkeys[0] = '\n'; wkeys[1] = 0; len = 1; }
1117 insert_text(wkeys, len);
1125 int BC_TextBox::keypress_event()
1127 // Result == 2 contents changed
1128 // Result == 1 trapped keypress
1129 // Result == 0 nothing
1131 int dispatch_event = 0;
1133 if(!active || !enabled) return 0;
1135 int wtext_len = wtext_update();
1136 last_keypress = get_keypress();
1138 if( unicode_active >= 0 ) {
1141 switch( last_keypress ) {
1142 //unicode active acitons
1144 for( int i=highlight_letter1+1; i<highlight_letter2; ++i ) {
1145 int ch = nib(wtext[i]);
1146 if( ch < 0 ) return 1;
1147 wch = (wch<<4) + ch;
1151 unicode_active = -1;
1157 unicode_active = -1;
1162 if(ibeam_letter > 0) {
1163 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1164 highlight_letter2 = --ibeam_letter;
1165 if( highlight_letter1 >= highlight_letter2 )
1166 unicode_active = -1;
1171 case '0': case '1': case '2': case '3': case '4':
1172 case '5': case '6': case '7': case '8': case '9':
1173 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1174 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': {
1175 int n = nib(last_keypress);
1176 wch = n < 10 ? '0'+n : 'A'+n-10;
1190 insert_text(&wch, wlen);
1192 if( unicode_active >= 0 )
1193 highlight_letter2 = ibeam_letter;
1195 highlight_letter1 = highlight_letter2 = 0;
1201 //printf("BC_TextBox::keypress_event %d %x\n", __LINE__, last_keypress)
1202 switch(last_keypress) {
1204 // Deactivate the suggestions
1205 if( suggestions_popup ) {
1210 top_level->deactivate();
1217 highlight_letter1 = highlight_letter2 = 0;
1218 ibeam_letter = wtext_update();
1219 top_level->deactivate();
1224 default_keypress(dispatch_event, result);
1229 // Handle like a default keypress
1231 top_level->cycle_textboxes(1);
1236 top_level->cycle_textboxes(-1);
1241 if(ibeam_letter > 0) {
1242 int old_ibeam_letter = ibeam_letter;
1250 while(ibeam_letter > 0 && isalnum(wtext[ibeam_letter - 1]))
1255 if(top_level->shift_down()) {
1256 // Initialize highlighting
1257 if(highlight_letter1 == highlight_letter2) {
1258 highlight_letter1 = ibeam_letter;
1259 highlight_letter2 = old_ibeam_letter;
1261 else if(highlight_letter1 == old_ibeam_letter) {
1262 // Extend left highlight
1263 highlight_letter1 = ibeam_letter;
1265 else if(highlight_letter2 == old_ibeam_letter) {
1266 // Shrink right highlight
1267 highlight_letter2 = ibeam_letter;
1271 highlight_letter1 = highlight_letter2 = ibeam_letter;
1276 if(keypress_draw) draw(1);
1282 if(ibeam_letter < wtext_len) {
1283 int old_ibeam_letter = ibeam_letter;
1290 while(ibeam_letter < wtext_len && isalnum(wtext[ibeam_letter++]));
1296 if(top_level->shift_down()) {
1297 // Initialize highlighting
1298 if(highlight_letter1 == highlight_letter2) {
1299 highlight_letter1 = old_ibeam_letter;
1300 highlight_letter2 = ibeam_letter;
1302 else if(highlight_letter1 == old_ibeam_letter) {
1303 // Shrink left highlight
1304 highlight_letter1 = ibeam_letter;
1306 else if(highlight_letter2 == old_ibeam_letter) {
1307 // Expand right highlight
1308 highlight_letter2 = ibeam_letter;
1312 highlight_letter1 = highlight_letter2 = ibeam_letter;
1316 if(keypress_draw) draw(1);
1322 if( suggestions && suggestions_popup ) {
1323 // Pass to suggestions popup
1324 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1325 suggestions_popup->activate(1);
1326 suggestions_popup->keypress_event();
1329 else if(ibeam_letter > 0) {
1330 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
1331 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1332 ibeam_y + text_y - text_height);
1333 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
1336 if(top_level->shift_down()) {
1337 // Initialize highlighting
1338 if(highlight_letter1 == highlight_letter2) {
1339 highlight_letter1 = new_letter;
1340 highlight_letter2 = ibeam_letter;
1342 else if(highlight_letter1 == ibeam_letter) {
1343 // Expand left highlight
1344 highlight_letter1 = new_letter;
1346 else if(highlight_letter2 == ibeam_letter) {
1347 // Shrink right highlight
1348 highlight_letter2 = new_letter;
1352 highlight_letter1 = highlight_letter2 = new_letter;
1354 if(highlight_letter1 > highlight_letter2) {
1355 int temp = highlight_letter1;
1356 highlight_letter1 = highlight_letter2;
1357 highlight_letter2 = temp;
1359 ibeam_letter = new_letter;
1362 if(keypress_draw) draw(1);
1368 if(ibeam_letter > 0) {
1369 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1370 ibeam_y + text_y - get_h());
1373 if(top_level->shift_down()) {
1374 // Initialize highlighting
1375 if(highlight_letter1 == highlight_letter2) {
1376 highlight_letter1 = new_letter;
1377 highlight_letter2 = ibeam_letter;
1379 else if(highlight_letter1 == ibeam_letter) {
1380 // Expand left highlight
1381 highlight_letter1 = new_letter;
1383 else if(highlight_letter2 == ibeam_letter) {
1384 // Shrink right highlight
1385 highlight_letter2 = new_letter;
1389 highlight_letter1 = highlight_letter2 = new_letter;
1391 if(highlight_letter1 > highlight_letter2) {
1392 int temp = highlight_letter1;
1393 highlight_letter1 = highlight_letter2;
1394 highlight_letter2 = temp;
1396 ibeam_letter = new_letter;
1399 if(keypress_draw) draw(1);
1405 // printf("BC_TextBox::keypress_event %d %p %p\n",
1408 // suggestions_popup);
1409 if( suggestions && suggestions_popup ) {
1410 // Pass to suggestions popup
1411 suggestions_popup->activate(1);
1412 suggestions_popup->keypress_event();
1416 // if(ibeam_letter > 0)
1419 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1420 ibeam_y + text_y + text_height);
1421 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1423 if(top_level->shift_down()) {
1424 // Initialize highlighting
1425 if(highlight_letter1 == highlight_letter2) {
1426 highlight_letter1 = new_letter;
1427 highlight_letter2 = ibeam_letter;
1429 else if(highlight_letter1 == ibeam_letter) {
1430 // Shrink left highlight
1431 highlight_letter1 = new_letter;
1433 else if(highlight_letter2 == ibeam_letter) {
1434 // Expand right highlight
1435 highlight_letter2 = new_letter;
1439 highlight_letter1 = highlight_letter2 = new_letter;
1441 if(highlight_letter1 > highlight_letter2) {
1442 int temp = highlight_letter1;
1443 highlight_letter1 = highlight_letter2;
1444 highlight_letter2 = temp;
1446 ibeam_letter = new_letter;
1449 if(keypress_draw) draw(1);
1451 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1458 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1459 ibeam_y + text_y + get_h());
1460 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1462 if(top_level->shift_down()) {
1463 // Initialize highlighting
1464 if(highlight_letter1 == highlight_letter2) {
1465 highlight_letter1 = new_letter;
1466 highlight_letter2 = ibeam_letter;
1468 else if(highlight_letter1 == ibeam_letter) {
1469 // Shrink left highlight
1470 highlight_letter1 = new_letter;
1472 else if(highlight_letter2 == ibeam_letter) {
1473 // Expand right highlight
1474 highlight_letter2 = new_letter;
1478 highlight_letter1 = highlight_letter2 = new_letter;
1480 if(highlight_letter1 > highlight_letter2) {
1481 int temp = highlight_letter1;
1482 highlight_letter1 = highlight_letter2;
1483 highlight_letter2 = temp;
1485 ibeam_letter = new_letter;
1488 if(keypress_draw) draw(1);
1490 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1497 int old_ibeam_letter = ibeam_letter;
1499 while(ibeam_letter < wtext_len && wtext[ibeam_letter] != '\n')
1502 if(top_level->shift_down()) {
1504 if(highlight_letter1 == highlight_letter2) {
1505 highlight_letter2 = ibeam_letter;
1506 highlight_letter1 = old_ibeam_letter;
1508 else if(highlight_letter1 == old_ibeam_letter) {
1510 highlight_letter1 = highlight_letter2;
1511 highlight_letter2 = ibeam_letter;
1513 else if(highlight_letter2 == old_ibeam_letter) {
1515 highlight_letter2 = ibeam_letter;
1519 highlight_letter1 = highlight_letter2 = ibeam_letter;
1522 if(keypress_draw) draw(1);
1529 int old_ibeam_letter = ibeam_letter;
1531 while(ibeam_letter > 0 && wtext[ibeam_letter - 1] != '\n')
1534 if(top_level->shift_down())
1537 if(highlight_letter1 == highlight_letter2)
1539 highlight_letter2 = old_ibeam_letter;
1540 highlight_letter1 = ibeam_letter;
1544 if(highlight_letter1 == old_ibeam_letter)
1546 highlight_letter1 = ibeam_letter;
1550 if(highlight_letter2 == old_ibeam_letter)
1552 highlight_letter2 = highlight_letter1;
1553 highlight_letter1 = ibeam_letter;
1557 highlight_letter1 = highlight_letter2 = ibeam_letter;
1560 if(keypress_draw) draw(1);
1567 if(highlight_letter1 == highlight_letter2) {
1568 if(ibeam_letter > 0) {
1569 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1574 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1575 highlight_letter2 = ibeam_letter = highlight_letter1;
1579 if(keypress_draw) draw(1);
1585 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1586 if(highlight_letter1 == highlight_letter2) {
1587 if(ibeam_letter < wtext_len) {
1588 delete_selection(ibeam_letter, ibeam_letter + 1, wtext_len);
1592 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1593 highlight_letter2 = ibeam_letter = highlight_letter1;
1597 if(keypress_draw) draw(1);
1604 switch( get_keypress() ) {
1605 case 'c': case 'C': {
1606 if(highlight_letter1 != highlight_letter2) {
1607 copy_selection(SECONDARY_SELECTION);
1611 case 'v': case 'V': {
1612 paste_selection(SECONDARY_SELECTION);
1614 if(keypress_draw) draw(1);
1618 case 'x': case 'X': {
1619 if(highlight_letter1 != highlight_letter2) {
1620 copy_selection(SECONDARY_SELECTION);
1621 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1622 highlight_letter2 = ibeam_letter = highlight_letter1;
1626 if(keypress_draw) draw(1);
1630 case 'u': case 'U': {
1631 if( shift_down() ) {
1632 unicode_active = ibeam_letter;
1634 insert_text(&wkey, 1);
1636 highlight_letter1 = unicode_active;
1637 highlight_letter2 = ibeam_letter;
1646 default_keypress(dispatch_event, result);
1651 if(result) skip_cursor->update();
1652 if(dispatch_event && handle_event())
1659 int BC_TextBox::uses_text()
1665 void BC_TextBox::delete_selection(int letter1, int letter2, int wtext_len)
1668 for(i=letter1, j=letter2; j<wtext_len; i++, j++) {
1669 wtext[i] = wtext[j];
1677 void BC_TextBox::insert_text(const wchar_t *wcp, int len)
1679 if( len < 0 ) len = wcslen(wcp);
1680 int wtext_len = wtext_update();
1681 if( unicode_active < 0 && highlight_letter1 < highlight_letter2 ) {
1682 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1683 highlight_letter2 = ibeam_letter = highlight_letter1;
1684 wtext_len = wtext_update();
1688 for(i=wtext_len-1, j=wtext_len+len-1; i>=ibeam_letter; i--, j--) {
1689 if( j >= wsize ) continue;
1690 wtext[j] = wtext[i];
1693 for(i = ibeam_letter, j = 0; j < len; j++, i++) {
1694 if( i >= wsize ) break;
1697 if( (wlen+=len) > wsize ) wlen = wsize;
1698 if( (ibeam_letter+=len) > wsize ) ibeam_letter = wsize;
1699 wtext[wlen] = 0; // wtext allocated wsize+1
1703 int BC_TextBox::is_separator(const char *txt, int i)
1705 if( i != 0 || separators[0] != '+' ) return !isalnum(txt[i]);
1706 return txt[0] != '+' && txt[0] != '-' && !isalnum(txt[0]);
1709 // used for time entry
1710 void BC_TextBox::do_separators(int ibeam_left)
1714 // Remove separators from text
1715 int wtext_len = wtext_update();
1716 for(int i = 0; i < wtext_len; ) {
1717 if( !iswalnum(wtext[i]) ) {
1718 for(int j = i; j < wtext_len - 1; j++)
1719 wtext[j] = wtext[j + 1];
1720 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1726 wtext[wtext_len] = 0;
1732 // Insert separators into text
1733 int separator_len = strlen(separators);
1734 for(int i = 0; i < separator_len; i++) {
1736 // Insert a separator
1737 if( is_separator(separators,i) ) {
1738 for(int j = wtext_len; j >= i; j--) {
1739 wtext[j + 1] = wtext[j];
1741 if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1743 wtext[i] = separators[i];
1747 wtext[i] = separators[i];
1752 wtext[separator_len] = 0;
1753 wlen = separator_len;
1757 int BC_TextBox::get_x_position(int i, int start)
1759 return get_text_width(font, &wtext[start], i - start);
1762 void BC_TextBox::get_ibeam_position(int &x, int &y)
1764 int i, row_begin, row_end;
1765 int wtext_len = wtext_update();
1768 for( i=0; i<wtext_len; ) {
1770 for(; i<wtext_len && wtext[i]!='\n'; i++);
1773 if( ibeam_letter >= row_begin && ibeam_letter <= row_end ) {
1774 x = get_x_position(ibeam_letter, row_begin);
1775 //printf("BC_TextBox::get_ibeam_position %d %d %d %d %d\n", ibeam_letter, row_begin, row_end, x, y);
1779 if( i < wtext_len && wtext[i] == '\n' ) {
1784 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1790 void BC_TextBox::set_text_row(int row)
1792 text_x = left_margin;
1793 text_y = -(row * text_height) + top_margin;
1797 int BC_TextBox::get_text_row()
1799 return -(text_y - top_margin) / text_height;
1802 void BC_TextBox::find_ibeam(int dispatch_event)
1805 int old_x = text_x, old_y = text_y;
1807 get_ibeam_position(x, y);
1809 if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1811 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1812 if(text_x > left_margin) text_x = left_margin;
1815 if(left_margin + text_x + x < left_margin)
1817 text_x = -(x - (get_w() / 4)) + left_margin;
1818 if(text_x > left_margin) text_x = left_margin;
1821 int text_row = y / text_height;
1822 if( text_row < rows ) text_y = top_margin;
1824 int pix_rows = get_h() - bottom_margin - (y + text_y);
1825 if( pix_rows < text_height )
1826 text_y -= text_height * ((2*text_height-1-pix_rows) / text_height);
1828 pix_rows = y + text_y - top_margin;
1829 if( pix_rows < 0 ) {
1830 text_y += text_height * ((text_height-1-pix_rows) / text_height);
1831 if( text_y > top_margin ) text_y = top_margin;
1834 if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1838 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1840 int i, j, k, row_begin, row_end, result = 0, done = 0;
1841 int column1, column2;
1842 int got_visible_row = 0;
1844 // Select complete row if cursor above the window
1845 //printf("BC_TextBox::get_cursor_letter %d %d\n", __LINE__, text_y);
1846 if(cursor_y < text_y - text_height)
1852 int wtext_len = wtext_update();
1854 for(i=0, k=text_y; i<wtext_len && k<get_h() && !done; k+=text_height) {
1855 // Simulate drawing of 1 row
1857 for(j = 0; wtext[i]!='\n' && i<wtext_len; i++);
1861 int first_visible_row = 0;
1862 int last_visible_row = 0;
1863 if( k+text_height > top_margin && !got_visible_row) {
1864 first_visible_row = 1;
1865 got_visible_row = 1;
1868 if( (k+text_height >= get_h() - bottom_margin ||
1869 (row_end >= wtext_len && k < get_h() - bottom_margin &&
1870 k + text_height > 0)) )
1871 last_visible_row = 1;
1873 // Cursor is inside vertical range of row
1874 if((cursor_y >= top_margin &&
1875 cursor_y < get_h() - bottom_margin &&
1876 cursor_y >= k && cursor_y < k + text_height) ||
1877 // Cursor is above 1st row
1878 (cursor_y < k + text_height && first_visible_row) ||
1879 // Cursor is below last row
1880 (cursor_y >= k && last_visible_row))
1882 column1 = column2 = 0;
1883 for(j = row_begin; j<wsize && j<=row_end && !done; j++) {
1884 column2 = get_text_width(font, &wtext[row_begin], j-row_begin) + text_x;
1885 if((column2 + column1) / 2 >= cursor_x) {
1888 // printf("BC_TextBox::get_cursor_letter %d %d %d %d\n",
1889 // __LINE__, result, first_visible_row, last_visible_row);
1900 if(wtext[i] == '\n') i++;
1902 // Select complete row if last visible & cursor is below window
1903 if(last_visible_row && cursor_y > k + text_height * 2)
1906 if(i >= wtext_len && !done) {
1912 // printf("BC_TextBox::get_cursor_letter %d cursor_y=%d k=%d h=%d %d %d\n",
1913 // __LINE__, cursor_y, k, get_h(), first_visible_row, last_visible_row);
1914 if(result < 0) result = 0;
1915 if(result > wtext_len) {
1916 //printf("BC_TextBox::get_cursor_letter %d\n", __LINE__);
1924 int BC_TextBox::get_cursor_letter2(int cursor_x, int cursor_y)
1926 int i, j, k, row_begin, row_end, result = 0, done = 0;
1927 int column1, column2;
1928 int wtext_len = wtext_update();
1930 if(cursor_y < text_y) {
1935 for(i = 0, k = text_y; i < wtext_len && !done; k += text_height) {
1937 for(; wtext[i] != '\n' && i < wtext_len; i++);
1940 if(cursor_y >= k && cursor_y < k + text_height) {
1941 column1 = column2 = 0;
1942 for(j = 0; j <= row_end - row_begin && !done; j++) {
1943 column2 = get_text_width(font, &wtext[row_begin], j) + text_x;
1944 if((column2 + column1) / 2 >= cursor_x) {
1945 result = row_begin + j - 1;
1956 if(wtext[i] == '\n') i++;
1958 if(i >= wtext_len && !done) {
1962 if(result < 0) result = 0;
1963 if(result > wtext_len) result = wtext_len;
1968 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
1970 int wtext_len = wtext_update();
1971 letter1 = letter2 = ibeam_letter;
1972 if( letter1 < 0 ) letter1 = 0;
1973 if( letter2 < 0 ) letter2 = 0;
1974 if( letter1 > wtext_len ) letter1 = wtext_len;
1975 if( letter2 > wtext_len ) letter2 = wtext_len;
1976 if( !wtext_len ) return;
1977 for( int i=letter1; i>=0 && iswalnum(wtext[i]); --i ) letter1 = i;
1978 for( int i=letter2; i<wtext_len && iswalnum(wtext[i]); ) letter2 = ++i;
1979 if( letter2 < wtext_len && wtext[letter2] == ' ' ) ++letter2;
1983 void BC_TextBox::select_line(int &letter1, int &letter2, int ibeam_letter)
1985 int wtext_len = wtext_update();
1986 letter1 = letter2 = ibeam_letter;
1987 if( letter1 < 0 ) letter1 = 0;
1988 if( letter2 < 0 ) letter2 = 0;
1989 if( letter1 > wtext_len ) letter1 = wtext_len;
1990 if( letter2 > wtext_len ) letter2 = wtext_len;
1991 if( !wtext_len ) return;
1992 for( int i=letter1; i>=0 && wtext[i]!='\n'; --i ) letter1 = i;
1993 for( int i=letter2; i<wtext_len && wtext[i]!='\n'; ) letter2 = ++i;
1996 void BC_TextBox::copy_selection(int clipboard_num)
1998 int wtext_len = wtext_update();
1999 if(!wtext_len) return;
2001 if(highlight_letter1 >= wtext_len || highlight_letter2 > wtext_len ||
2002 highlight_letter1 < 0 || highlight_letter2 < 0 ||
2003 highlight_letter2 - highlight_letter1 <= 0) return;
2004 int clip_len = highlight_letter2 - highlight_letter1;
2005 //printf(" BC_TextBox::copy_selection %d %d %d\n",highlight_letter1, highlight_letter2, clip_len);
2006 char ctext[4*clip_len+4];
2007 clip_len = text_update(&wtext[highlight_letter1],clip_len, ctext,4*clip_len+4);
2008 get_clipboard()->to_clipboard(ctext, clip_len, clipboard_num);
2012 void BC_TextBox::paste_selection(int clipboard_num)
2014 int len = get_clipboard()->clipboard_len(clipboard_num);
2017 char cstring[len]; wchar_t wstring[len];
2018 get_clipboard()->from_clipboard(cstring, len, clipboard_num); --len;
2019 //printf("BC_TextBox::paste_selection %d '%*.*s'\n",len,len,len,cstring);
2020 len = BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
2021 cstring,len, (char *)wstring,(len+1)*sizeof(wchar_t)) / sizeof(wchar_t);
2022 insert_text(wstring, len);
2026 void BC_TextBox::set_keypress_draw(int value)
2028 keypress_draw = value;
2031 int BC_TextBox::get_last_keypress()
2033 return last_keypress;
2036 int BC_TextBox::get_ibeam_letter()
2038 return ibeam_letter;
2041 void BC_TextBox::set_ibeam_letter(int number, int redraw)
2043 this->ibeam_letter = number;
2050 void BC_TextBox::set_separators(const char *separators)
2052 this->separators = (char*)separators;
2055 int BC_TextBox::get_rows()
2066 BC_TextBoxSuggestions::BC_TextBoxSuggestions(BC_TextBox *text_box, int x, int y)
2067 : BC_ListBox(x, y, text_box->get_w(), 200, LISTBOX_TEXT,
2068 text_box->suggestions, 0, 0, 1, 0, 1)
2070 this->text_box = text_box;
2072 set_justify(LISTBOX_LEFT);
2075 BC_TextBoxSuggestions::~BC_TextBoxSuggestions()
2079 int BC_TextBoxSuggestions::handle_event()
2081 char *current_suggestion = 0;
2082 BC_ListBoxItem *item = get_selection(0, 0);
2083 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2084 if(item && (current_suggestion=item->get_text()) != 0)
2086 int col = text_box->suggestion_column;
2087 int len = BCTEXTLEN-1 - col;
2088 char *cp = &text_box->text[col];
2089 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2090 strncpy(cp, current_suggestion, len);
2091 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2092 if( (col=strlen(current_suggestion)) >= len )
2094 text_box->dirty = 1;
2098 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2099 text_box->highlight_letter1 =
2100 text_box->highlight_letter2 =
2101 text_box->ibeam_letter = text_box->tstrlen();
2102 text_box->wtext_update();
2104 text_box->handle_event();
2105 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2110 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2111 int x, int y, int w, int rows,
2112 const char *default_text, int default_size)
2114 this->parent_window = parent_window;
2119 this->default_text = default_text;
2120 this->default_wtext = 0;
2121 this->default_size = default_size;
2124 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2125 int x, int y, int w, int rows,
2126 const wchar_t *default_wtext, int default_size)
2128 this->parent_window = parent_window;
2133 this->default_text = 0;
2134 this->default_wtext = default_wtext;
2135 this->default_size = default_size;
2138 BC_ScrollTextBox::~BC_ScrollTextBox()
2147 void BC_ScrollTextBox::create_objects()
2149 // Must be created first
2150 parent_window->add_subwindow(text = default_wtext ?
2151 new BC_ScrollTextBoxText(this, default_wtext) :
2152 new BC_ScrollTextBoxText(this, default_text));
2153 parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
2154 text->yscroll = yscroll;
2155 yscroll->bound_to = text;
2159 void BC_ScrollTextBox::set_text(char *text, int isz)
2161 this->text->set_text(text, isz);
2162 yscroll->update_length(this->text->get_text_rows(),
2163 this->text->get_text_row(),
2164 yscroll->get_handlelength(),
2168 int BC_ScrollTextBox::set_text_row(int n)
2170 text->set_text_row(n);
2171 yscroll->update_value(n);
2175 void BC_ScrollTextBox::update(const char *text)
2177 this->text->update(text);
2178 yscroll->update_length(this->text->get_text_rows(),
2179 this->text->get_text_row(),
2180 yscroll->get_handlelength(),
2184 void BC_ScrollTextBox::update(const wchar_t *wtext)
2186 this->text->update(wtext);
2187 yscroll->update_length(this->text->get_text_rows(),
2188 this->text->get_text_row(),
2189 yscroll->get_handlelength(),
2193 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
2200 text->reposition_window(x,
2202 w - yscroll->get_span(),
2204 yscroll->reposition_window(x + w - yscroll->get_span(),
2206 BC_TextBox::calculate_row_h(rows,
2208 yscroll->update_length(text->get_text_rows(),
2209 text->get_text_row(),
2214 int BC_ScrollTextBox::button_press_event()
2216 return text->BC_TextBox::button_press_event();
2218 int BC_ScrollTextBox::button_release_event()
2220 return text->BC_TextBox::button_release_event();
2223 int BC_ScrollTextBox::get_h() { return text->get_h(); }
2224 const char *BC_ScrollTextBox::get_text() { return text->get_text(); }
2225 const wchar_t *BC_ScrollTextBox::get_wtext() { return text->get_wtext(); }
2227 int BC_ScrollTextBox::get_buttonpress()
2229 return text->BC_TextBox::get_buttonpress();
2231 void BC_ScrollTextBox::wset_selection(int char1, int char2, int ibeam)
2233 text->wset_selection(char1, char2, ibeam);
2235 void BC_ScrollTextBox::set_selection(int char1, int char2, int ibeam)
2237 text->set_selection(char1, char2, ibeam);
2239 int BC_ScrollTextBox::get_ibeam_letter()
2241 return text->get_ibeam_letter();
2244 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const char *text)
2245 : BC_TextBox(gui->x, gui->y,
2246 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2247 gui->rows, gui->default_size, (char*)text, 1, MEDIUMFONT)
2252 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const wchar_t *wtext)
2253 : BC_TextBox(gui->x, gui->y,
2254 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2255 gui->rows, gui->default_size, (wchar_t*)wtext, 1, MEDIUMFONT)
2260 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
2269 int BC_ScrollTextBoxText::handle_event()
2271 gui->yscroll->update_length(get_text_rows(),
2273 gui->yscroll->get_handlelength(),
2275 return gui->handle_event();
2278 int BC_ScrollTextBoxText::motion_event()
2280 gui->yscroll->update_length(get_text_rows(),
2282 gui->yscroll->get_handlelength(),
2287 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
2288 : BC_ScrollBar(gui->x +
2290 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2293 BC_TextBox::calculate_row_h(gui->rows,
2294 gui->parent_window),
2295 gui->text->get_text_rows(),
2302 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
2306 int BC_ScrollTextBoxYScroll::handle_event()
2308 gui->text->set_text_row(get_position());
2314 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const char *text)
2315 : BC_TextBox(x, y, popup->text_w, 1, text, BCTEXTLEN)
2317 this->popup = popup;
2320 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const wchar_t *wtext)
2321 : BC_TextBox(x, y, popup->text_w, 1, wtext, BCTEXTLEN)
2323 this->popup = popup;
2326 BC_PopupTextBoxText::~BC_PopupTextBoxText()
2336 int BC_PopupTextBoxText::handle_event()
2338 popup->handle_event();
2342 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
2344 popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
2345 popup->list_h, popup->list_format, popup->list_items, 0, 0, 1, 0, 1)
2347 this->popup = popup;
2349 int BC_PopupTextBoxList::handle_event()
2351 BC_ListBoxItem *item = get_selection(0, 0);
2354 popup->textbox->update(item->get_text());
2355 popup->textbox->set_text_row(0);
2356 popup->handle_event();
2364 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window,
2365 ArrayList<BC_ListBoxItem*> *list_items,
2366 const char *default_text, int x, int y,
2367 int text_w, int list_h, int list_format)
2371 this->list_h = list_h;
2372 this->list_format = list_format;
2373 this->default_text = (char*)default_text;
2374 this->default_wtext = 0;
2375 this->text_w = text_w;
2376 this->parent_window = parent_window;
2377 this->list_items = list_items;
2380 BC_PopupTextBox::~BC_PopupTextBox()
2390 int BC_PopupTextBox::create_objects()
2392 int x = this->x, y = this->y;
2393 parent_window->add_subwindow(textbox = default_wtext ?
2394 new BC_PopupTextBoxText(this, x, y, default_wtext) :
2395 new BC_PopupTextBoxText(this, x, y, default_text));
2396 x += textbox->get_w();
2397 parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
2401 void BC_PopupTextBox::update(const char *text)
2403 textbox->update(text);
2404 textbox->set_text_row(0);
2407 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
2409 listbox->update(data, 0, 0, 1);
2413 const char* BC_PopupTextBox::get_text()
2415 return textbox->get_text();
2418 const wchar_t* BC_PopupTextBox::get_wtext()
2420 return textbox->get_wtext();
2423 int BC_PopupTextBox::get_number()
2425 return listbox->get_selection_number(0, 0);
2428 int BC_PopupTextBox::get_x()
2433 int BC_PopupTextBox::get_y()
2438 int BC_PopupTextBox::get_w()
2440 return textbox->get_w() + listbox->get_w();
2443 int BC_PopupTextBox::get_h()
2445 return textbox->get_h();
2448 int BC_PopupTextBox::get_show_query()
2450 return listbox->get_show_query();
2453 void BC_PopupTextBox::set_show_query(int v)
2455 listbox->set_show_query(v);
2458 int BC_PopupTextBox::handle_event()
2463 void BC_PopupTextBox::reposition_window(int x, int y)
2468 textbox->reposition_window(x1,
2471 textbox->get_rows());
2472 x1 += textbox->get_w();
2473 listbox->reposition_window(x1, y1, -1, -1, 0);
2474 // if(flush) parent_window->flush();
2490 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2491 int64_t default_value, int x, int y)
2492 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2494 this->popup = popup;
2497 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2498 float default_value, int x, int y)
2499 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2501 this->popup = popup;
2504 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
2516 int BC_TumbleTextBoxText::handle_event()
2518 popup->handle_event();
2522 int BC_TumbleTextBoxText::button_press_event()
2526 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
2528 if(get_buttonpress() == 4)
2530 popup->tumbler->handle_up_event();
2533 if(get_buttonpress() == 5)
2535 popup->tumbler->handle_down_event();
2545 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2546 int64_t default_value,
2558 this->default_value = default_value;
2559 this->text_w = text_w;
2560 this->parent_window = parent_window;
2566 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2579 this->default_value = default_value;
2580 this->text_w = text_w;
2581 this->parent_window = parent_window;
2587 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2588 float default_value_f,
2598 this->min_f = min_f;
2599 this->max_f = max_f;
2600 this->default_value_f = default_value_f;
2601 this->text_w = text_w;
2602 this->parent_window = parent_window;
2608 BC_TumbleTextBox::~BC_TumbleTextBox()
2610 // Recursive delete. Normally ~BC_TumbleTextBox is never called but textbox
2611 // is deleted anyway by the windowbase so textbox deletes this.
2612 if(tumbler) delete tumbler;
2614 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
2623 void BC_TumbleTextBox::reset()
2630 void BC_TumbleTextBox::set_precision(int precision)
2632 this->precision = precision;
2635 void BC_TumbleTextBox::set_increment(float value)
2637 this->increment = value;
2638 if(tumbler) tumbler->set_increment(value);
2641 void BC_TumbleTextBox::set_log_floatincrement(int value)
2643 this->log_floatincrement = value;
2644 if(tumbler) tumbler->set_log_floatincrement(value);
2647 int BC_TumbleTextBox::create_objects()
2649 int x = this->x, y = this->y;
2653 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2654 default_value_f, x, y));
2655 textbox->set_precision(precision);
2658 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2659 default_value, x, y));
2661 x += textbox->get_w();
2664 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox,
2670 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox,
2676 tumbler->set_increment(increment);
2680 const char* BC_TumbleTextBox::get_text()
2682 return textbox->get_text();
2685 const wchar_t* BC_TumbleTextBox::get_wtext()
2687 return textbox->get_wtext();
2690 BC_TextBox* BC_TumbleTextBox::get_textbox()
2695 int BC_TumbleTextBox::update(const char *value)
2697 textbox->update(value);
2698 textbox->set_text_row(0);
2702 int BC_TumbleTextBox::update(int64_t value)
2704 textbox->update(value);
2705 textbox->set_text_row(0);
2709 int BC_TumbleTextBox::update(float value)
2711 textbox->update(value);
2712 textbox->set_text_row(0);
2717 int BC_TumbleTextBox::get_x()
2722 int BC_TumbleTextBox::get_y()
2727 int BC_TumbleTextBox::get_w()
2729 return textbox->get_w() + tumbler->get_w();
2732 int BC_TumbleTextBox::get_h()
2734 return textbox->get_h();
2737 void BC_TumbleTextBox::disable(int hide_text)
2739 if( hide_text && !textbox->is_hidden() )
2740 textbox->hide_window(0);
2741 if( !tumbler->is_hidden() )
2742 tumbler->hide_window(0);
2743 if( !get_enabled() ) return;
2744 return textbox->disable();
2747 void BC_TumbleTextBox::enable()
2749 if( textbox->is_hidden() )
2750 textbox->show_window(0);
2751 if( tumbler->is_hidden() )
2752 tumbler->show_window(0);
2753 if( get_enabled() ) return;
2754 return textbox->enable();
2757 int BC_TumbleTextBox::get_enabled()
2759 return textbox->get_enabled();
2762 int BC_TumbleTextBox::handle_event()
2767 void BC_TumbleTextBox::reposition_window(int x, int y)
2772 textbox->reposition_window(x,
2776 tumbler->reposition_window(x + textbox->get_w(),
2778 // if(flush) parent_window->flush();
2782 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2784 tumbler->set_boundaries(min, max);
2787 void BC_TumbleTextBox::set_boundaries(float min, float max)
2789 tumbler->set_boundaries(min, max);
2792 void BC_TumbleTextBox::set_tooltip(const char *text)
2794 textbox->set_tooltip(text);