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"
42 #define VERTICAL_MARGIN 2
43 #define VERTICAL_MARGIN_NOBORDER 0
44 #define HORIZONTAL_MARGIN 4
45 #define HORIZONTAL_MARGIN_NOBORDER 2
47 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
48 int size, char *text, int has_border, int font)
49 : BC_SubWindow(x, y, w, 0, -1)
53 reset_parameters(rows, has_border, font, size);
56 else // text referenced directly
60 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
61 int size, wchar_t *wtext, int has_border, int font)
62 : BC_SubWindow(x, y, w, 0, -1)
66 wsize = size > 0 ? size : wcslen(wtext);
67 if( size <= 0 ) size = 2*wsize;
68 reset_parameters(rows, has_border, font, size);
69 this->wtext = new wchar_t[wsize+1];
70 wcsncpy(this->wtext, wtext, wsize);
71 this->wtext[wsize] = 0;
74 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
75 const char *text, int has_border, int font, int is_utf8)
76 : BC_SubWindow(x, y, w, 0, -1)
78 this->is_utf8 = is_utf8;
80 reset_parameters(rows, has_border, font, BCTEXTLEN);
84 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
85 const wchar_t *wtext, int has_border, int font, int is_utf8)
86 : BC_SubWindow(x, y, w, 0, -1)
88 this->is_utf8 = is_utf8;
90 reset_parameters(rows, has_border, font, BCTEXTLEN);
92 wtext = new wchar_t[wsize+1];
93 wcsncpy(this->wtext, wtext, wsize);
94 this->wtext[wsize] = 0;
97 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
98 int64_t text, int has_border, int font)
99 : BC_SubWindow(x, y, w, 0, -1)
103 reset_parameters(rows, has_border, font, BCSTRLEN);
104 snprintf(this->text, this->tsize, _LD, text);
105 dirty = 1; wtext_update();
108 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
109 float text, int has_border, int font, int precision)
110 : BC_SubWindow(x, y, w, 0, -1)
114 reset_parameters(rows, has_border, font, BCSTRLEN);
115 this->precision = precision;
116 snprintf(this->text, this->tsize, "%0.*f", precision, text);
117 dirty = 1; wtext_update();
120 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
121 int text, int has_border, int font)
122 : BC_SubWindow(x, y, w, 0, -1)
126 reset_parameters(rows, has_border, font, BCSTRLEN);
127 snprintf(this->text, this->tsize, "%d", text);
128 dirty = 1; wtext_update();
131 BC_TextBox::~BC_TextBox()
133 if(skip_cursor) delete skip_cursor;
134 delete suggestions_popup;
135 suggestions->remove_all_objects();
143 int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
145 suggestions = new ArrayList<BC_ListBoxItem*>;
146 suggestions_popup = 0;
147 suggestion_column = 0;
150 this->has_border = has_border;
153 this->tsize = size >= 0 ? size : -size;
154 this->text = size > 0 ? new char[size+1] : 0;
155 if( this->text ) this->text[0] = 0;
158 highlight_letter1 = highlight_letter2 = 0;
159 highlight_letter3 = highlight_letter4 = 0;
170 skip_cursor = new Timer;
184 int BC_TextBox::tstrlen()
186 if( !tsize ) return strlen(text);
187 return strnlen(text, tsize);
190 int BC_TextBox::tstrcmp(const char *cp)
192 if( !tsize ) return strcmp(text, cp);
193 return strncmp(text, cp, tsize);
196 char *BC_TextBox::tstrcpy(const char *cp)
201 return strcpy(text, cp);
202 strncpy(text, cp, tsize);
210 char *BC_TextBox::tstrcat(const char *cp)
213 if( !tsize ) return strcat(text, cp);
214 char *result = strncat(text, cp, tsize);
219 int BC_TextBox::wtext_update()
222 const char *src_enc = is_utf8 ? "UTF8" : BC_Resources::encoding;
223 const char *dst_enc = BC_Resources::wide_encoding;
224 int nsize = tsize > 0 ? tsize : strlen(text) + BCTEXTLEN;
225 if( nsize > wsize || !wtext ) {
226 wchar_t *ntext = new wchar_t[nsize+1];
227 memcpy(ntext, wtext, wsize*sizeof(wtext[0]));
228 delete [] wtext; wtext = ntext; wsize = nsize;
229 int *npositions = new int[nsize+1];
231 memcpy(npositions, positions, (plen+1)*sizeof(positions[0]));
234 delete [] positions; positions = npositions; plen = nsize;
236 wlen = BC_Resources::encode(src_enc, dst_enc, text, strlen(text),
237 (char*)wtext, wsize*sizeof(wchar_t)) / sizeof(wchar_t);
244 int BC_TextBox::text_update(const wchar_t *wcp, int wsz, char *tcp, int tsz)
246 const char *src_enc = BC_Resources::wide_encoding;
247 const char *dst_enc = BC_Resources::encoding;
248 if( wsz < 0 ) wsz = wcslen(wcp);
249 int len = BC_Resources::encode(src_enc, dst_enc,
250 (char*)wcp, wsz*sizeof(wchar_t), tcp, tsz);
255 int BC_TextBox::initialize()
258 skip_cursor = new Timer;
259 skip_cursor->update();
261 text_ascent = get_text_ascent(font) + 1;
262 text_descent = get_text_descent(font) + 1;
263 text_height = text_ascent + text_descent;
264 ibeam_letter = wtext_update();
267 left_margin = right_margin = HORIZONTAL_MARGIN;
268 top_margin = bottom_margin = VERTICAL_MARGIN;
272 left_margin = right_margin = HORIZONTAL_MARGIN_NOBORDER;
273 top_margin = bottom_margin = VERTICAL_MARGIN_NOBORDER;
276 text_x = left_margin;
280 // Create the subwindow
281 BC_SubWindow::initialize();
283 BC_Resources *resources = get_resources();
286 back_color = resources->text_background;
287 high_color = resources->text_background_hi;
291 high_color = resources->text_background_noborder_hi;
292 back_color = bg_color;
296 set_cursor(IBEAM_CURSOR, 0, 0);
301 int BC_TextBox::calculate_h(BC_WindowBase *gui,
306 return rows * (gui->get_text_ascent(font) + 1 +
307 gui->get_text_descent(font) + 1) +
308 2 * (has_border ? VERTICAL_MARGIN : VERTICAL_MARGIN_NOBORDER);
311 void BC_TextBox::set_precision(int precision)
313 this->precision = precision;
316 // Compute suggestions for a path
317 int BC_TextBox::calculate_suggestions(ArrayList<BC_ListBoxItem*> *entries)
319 // Let user delete suggestion
320 if(get_last_keypress() != BACKSPACE)
323 // Compute suggestions
325 ArrayList<char*> suggestions;
326 const char *current_text = get_text();
328 // If directory, tabulate it
329 if(current_text[0] == '/' ||
330 current_text[0] == '~')
332 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
333 char string[BCTEXTLEN];
334 strncpy(string, current_text, sizeof(string));
335 char *ptr = strrchr(string, '/');
336 if(!ptr) ptr = strrchr(string, '~');
338 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
340 int suggestion_column = ptr + 1 - string;
342 fs.set_filter(get_resources()->filebox_filter);
343 // fs.set_sort_order(filebox->sort_order);
344 // fs.set_sort_field(filebox->column_type[filebox->sort_column]);
347 //printf("BC_TextBox::calculate_suggestions %d %c %s\n", __LINE__, *ptr, string);
348 if(current_text[0] == '~' && *ptr != '/')
354 fs.parse_tildas(string);
357 //printf("BC_TextBox::calculate_suggestions %d %d\n", __LINE__, fs.total_files());
360 // Accept only entries with matching trailing characters
361 ptr = strrchr((char*)current_text, '/');
362 if(!ptr) ptr = strrchr((char*)current_text, '~');
364 //printf("BC_TextBox::calculate_suggestions %d %s %p\n", __LINE__, current_text, ptr);
369 for(int i = 0; i < fs.total_files(); i++)
371 char *current_name = fs.get_entry(i)->name;
372 if(!strncmp(ptr, current_name, strlen(ptr)))
374 suggestions.append(current_name);
375 //printf("BC_TextBox::calculate_suggestions %d %s\n", __LINE__, current_name);
380 // Accept all entries
381 for(int i = 0; i < fs.total_files(); i++)
383 //printf("BC_TextBox::calculate_suggestions %d %s\n", __LINE__, fs.get_entry(i)->name);
384 suggestions.append(fs.get_entry(i)->name);
386 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
388 // Add 1 to column to keep /
389 set_suggestions(&suggestions, suggestion_column);
390 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
393 // Get entries from current listbox with matching trailing characters
396 // printf("BC_TextBox::calculate_suggestions %d %d\n",
399 for(int i = 0; i < entries->size(); i++)
401 char *current_name = entries->get(i)->get_text();
403 //printf("BC_TextBox::calculate_suggestions %d %s %s\n", __LINE__, current_text, current_name);
404 if(!strncmp(current_text, current_name, strlen(current_text)))
406 suggestions.append(current_name);
410 set_suggestions(&suggestions, 0);
417 void BC_TextBox::set_suggestions(ArrayList<char*> *suggestions, int column)
420 this->suggestions->remove_all_objects();
421 this->suggestion_column = column;
425 for(int i = 0; i < suggestions->size(); i++)
427 this->suggestions->append(new BC_ListBoxItem(suggestions->get(i)));
430 // Show the popup without taking focus
431 if(suggestions->size() > 1)
433 if(!suggestions_popup)
436 get_parent()->add_subwindow(suggestions_popup =
437 new BC_TextBoxSuggestions(this, x, y));
438 suggestions_popup->set_is_suggestions(1);
439 suggestions_popup->activate(0);
443 suggestions_popup->update(this->suggestions,
447 suggestions_popup->activate(0);
451 // Show the highlighted text
452 if(suggestions->size() == 1)
454 highlight_letter1 = wtext_update();
455 text_update(wtext,wlen, text,tsize);
456 char *current_suggestion = suggestions->get(0);
457 int col = highlight_letter1 - suggestion_column;
458 if( col < 0 ) col = 0;
459 char *cur = current_suggestion + col;
461 highlight_letter2 = wtext_update();
462 //printf("BC_TextBox::set_suggestions %d %d\n", __LINE__, suggestion_column);
466 delete suggestions_popup;
467 suggestions_popup = 0;
472 if(!suggestions || !this->suggestions->size())
474 delete suggestions_popup;
475 suggestions_popup = 0;
479 void BC_TextBox::set_selection(int char1, int char2, int ibeam)
481 highlight_letter1 = char1;
482 highlight_letter2 = char2;
483 ibeam_letter = ibeam;
487 int BC_TextBox::update(const char *text)
489 //printf("BC_TextBox::update 1 %d %s %s\n", tstrcmp(text), text, this->text);
490 // Don't update if contents are the same
491 if(!tstrcmp(text)) return 0;
493 int wtext_len = wtext_update();
494 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
495 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
496 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
501 int BC_TextBox::update(const wchar_t *wtext)
503 int wtext_len = wcslen(wtext);
504 if( wtext_len >= wsize ) wtext_len = wsize;
505 wcsncpy(this->wtext, wtext, wtext_len);
507 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
508 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
509 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
514 int BC_TextBox::update(int64_t value)
516 char string[BCTEXTLEN];
517 sprintf(string, _LD, value);
522 int BC_TextBox::update(float value)
524 char string[BCTEXTLEN];
525 sprintf(string, "%0.*f", precision, value);
530 void BC_TextBox::disable()
535 if(active) top_level->deactivate();
541 void BC_TextBox::enable()
551 int BC_TextBox::get_enabled()
556 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
558 return (pixels - 4) /
559 (window->get_text_ascent(font) + 1 +
560 window->get_text_descent(font) + 1);
563 int BC_TextBox::calculate_row_h(int rows,
564 BC_WindowBase *parent_window,
569 (parent_window->get_text_ascent(font) + 1 +
570 parent_window->get_text_descent(font) + 1) +
571 (has_border ? 4 : 0);
574 const char* BC_TextBox::get_text()
576 int wtext_len = wtext_update();
577 text_update(wtext,wtext_len, text,tsize);
581 const wchar_t* BC_TextBox::get_wtext()
587 void BC_TextBox::set_text(char *text, int isz)
589 if( size > 0 || isz < 0 ) return;
598 int BC_TextBox::get_text_rows()
600 int wtext_len = wtext_update();
602 for(int i = 0; i < wtext_len; i++) {
603 if(wtext[i] == '\n') result++;
609 int BC_TextBox::get_row_h(int rows)
611 return rows * text_height + top_margin + bottom_margin;
614 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
617 if(w < 0) w = get_w();
620 new_h = get_row_h(rows);
629 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
630 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
631 BC_WindowBase::reposition_window(x, y, w, new_h);
637 void BC_TextBox::draw_border()
639 BC_Resources *resources = get_resources();
641 set_color(background_color);
642 draw_box(0, 0, left_margin, get_h());
643 draw_box(get_w() - right_margin, 0, right_margin, get_h());
648 draw_3d_border(0, 0, w, h,
649 resources->text_border1,
650 resources->text_border2_hi,
651 resources->text_border3_hi,
652 resources->text_border4);
654 draw_3d_border(0, 0, w, h,
655 resources->text_border1,
656 resources->text_border2,
657 resources->text_border3,
658 resources->text_border4);
662 void BC_TextBox::draw_cursor()
664 // set_color(background_color);
672 draw_box(ibeam_x + text_x,
681 void BC_TextBox::draw(int flush)
684 int row_begin, row_end;
685 int highlight_x1, highlight_x2;
687 BC_Resources *resources = get_resources();
689 //printf("BC_TextBox::draw %d %s\n", __LINE__, text);
692 background_color = resources->text_background;
694 background_color = high_color;
696 background_color = back_color;
697 set_color(background_color);
698 draw_box(0, 0, w, h);
700 int wtext_len = wtext_update();
702 // Draw text with selection
705 for(i=0, j=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
708 wchar_t *wtext_row = &wtext[i];
709 for(j=0; j<BCTEXTLEN-1 && i<wtext_len && wtext[i]!='\n'; ++i, ++j);
710 if( (row_end=i) < wtext_len ) ++i;
712 if(k > top_margin-text_height && k < get_h()-bottom_margin) {
713 // Draw highlighted region of row
714 if(highlight_letter2 > highlight_letter1 &&
715 highlight_letter2 > row_begin &&
716 highlight_letter1 <= row_end) {
717 if(active && enabled && get_has_focus())
718 set_color(resources->text_highlight);
720 set_color(resources->text_inactive_highlight);
722 if(highlight_letter1 >= row_begin &&
723 highlight_letter1 <= row_end)
724 highlight_x1 = positions[highlight_letter1];
728 if(highlight_letter2 > row_begin &&
729 highlight_letter2 <= row_end)
730 highlight_x2 = positions[highlight_letter2];
732 highlight_x2 = get_w();
734 draw_box(highlight_x1 + text_x, k,
735 highlight_x2 - highlight_x1, text_height);
738 // Draw text over highlight
739 int len = row_end - row_begin;
741 set_color(enabled ? resources->text_default : DMGREY);
742 draw_wtext(text_x, k + text_ascent, wtext_row, len,
743 0, &positions[wtext_row - wtext]);
746 // Get ibeam location
747 if(ibeam_letter >= row_begin && ibeam_letter <= row_end) {
749 ibeam_y = k - text_y;
750 ibeam_x = positions[ibeam_letter];
755 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
757 if( wtext_len == 0 ) {
767 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
777 int BC_TextBox::focus_in_event()
783 int BC_TextBox::focus_out_event()
789 int BC_TextBox::cursor_enter_event()
791 if(top_level->event_win == win && enabled)
805 int BC_TextBox::cursor_leave_event()
817 int BC_TextBox::button_press_event()
821 if(!enabled) return 0;
822 if(get_buttonpress() != WHEEL_UP &&
823 get_buttonpress() != WHEEL_DOWN &&
824 get_buttonpress() != LEFT_BUTTON &&
825 get_buttonpress() != MIDDLE_BUTTON) return 0;
829 if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
831 int cursor_letter = 0;
832 int wtext_len = wtext_update();
833 int update_scroll = 0;
836 if(top_level->event_win == win)
841 top_level->deactivate();
846 if(get_buttonpress() == WHEEL_UP)
848 text_y += text_height;
849 text_y = MIN(text_y, top_margin);
853 if(get_buttonpress() == WHEEL_DOWN)
855 int min_y = -(get_text_rows() *
859 text_y -= text_height;
860 text_y = MAX(text_y, min_y);
861 text_y = MIN(text_y, top_margin);
867 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
869 //printf("BC_TextBox::button_press_event %d %d\n", __LINE__, cursor_letter);
872 if(get_triple_click())
874 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
876 select_line(highlight_letter1, highlight_letter2, cursor_letter);
877 highlight_letter3 = highlight_letter1;
878 highlight_letter4 = highlight_letter2;
879 ibeam_letter = highlight_letter2;
880 copy_selection(PRIMARY_SELECTION);
883 if(get_double_click())
886 select_word(highlight_letter1, highlight_letter2, cursor_letter);
887 highlight_letter3 = highlight_letter1;
888 highlight_letter4 = highlight_letter2;
889 ibeam_letter = highlight_letter2;
890 copy_selection(PRIMARY_SELECTION);
893 if(get_buttonpress() == MIDDLE_BUTTON)
895 highlight_letter3 = highlight_letter4 =
896 ibeam_letter = highlight_letter1 =
897 highlight_letter2 = cursor_letter;
898 paste_selection(PRIMARY_SELECTION);
903 highlight_letter3 = highlight_letter4 =
904 ibeam_letter = highlight_letter1 =
905 highlight_letter2 = cursor_letter;
909 // Handle scrolling by highlighting text
910 if(text_selected || word_selected || line_selected)
912 set_repeat(top_level->get_resources()->scroll_repeat);
915 if(ibeam_letter < 0) ibeam_letter = 0;
916 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
920 if(update_scroll && yscroll)
922 yscroll->update_length(get_text_rows(),
924 yscroll->get_handlelength(),
931 if(active && (!yscroll || !yscroll->is_event_win()))
933 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
934 // Suggestion popup is not active but must be deactivated.
935 if(suggestions_popup)
938 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
939 // // Pass event to suggestions popup
940 // if(!suggestions_popup->button_press_event())
942 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
943 // top_level->deactivate();
948 top_level->deactivate();
956 int BC_TextBox::button_release_event()
961 if(text_selected || word_selected || line_selected)
967 // Stop scrolling by highlighting text
968 unset_repeat(top_level->get_resources()->scroll_repeat);
974 int BC_TextBox::cursor_motion_event()
976 int cursor_letter, letter1, letter2;
979 if(text_selected || word_selected || line_selected)
981 cursor_letter = get_cursor_letter(top_level->cursor_x,
982 top_level->cursor_y);
984 //printf("BC_TextBox::cursor_motion_event %d cursor_letter=%d\n", __LINE__, cursor_letter);
988 select_line(letter1, letter2, cursor_letter);
993 select_word(letter1, letter2, cursor_letter);
998 letter1 = letter2 = cursor_letter;
1001 if(letter1 <= highlight_letter3)
1003 highlight_letter1 = letter1;
1004 highlight_letter2 = highlight_letter4;
1005 ibeam_letter = letter1;
1008 if(letter2 >= highlight_letter4)
1010 highlight_letter2 = letter2;
1011 highlight_letter1 = highlight_letter3;
1012 ibeam_letter = letter2;
1015 copy_selection(PRIMARY_SELECTION);
1028 int BC_TextBox::activate()
1030 top_level->active_subwindow = this;
1033 top_level->set_repeat(top_level->get_resources()->blink_rate);
1037 int BC_TextBox::deactivate()
1039 //printf("BC_TextBox::deactivate %d suggestions_popup=%p\n", __LINE__, suggestions_popup);
1041 top_level->unset_repeat(top_level->get_resources()->blink_rate);
1042 if(suggestions_popup)
1044 // Must deactivate instead of delete since this is called from BC_ListBox::button_press_event
1045 // suggestions_popup->deactivate();
1047 delete suggestions_popup;
1048 suggestions_popup = 0;
1055 int BC_TextBox::repeat_event(int64_t duration)
1058 int cursor_y = get_cursor_y();
1059 //int cursor_x = get_cursor_x();
1061 if(duration == top_level->get_resources()->tooltip_delay &&
1062 tooltip_text && tooltip_text[0] != 0 && highlighted)
1069 if(duration == top_level->get_resources()->blink_rate &&
1073 // don't flash if keypress
1074 if(skip_cursor->get_difference() < 500)
1076 // printf("BC_TextBox::repeat_event 1 %lld %lld\n",
1077 // skip_cursor->get_difference(),
1083 if(!(text_selected || word_selected || line_selected))
1092 if(duration == top_level->get_resources()->scroll_repeat &&
1093 (text_selected || word_selected || line_selected))
1096 if(get_cursor_y() < top_margin)
1098 difference = get_cursor_y() - top_margin ;
1101 if(get_cursor_y() > get_h() - bottom_margin)
1103 difference = get_cursor_y() -
1104 (get_h() - bottom_margin);
1106 if(difference != 0) {
1107 int min_y = -(get_text_rows() * text_height -
1108 get_h() + bottom_margin);
1110 text_y -= difference;
1111 // printf("BC_TextBox::repeat_event %d %d %d\n",
1115 text_y = MAX(min_y, text_y);
1116 text_y = MIN(text_y, top_margin);
1123 if(get_cursor_x() < left_margin)
1125 int difference = left_margin - get_cursor_x();
1127 text_x += difference;
1128 text_x = MIN(text_x, left_margin);
1132 else if(get_cursor_x() > get_w() - right_margin)
1134 int difference = get_cursor_x() - (get_w() - right_margin);
1135 int new_text_x = text_x - difference;
1137 // Get width of current row
1140 int wtext_len = wtext_update();
1143 for(int i = 0, k = text_y; i < wtext_len; k += text_height)
1146 while(wtext[i] != '\n' && i < wtext_len) {
1150 if(wtext[i] == '\n') i++;
1152 if(cursor_y >= k && cursor_y < k + text_height) {
1153 row_width = get_text_width(font,
1155 row_end - row_begin);
1161 min_x = -row_width + get_w() - left_margin - BCCURSORW;
1162 new_text_x = MAX(new_text_x, min_x);
1163 new_text_x = MIN(new_text_x, left_margin);
1165 if(new_text_x < text_x) text_x = new_text_x;
1174 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
1176 if((top_level->get_keypress() == RETURN) ||
1177 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255))
1180 wchar_t *temp_string = top_level->get_wkeystring(&len);
1181 if(top_level->get_keypress() == RETURN) {
1182 temp_string[0] = '\n'; temp_string[1] = 0;
1185 insert_text(temp_string, len);
1193 int BC_TextBox::keypress_event()
1195 // Result == 2 contents changed
1196 // Result == 1 trapped keypress
1197 // Result == 0 nothing
1199 int dispatch_event = 0;
1201 if(!active || !enabled) return 0;
1203 int wtext_len = wtext_update();
1204 last_keypress = get_keypress();
1205 //printf("BC_TextBox::keypress_event %d %x\n", __LINE__, last_keypress)
1206 switch(last_keypress)
1209 // Deactivate the suggestions
1210 if(suggestions && suggestions_popup)
1212 delete suggestions_popup;
1213 suggestions_popup = 0;
1218 top_level->deactivate();
1230 top_level->deactivate();
1236 default_keypress(dispatch_event, result);
1243 // Handle like a default keypress
1245 top_level->cycle_textboxes(1);
1252 top_level->cycle_textboxes(-1);
1257 if(ibeam_letter > 0)
1259 int old_ibeam_letter = ibeam_letter;
1269 while(ibeam_letter > 0 && isalnum(wtext[ibeam_letter - 1]))
1275 if(top_level->shift_down())
1277 // Initialize highlighting
1278 if(highlight_letter1 == highlight_letter2)
1280 highlight_letter1 = ibeam_letter;
1281 highlight_letter2 = old_ibeam_letter;
1284 // Extend left highlight
1285 if(highlight_letter1 == old_ibeam_letter)
1287 highlight_letter1 = ibeam_letter;
1290 // Shrink right highlight
1291 if(highlight_letter2 == old_ibeam_letter)
1293 highlight_letter2 = ibeam_letter;
1298 highlight_letter1 = highlight_letter2 = ibeam_letter;
1303 if(keypress_draw) draw(1);
1309 if(ibeam_letter < wtext_len)
1311 int old_ibeam_letter = ibeam_letter;
1320 while(ibeam_letter < wtext_len && isalnum(wtext[ibeam_letter++]))
1327 if(top_level->shift_down())
1329 // Initialize highlighting
1330 if(highlight_letter1 == highlight_letter2)
1332 highlight_letter1 = old_ibeam_letter;
1333 highlight_letter2 = ibeam_letter;
1336 // Shrink left highlight
1337 if(highlight_letter1 == old_ibeam_letter)
1339 highlight_letter1 = ibeam_letter;
1342 // Expand right highlight
1343 if(highlight_letter2 == old_ibeam_letter)
1345 highlight_letter2 = ibeam_letter;
1350 highlight_letter1 = highlight_letter2 = ibeam_letter;
1354 if(keypress_draw) draw(1);
1360 if(suggestions && suggestions_popup)
1362 // Pass to suggestions popup
1363 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1364 suggestions_popup->activate(1);
1365 suggestions_popup->keypress_event();
1369 if(ibeam_letter > 0)
1371 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
1372 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1373 ibeam_y + text_y - text_height);
1374 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
1377 if(top_level->shift_down())
1379 // Initialize highlighting
1380 if(highlight_letter1 == highlight_letter2)
1382 highlight_letter1 = new_letter;
1383 highlight_letter2 = ibeam_letter;
1386 // Expand left highlight
1387 if(highlight_letter1 == ibeam_letter)
1389 highlight_letter1 = new_letter;
1392 // Shrink right highlight
1393 if(highlight_letter2 == ibeam_letter)
1395 highlight_letter2 = new_letter;
1399 highlight_letter1 = highlight_letter2 = new_letter;
1401 if(highlight_letter1 > highlight_letter2)
1403 int temp = highlight_letter1;
1404 highlight_letter1 = highlight_letter2;
1405 highlight_letter2 = temp;
1407 ibeam_letter = new_letter;
1410 if(keypress_draw) draw(1);
1416 if(ibeam_letter > 0)
1418 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1419 ibeam_y + text_y - get_h());
1422 if(top_level->shift_down())
1424 // Initialize highlighting
1425 if(highlight_letter1 == highlight_letter2)
1427 highlight_letter1 = new_letter;
1428 highlight_letter2 = ibeam_letter;
1431 // Expand left highlight
1432 if(highlight_letter1 == ibeam_letter)
1434 highlight_letter1 = new_letter;
1437 // Shrink right highlight
1438 if(highlight_letter2 == ibeam_letter)
1440 highlight_letter2 = new_letter;
1444 highlight_letter1 = highlight_letter2 = new_letter;
1446 if(highlight_letter1 > highlight_letter2)
1448 int temp = highlight_letter1;
1449 highlight_letter1 = highlight_letter2;
1450 highlight_letter2 = temp;
1452 ibeam_letter = new_letter;
1455 if(keypress_draw) draw(1);
1461 // printf("BC_TextBox::keypress_event %d %p %p\n",
1464 // suggestions_popup);
1465 if(suggestions && suggestions_popup)
1467 // Pass to suggestions popup
1468 suggestions_popup->activate(1);
1469 suggestions_popup->keypress_event();
1473 // if(ibeam_letter > 0)
1476 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1477 ibeam_y + text_y + text_height);
1478 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1480 if(top_level->shift_down())
1482 // Initialize highlighting
1483 if(highlight_letter1 == highlight_letter2)
1485 highlight_letter1 = new_letter;
1486 highlight_letter2 = ibeam_letter;
1489 // Shrink left highlight
1490 if(highlight_letter1 == ibeam_letter)
1492 highlight_letter1 = new_letter;
1495 // Expand right highlight
1496 if(highlight_letter2 == ibeam_letter)
1498 highlight_letter2 = new_letter;
1502 highlight_letter1 = highlight_letter2 = new_letter;
1504 if(highlight_letter1 > highlight_letter2)
1506 int temp = highlight_letter1;
1507 highlight_letter1 = highlight_letter2;
1508 highlight_letter2 = temp;
1510 ibeam_letter = new_letter;
1513 if(keypress_draw) draw(1);
1515 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1523 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1524 ibeam_y + text_y + get_h());
1525 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1527 if(top_level->shift_down())
1529 // Initialize highlighting
1530 if(highlight_letter1 == highlight_letter2)
1532 highlight_letter1 = new_letter;
1533 highlight_letter2 = ibeam_letter;
1536 // Shrink left highlight
1537 if(highlight_letter1 == ibeam_letter)
1539 highlight_letter1 = new_letter;
1542 // Expand right highlight
1543 if(highlight_letter2 == ibeam_letter)
1545 highlight_letter2 = new_letter;
1549 highlight_letter1 = highlight_letter2 = new_letter;
1551 if(highlight_letter1 > highlight_letter2)
1553 int temp = highlight_letter1;
1554 highlight_letter1 = highlight_letter2;
1555 highlight_letter2 = temp;
1557 ibeam_letter = new_letter;
1560 if(keypress_draw) draw(1);
1562 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1569 delete suggestions_popup;
1570 suggestions_popup = 0;
1572 int old_ibeam_letter = ibeam_letter;
1574 while(ibeam_letter < wtext_len && wtext[ibeam_letter] != '\n')
1577 if(top_level->shift_down())
1580 if(highlight_letter1 == highlight_letter2)
1582 highlight_letter2 = ibeam_letter;
1583 highlight_letter1 = old_ibeam_letter;
1587 if(highlight_letter1 == old_ibeam_letter)
1589 highlight_letter1 = highlight_letter2;
1590 highlight_letter2 = ibeam_letter;
1594 if(highlight_letter2 == old_ibeam_letter)
1596 highlight_letter2 = ibeam_letter;
1600 highlight_letter1 = highlight_letter2 = ibeam_letter;
1603 if(keypress_draw) draw(1);
1610 delete suggestions_popup;
1611 suggestions_popup = 0;
1613 int old_ibeam_letter = ibeam_letter;
1615 while(ibeam_letter > 0 && wtext[ibeam_letter - 1] != '\n')
1618 if(top_level->shift_down())
1621 if(highlight_letter1 == highlight_letter2)
1623 highlight_letter2 = old_ibeam_letter;
1624 highlight_letter1 = ibeam_letter;
1628 if(highlight_letter1 == old_ibeam_letter)
1630 highlight_letter1 = ibeam_letter;
1634 if(highlight_letter2 == old_ibeam_letter)
1636 highlight_letter2 = highlight_letter1;
1637 highlight_letter1 = ibeam_letter;
1641 highlight_letter1 = highlight_letter2 = ibeam_letter;
1644 if(keypress_draw) draw(1);
1650 if(suggestions_popup)
1652 delete suggestions_popup;
1653 suggestions_popup = 0;
1656 if(highlight_letter1 == highlight_letter2)
1658 if(ibeam_letter > 0)
1660 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1666 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1667 highlight_letter2 = ibeam_letter = highlight_letter1;
1671 if(keypress_draw) draw(1);
1677 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1678 if(highlight_letter1 == highlight_letter2)
1680 if(ibeam_letter < wtext_len)
1682 delete_selection(ibeam_letter, ibeam_letter + 1, wtext_len);
1687 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1688 highlight_letter2 = ibeam_letter = highlight_letter1;
1692 if(keypress_draw) draw(1);
1702 if(get_keypress() == 'c' || get_keypress() == 'C')
1704 if(highlight_letter1 != highlight_letter2)
1706 copy_selection(SECONDARY_SELECTION);
1711 if(get_keypress() == 'v' || get_keypress() == 'V')
1713 paste_selection(SECONDARY_SELECTION);
1715 if(keypress_draw) draw(1);
1720 if(get_keypress() == 'x' || get_keypress() == 'X')
1722 if(highlight_letter1 != highlight_letter2)
1724 copy_selection(SECONDARY_SELECTION);
1725 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1726 highlight_letter2 = ibeam_letter = highlight_letter1;
1730 if(keypress_draw) draw(1);
1738 default_keypress(dispatch_event, result);
1742 if(result) skip_cursor->update();
1743 if(dispatch_event && handle_event())
1750 int BC_TextBox::uses_text()
1756 void BC_TextBox::delete_selection(int letter1, int letter2, int wtext_len)
1759 for(i=letter1, j=letter2; j<wtext_len; i++, j++) {
1760 wtext[i] = wtext[j];
1768 void BC_TextBox::insert_text(const wchar_t *wcp, int len)
1770 if( len < 0 ) len = wcslen(wcp);
1771 int wtext_len = wtext_update();
1772 if(highlight_letter1 < highlight_letter2)
1774 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1775 highlight_letter2 = ibeam_letter = highlight_letter1;
1776 wtext_len = wtext_update();
1781 for(i=wtext_len-1, j=wtext_len+len-1; i>=ibeam_letter; i--, j--) {
1782 if( j >= wsize ) continue;
1783 wtext[j] = wtext[i];
1786 for(i = ibeam_letter, j = 0; j < len; j++, i++) {
1787 if( i >= wsize ) break;
1790 if( (wlen+=len) > wsize ) wlen = wsize;
1791 if( (ibeam_letter+=len) > wsize ) ibeam_letter = wsize;
1792 wtext[wlen] = 0; // wtext allocated wsize+1
1796 int BC_TextBox::is_separator(const char *txt, int i)
1798 if( i != 0 || separators[0] != '+' ) return !isalnum(txt[i]);
1799 return txt[0] != '+' && txt[0] != '-' && !isalnum(txt[0]);
1802 // used for time entry
1803 void BC_TextBox::do_separators(int ibeam_left)
1807 // Remove separators from text
1808 int wtext_len = wtext_update();
1809 for(int i = 0; i < wtext_len; ) {
1810 if( !iswalnum(wtext[i]) ) {
1811 for(int j = i; j < wtext_len - 1; j++)
1812 wtext[j] = wtext[j + 1];
1813 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1819 wtext[wtext_len] = 0;
1825 // Insert separators into text
1826 int separator_len = strlen(separators);
1827 for(int i = 0; i < separator_len; i++) {
1829 // Insert a separator
1830 if( is_separator(separators,i) ) {
1831 for(int j = wtext_len; j >= i; j--) {
1832 wtext[j + 1] = wtext[j];
1834 if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1836 wtext[i] = separators[i];
1840 wtext[i] = separators[i];
1845 wtext[separator_len] = 0;
1846 wlen = separator_len;
1850 void BC_TextBox::get_ibeam_position(int &x, int &y)
1852 int i, row_begin, row_end;
1853 int wtext_len = wtext_update();
1857 for( i=0; i<wtext_len; ) {
1859 for(; i<wtext_len && wtext[i]!='\n'; i++);
1862 if( ibeam_letter >= row_begin && ibeam_letter <= row_end ) {
1863 x = get_text_width(font, &wtext[row_begin], ibeam_letter - row_begin);
1864 //printf("BC_TextBox::get_ibeam_position %d %d %d %d %d\n", ibeam_letter, row_begin, row_end, x, y);
1868 if( i < wtext_len && wtext[i] == '\n' ) {
1873 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1879 void BC_TextBox::set_text_row(int row)
1881 text_x = left_margin;
1882 text_y = -(row * text_height) + top_margin;
1886 int BC_TextBox::get_text_row()
1888 return -(text_y - top_margin) / text_height;
1891 void BC_TextBox::find_ibeam(int dispatch_event)
1894 int old_x = text_x, old_y = text_y;
1896 get_ibeam_position(x, y);
1898 if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1900 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1901 if(text_x > left_margin) text_x = left_margin;
1904 if(left_margin + text_x + x < left_margin)
1906 text_x = -(x - (get_w() / 4)) + left_margin;
1907 if(text_x > left_margin) text_x = left_margin;
1910 int text_row = y / text_height;
1911 if( text_row < rows ) text_y = top_margin;
1913 int pix_rows = get_h() - bottom_margin - (y + text_y);
1914 if( pix_rows < text_height )
1915 text_y -= text_height * ((2*text_height-1-pix_rows) / text_height);
1917 pix_rows = y + text_y - top_margin;
1918 if( pix_rows < 0 ) {
1919 text_y += text_height * ((text_height-1-pix_rows) / text_height);
1920 if( text_y > top_margin ) text_y = top_margin;
1923 if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1927 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1929 int i, j, k, row_begin, row_end, result = 0, done = 0;
1930 int column1, column2;
1931 int got_visible_row = 0;
1933 // Select complete row if cursor above the window
1934 //printf("BC_TextBox::get_cursor_letter %d %d\n", __LINE__, text_y);
1935 if(cursor_y < text_y - text_height)
1941 int wtext_len = wtext_update();
1943 for(i=0, k=text_y; i<wtext_len && k<get_h() && !done; k+=text_height) {
1944 // Simulate drawing of 1 row
1946 for(j = 0; wtext[i]!='\n' && i<wtext_len; i++);
1950 int first_visible_row = 0;
1951 int last_visible_row = 0;
1952 if( k+text_height > top_margin && !got_visible_row) {
1953 first_visible_row = 1;
1954 got_visible_row = 1;
1957 if( (k+text_height >= get_h() - bottom_margin ||
1958 (row_end >= wtext_len && k < get_h() - bottom_margin &&
1959 k + text_height > 0)) )
1960 last_visible_row = 1;
1962 // Cursor is inside vertical range of row
1963 if((cursor_y >= top_margin &&
1964 cursor_y < get_h() - bottom_margin &&
1965 cursor_y >= k && cursor_y < k + text_height) ||
1966 // Cursor is above 1st row
1967 (cursor_y < k + text_height && first_visible_row) ||
1968 // Cursor is below last row
1969 (cursor_y >= k && last_visible_row))
1971 column1 = column2 = 0;
1972 for(j = row_begin; j<wsize && j<=row_end && !done; j++) {
1973 column2 = get_text_width(font, &wtext[row_begin], j-row_begin) + text_x;
1974 if((column2 + column1) / 2 >= cursor_x) {
1977 // printf("BC_TextBox::get_cursor_letter %d %d %d %d\n",
1978 // __LINE__, result, first_visible_row, last_visible_row);
1989 if(wtext[i] == '\n') i++;
1991 // Select complete row if last visible & cursor is below window
1992 if(last_visible_row && cursor_y > k + text_height * 2)
1995 if(i >= wtext_len && !done) {
2001 // printf("BC_TextBox::get_cursor_letter %d cursor_y=%d k=%d h=%d %d %d\n",
2002 // __LINE__, cursor_y, k, get_h(), first_visible_row, last_visible_row);
2003 if(result < 0) result = 0;
2004 if(result > wtext_len) {
2005 //printf("BC_TextBox::get_cursor_letter %d\n", __LINE__);
2013 int BC_TextBox::get_cursor_letter2(int cursor_x, int cursor_y)
2015 int i, j, k, row_begin, row_end, result = 0, done = 0;
2016 int column1, column2;
2017 int wtext_len = wtext_update();
2019 if(cursor_y < text_y) {
2024 for(i = 0, k = text_y; i < wtext_len && !done; k += text_height) {
2026 for(; wtext[i] != '\n' && i < wtext_len; i++);
2029 if(cursor_y >= k && cursor_y < k + text_height) {
2030 column1 = column2 = 0;
2031 for(j = 0; j <= row_end - row_begin && !done; j++) {
2032 column2 = get_text_width(font, &wtext[row_begin], j) + text_x;
2033 if((column2 + column1) / 2 >= cursor_x) {
2034 result = row_begin + j - 1;
2045 if(wtext[i] == '\n') i++;
2047 if(i >= wtext_len && !done) {
2051 if(result < 0) result = 0;
2052 if(result > wtext_len) result = wtext_len;
2057 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
2059 int wtext_len = wtext_update();
2060 if(!wtext_len) return;
2062 letter1 = letter2 = ibeam_letter;
2064 if(iswalnum(wtext[letter1])) letter1--;
2065 } while(letter1 > 0 && iswalnum(wtext[letter1]));
2067 if( !iswalnum(wtext[letter1]) ) letter1++;
2070 if( iswalnum(wtext[letter2]) ) letter2++;
2071 } while( letter2 < wtext_len && isalnum(wtext[letter2]) );
2073 if( letter2 < wtext_len && wtext[letter2] == ' ') letter2++;
2075 if(letter1 < 0) letter1 = 0;
2076 if(letter2 < 0) letter2 = 0;
2077 if(letter1 > wtext_len) letter1 = wtext_len;
2078 if(letter2 > wtext_len) letter2 = wtext_len;
2081 void BC_TextBox::select_line(int &letter1, int &letter2, int ibeam_letter)
2083 int wtext_len = wtext_update();
2084 if(!wtext_len) return;
2086 letter1 = letter2 = ibeam_letter;
2088 // Rewind to previous linefeed
2090 if( wtext[letter1] != '\n' ) letter1--;
2091 } while( letter1 > 0 && wtext[letter1] != '\n' );
2092 if( wtext[letter1] == '\n' ) letter1++;
2094 // Advance to next linefeed
2096 if( wtext[letter2] != '\n' ) letter2++;
2097 } while( letter2 < wtext_len && wtext[letter2] != '\n' );
2098 if( letter2 < wtext_len && wtext[letter2] == '\n') letter2++;
2100 if(letter1 < 0) letter1 = 0;
2101 if(letter2 < 0) letter2 = 0;
2102 if(letter1 > wtext_len) letter1 = wtext_len;
2103 if(letter2 > wtext_len) letter2 = wtext_len;
2106 void BC_TextBox::copy_selection(int clipboard_num)
2108 int wtext_len = wtext_update();
2109 if(!wtext_len) return;
2111 if(highlight_letter1 >= wtext_len || highlight_letter2 > wtext_len ||
2112 highlight_letter1 < 0 || highlight_letter2 < 0 ||
2113 highlight_letter2 - highlight_letter1 <= 0) return;
2114 int clip_len = highlight_letter2 - highlight_letter1;
2115 char ctext[clip_len+1];
2116 //printf(" BC_TextBox::copy_selection %d %d %d\n",highlight_letter1, highlight_letter2, clip_len);
2117 text_update(&wtext[highlight_letter1],clip_len, ctext,clip_len+1);
2118 get_clipboard()->to_clipboard(ctext, clip_len, clipboard_num);
2122 void BC_TextBox::paste_selection(int clipboard_num)
2124 int len = get_clipboard()->clipboard_len(clipboard_num);
2127 char cstring[len]; wchar_t wstring[len]; --len;
2128 get_clipboard()->from_clipboard(cstring, len, clipboard_num);
2129 //printf("BC_TextBox::paste_selection %d '%*.*s'\n",len,len,len,cstring);
2130 BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
2131 cstring,(len+1), (char *)wstring,(len+1)*sizeof(wchar_t));
2132 insert_text(wstring, len);
2136 void BC_TextBox::set_keypress_draw(int value)
2138 keypress_draw = value;
2141 int BC_TextBox::get_last_keypress()
2143 return last_keypress;
2146 int BC_TextBox::get_ibeam_letter()
2148 return ibeam_letter;
2151 void BC_TextBox::set_ibeam_letter(int number, int redraw)
2153 this->ibeam_letter = number;
2160 void BC_TextBox::set_separators(const char *separators)
2162 this->separators = (char*)separators;
2165 int BC_TextBox::get_rows()
2176 BC_TextBoxSuggestions::BC_TextBoxSuggestions(BC_TextBox *text_box,
2184 text_box->suggestions,
2191 this->text_box = text_box;
2193 set_justify(LISTBOX_LEFT);
2196 BC_TextBoxSuggestions::~BC_TextBoxSuggestions()
2200 int BC_TextBoxSuggestions::selection_changed()
2203 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2204 BC_ListBoxItem *item = get_selection(0, 0);
2205 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2209 char *current_suggestion = item->get_text();
2210 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2211 // int text_box_len = strlen(text_box->text);
2212 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2213 strcpy(text_box->text + text_box->suggestion_column, current_suggestion);
2214 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2215 *(text_box->text + text_box->suggestion_column + strlen(current_suggestion)) = 0;
2217 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2219 text_box->handle_event();
2229 int BC_TextBoxSuggestions::handle_event()
2231 char *current_suggestion = 0;
2232 BC_ListBoxItem *item = get_selection(0, 0);
2233 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2234 if(item && (current_suggestion=item->get_text()) != 0)
2236 int col = text_box->suggestion_column;
2237 int len = BCTEXTLEN-1 - col;
2238 char *cp = &text_box->text[col];
2239 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2240 strncpy(cp, current_suggestion, len);
2241 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2242 if( (col=strlen(current_suggestion)) >= len )
2244 text_box->dirty = 1;
2248 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2249 text_box->highlight_letter1 =
2250 text_box->highlight_letter2 =
2251 text_box->ibeam_letter = text_box->tstrlen();
2252 text_box->wtext_update();
2254 text_box->handle_event();
2255 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2266 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2267 int x, int y, int w, int rows,
2268 const char *default_text, int default_size)
2270 this->parent_window = parent_window;
2275 this->default_text = default_text;
2276 this->default_wtext = 0;
2277 this->default_size = default_size;
2280 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2281 int x, int y, int w, int rows,
2282 const wchar_t *default_wtext, int default_size)
2284 this->parent_window = parent_window;
2289 this->default_text = 0;
2290 this->default_wtext = default_wtext;
2291 this->default_size = default_size;
2294 BC_ScrollTextBox::~BC_ScrollTextBox()
2303 void BC_ScrollTextBox::create_objects()
2305 // Must be created first
2306 parent_window->add_subwindow(text = default_wtext ?
2307 new BC_ScrollTextBoxText(this, default_wtext) :
2308 new BC_ScrollTextBoxText(this, default_text));
2309 parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
2310 text->yscroll = yscroll;
2311 yscroll->bound_to = text;
2315 int BC_ScrollTextBox::handle_event()
2320 int BC_ScrollTextBox::get_x()
2325 int BC_ScrollTextBox::get_y()
2330 int BC_ScrollTextBox::get_w()
2335 int BC_ScrollTextBox::get_h()
2337 return this->text->get_h();
2340 int BC_ScrollTextBox::get_rows()
2346 const char* BC_ScrollTextBox::get_text()
2348 return text->get_text();
2351 const wchar_t* BC_ScrollTextBox::get_wtext()
2353 return text->get_wtext();
2356 void BC_ScrollTextBox::set_text(char *text, int isz)
2358 this->text->set_text(text, isz);
2359 yscroll->update_length(this->text->get_text_rows(),
2360 this->text->get_text_row(),
2361 yscroll->get_handlelength(),
2365 int BC_ScrollTextBox::set_text_row(int n)
2367 text->set_text_row(n);
2368 yscroll->update_value(n);
2372 void BC_ScrollTextBox::update(const char *text)
2374 this->text->update(text);
2375 yscroll->update_length(this->text->get_text_rows(),
2376 this->text->get_text_row(),
2377 yscroll->get_handlelength(),
2381 void BC_ScrollTextBox::update(const wchar_t *wtext)
2383 this->text->update(wtext);
2384 yscroll->update_length(this->text->get_text_rows(),
2385 this->text->get_text_row(),
2386 yscroll->get_handlelength(),
2390 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
2397 text->reposition_window(x,
2399 w - yscroll->get_span(),
2401 yscroll->reposition_window(x + w - yscroll->get_span(),
2403 BC_TextBox::calculate_row_h(rows,
2405 yscroll->update_length(text->get_text_rows(),
2406 text->get_text_row(),
2411 void BC_ScrollTextBox::set_selection(int char1, int char2, int ibeam)
2413 this->text->set_selection(char1, char2, ibeam);
2422 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const char *text)
2423 : BC_TextBox(gui->x, gui->y,
2424 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2425 gui->rows, gui->default_size, (char*)text, 1, MEDIUMFONT)
2430 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const wchar_t *wtext)
2431 : BC_TextBox(gui->x, gui->y,
2432 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2433 gui->rows, gui->default_size, (wchar_t*)wtext, 1, MEDIUMFONT)
2438 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
2447 int BC_ScrollTextBoxText::handle_event()
2449 gui->yscroll->update_length(get_text_rows(),
2451 gui->yscroll->get_handlelength(),
2453 return gui->handle_event();
2456 int BC_ScrollTextBoxText::motion_event()
2458 gui->yscroll->update_length(get_text_rows(),
2460 gui->yscroll->get_handlelength(),
2466 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
2467 : BC_ScrollBar(gui->x +
2469 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2472 BC_TextBox::calculate_row_h(gui->rows,
2473 gui->parent_window),
2474 gui->text->get_text_rows(),
2481 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
2485 int BC_ScrollTextBoxYScroll::handle_event()
2487 gui->text->set_text_row(get_position());
2500 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const char *text)
2501 : BC_TextBox(x, y, popup->text_w, 1, text, BCTEXTLEN)
2503 this->popup = popup;
2506 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const wchar_t *wtext)
2507 : BC_TextBox(x, y, popup->text_w, 1, wtext, BCTEXTLEN)
2509 this->popup = popup;
2512 BC_PopupTextBoxText::~BC_PopupTextBoxText()
2522 int BC_PopupTextBoxText::handle_event()
2524 popup->handle_event();
2528 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
2530 popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
2531 popup->list_h, popup->list_format, popup->list_items, 0, 0, 1, 0, 1)
2533 this->popup = popup;
2535 int BC_PopupTextBoxList::handle_event()
2537 BC_ListBoxItem *item = get_selection(0, 0);
2540 popup->textbox->update(item->get_text());
2541 popup->handle_event();
2549 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window,
2550 ArrayList<BC_ListBoxItem*> *list_items,
2551 const char *default_text, int x, int y,
2552 int text_w, int list_h, int list_format)
2556 this->list_h = list_h;
2557 this->list_format = list_format;
2558 this->default_text = (char*)default_text;
2559 this->default_wtext = 0;
2560 this->text_w = text_w;
2561 this->parent_window = parent_window;
2562 this->list_items = list_items;
2565 BC_PopupTextBox::~BC_PopupTextBox()
2575 int BC_PopupTextBox::create_objects()
2577 int x = this->x, y = this->y;
2578 parent_window->add_subwindow(textbox = default_wtext ?
2579 new BC_PopupTextBoxText(this, x, y, default_wtext) :
2580 new BC_PopupTextBoxText(this, x, y, default_text));
2581 x += textbox->get_w();
2582 parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
2586 void BC_PopupTextBox::update(const char *text)
2588 textbox->update(text);
2591 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
2593 listbox->update(data,
2600 const char* BC_PopupTextBox::get_text()
2602 return textbox->get_text();
2605 const wchar_t* BC_PopupTextBox::get_wtext()
2607 return textbox->get_wtext();
2610 int BC_PopupTextBox::get_number()
2612 return listbox->get_selection_number(0, 0);
2615 int BC_PopupTextBox::get_x()
2620 int BC_PopupTextBox::get_y()
2625 int BC_PopupTextBox::get_w()
2627 return textbox->get_w() + listbox->get_w();
2630 int BC_PopupTextBox::get_h()
2632 return textbox->get_h();
2635 int BC_PopupTextBox::handle_event()
2640 void BC_PopupTextBox::reposition_window(int x, int y)
2645 textbox->reposition_window(x1,
2648 textbox->get_rows());
2649 x1 += textbox->get_w();
2650 listbox->reposition_window(x1, y1, -1, -1, 0);
2651 // if(flush) parent_window->flush();
2667 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2668 int64_t default_value,
2673 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2675 this->popup = popup;
2678 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2679 float default_value,
2684 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2686 this->popup = popup;
2689 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
2701 int BC_TumbleTextBoxText::handle_event()
2703 popup->handle_event();
2707 int BC_TumbleTextBoxText::button_press_event()
2711 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
2713 if(get_buttonpress() == 4)
2715 popup->tumbler->handle_up_event();
2718 if(get_buttonpress() == 5)
2720 popup->tumbler->handle_down_event();
2730 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2731 int64_t default_value,
2743 this->default_value = default_value;
2744 this->text_w = text_w;
2745 this->parent_window = parent_window;
2751 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2764 this->default_value = default_value;
2765 this->text_w = text_w;
2766 this->parent_window = parent_window;
2772 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2773 float default_value_f,
2783 this->min_f = min_f;
2784 this->max_f = max_f;
2785 this->default_value_f = default_value_f;
2786 this->text_w = text_w;
2787 this->parent_window = parent_window;
2793 BC_TumbleTextBox::~BC_TumbleTextBox()
2795 // Recursive delete. Normally ~BC_TumbleTextBox is never called but textbox
2796 // is deleted anyway by the windowbase so textbox deletes this.
2797 if(tumbler) delete tumbler;
2799 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
2808 void BC_TumbleTextBox::reset()
2815 void BC_TumbleTextBox::set_precision(int precision)
2817 this->precision = precision;
2820 void BC_TumbleTextBox::set_increment(float value)
2822 this->increment = value;
2823 if(tumbler) tumbler->set_increment(value);
2826 int BC_TumbleTextBox::create_objects()
2828 int x = this->x, y = this->y;
2832 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2838 textbox->set_precision(precision);
2841 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2848 x += textbox->get_w();
2851 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox,
2857 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox,
2863 tumbler->set_increment(increment);
2867 const char* BC_TumbleTextBox::get_text()
2869 return textbox->get_text();
2872 const wchar_t* BC_TumbleTextBox::get_wtext()
2874 return textbox->get_wtext();
2877 BC_TextBox* BC_TumbleTextBox::get_textbox()
2882 int BC_TumbleTextBox::update(const char *value)
2884 textbox->update(value);
2888 int BC_TumbleTextBox::update(int64_t value)
2890 textbox->update(value);
2894 int BC_TumbleTextBox::update(float value)
2896 textbox->update(value);
2901 int BC_TumbleTextBox::get_x()
2906 int BC_TumbleTextBox::get_y()
2911 int BC_TumbleTextBox::get_w()
2913 return textbox->get_w() + tumbler->get_w();
2916 int BC_TumbleTextBox::get_h()
2918 return textbox->get_h();
2921 void BC_TumbleTextBox::disable()
2923 if( !get_enabled() ) return;
2924 tumbler->hide_window(0);
2925 return textbox->disable();
2928 void BC_TumbleTextBox::enable()
2930 if( get_enabled() ) return;
2931 tumbler->show_window(0);
2932 return textbox->enable();
2935 int BC_TumbleTextBox::get_enabled()
2937 return textbox->get_enabled();
2940 int BC_TumbleTextBox::handle_event()
2945 void BC_TumbleTextBox::reposition_window(int x, int y)
2950 textbox->reposition_window(x,
2954 tumbler->reposition_window(x + textbox->get_w(),
2956 // if(flush) parent_window->flush();
2960 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2962 tumbler->set_boundaries(min, max);
2965 void BC_TumbleTextBox::set_boundaries(float min, float max)
2967 tumbler->set_boundaries(min, max);