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();
142 int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
144 suggestions = new ArrayList<BC_ListBoxItem*>;
145 suggestions_popup = 0;
146 suggestion_column = 0;
149 this->has_border = has_border;
152 this->tsize = size >= 0 ? size : -size;
153 this->text = size > 0 ? new char[size+1] : 0;
154 if( this->text ) this->text[0] = 0;
157 highlight_letter1 = highlight_letter2 = 0;
158 highlight_letter3 = highlight_letter4 = 0;
169 skip_cursor = new Timer;
183 int BC_TextBox::tstrlen()
185 if( !tsize ) return strlen(text);
186 return strnlen(text, tsize);
189 int BC_TextBox::tstrcmp(const char *cp)
191 if( !tsize ) return strcmp(text, cp);
192 return strncmp(text, cp, tsize);
195 char *BC_TextBox::tstrcpy(const char *cp)
200 return strcpy(text, cp);
201 strncpy(text, cp, tsize);
209 char *BC_TextBox::tstrcat(const char *cp)
212 if( !tsize ) return strcat(text, cp);
213 char *result = strncat(text, cp, tsize);
218 int BC_TextBox::wtext_update()
221 const char *src_enc = is_utf8 ? "UTF8" : BC_Resources::encoding;
222 const char *dst_enc = BC_Resources::wide_encoding;
223 int nsize = tsize > 0 ? tsize : strlen(text) + BCTEXTLEN;
224 if( nsize > wsize || !wtext ) {
225 wchar_t *ntext = new wchar_t[nsize+1];
226 memcpy(ntext, wtext, wsize*sizeof(wtext[0]));
227 delete [] wtext; wtext = ntext; wsize = nsize;
228 int *npositions = new int[nsize+1];
230 memcpy(npositions, positions, (plen+1)*sizeof(positions[0]));
233 delete [] positions; positions = npositions; plen = nsize;
235 wlen = BC_Resources::encode(src_enc, dst_enc, text, strlen(text),
236 (char*)wtext, wsize*sizeof(wchar_t)) / sizeof(wchar_t);
243 int BC_TextBox::text_update(const wchar_t *wcp, int wsz, char *tcp, int tsz)
245 const char *src_enc = BC_Resources::wide_encoding;
246 const char *dst_enc = BC_Resources::encoding;
247 if( wsz < 0 ) wsz = wcslen(wcp);
248 int len = BC_Resources::encode(src_enc, dst_enc,
249 (char*)wcp, wsz*sizeof(wchar_t), tcp, tsz);
254 int BC_TextBox::initialize()
257 skip_cursor = new Timer;
258 skip_cursor->update();
260 text_ascent = get_text_ascent(font) + 1;
261 text_descent = get_text_descent(font) + 1;
262 text_height = text_ascent + text_descent;
263 ibeam_letter = wtext_update();
266 left_margin = right_margin = HORIZONTAL_MARGIN;
267 top_margin = bottom_margin = VERTICAL_MARGIN;
271 left_margin = right_margin = HORIZONTAL_MARGIN_NOBORDER;
272 top_margin = bottom_margin = VERTICAL_MARGIN_NOBORDER;
275 text_x = left_margin;
279 // Create the subwindow
280 BC_SubWindow::initialize();
282 BC_Resources *resources = get_resources();
285 back_color = resources->text_background;
286 high_color = resources->text_background_hi;
290 high_color = resources->text_background_noborder_hi;
291 back_color = bg_color;
295 set_cursor(IBEAM_CURSOR, 0, 0);
300 int BC_TextBox::calculate_h(BC_WindowBase *gui,
305 return rows * (gui->get_text_ascent(font) + 1 +
306 gui->get_text_descent(font) + 1) +
307 2 * (has_border ? VERTICAL_MARGIN : VERTICAL_MARGIN_NOBORDER);
310 void BC_TextBox::set_precision(int precision)
312 this->precision = precision;
315 // Compute suggestions for a path
316 int BC_TextBox::calculate_suggestions(ArrayList<BC_ListBoxItem*> *entries)
318 // Let user delete suggestion
319 if(get_last_keypress() != BACKSPACE)
322 // Compute suggestions
324 ArrayList<char*> suggestions;
325 const char *current_text = get_text();
327 // If directory, tabulate it
328 if(current_text[0] == '/' ||
329 current_text[0] == '~')
331 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
332 char string[BCTEXTLEN];
333 strncpy(string, current_text, sizeof(string));
334 char *ptr = strrchr(string, '/');
335 if(!ptr) ptr = strrchr(string, '~');
337 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
339 int suggestion_column = ptr + 1 - string;
341 fs.set_filter(get_resources()->filebox_filter);
342 // fs.set_sort_order(filebox->sort_order);
343 // fs.set_sort_field(filebox->column_type[filebox->sort_column]);
346 //printf("BC_TextBox::calculate_suggestions %d %c %s\n", __LINE__, *ptr, string);
347 if(current_text[0] == '~' && *ptr != '/')
353 fs.parse_tildas(string);
356 //printf("BC_TextBox::calculate_suggestions %d %d\n", __LINE__, fs.total_files());
359 // Accept only entries with matching trailing characters
360 ptr = strrchr((char*)current_text, '/');
361 if(!ptr) ptr = strrchr((char*)current_text, '~');
363 //printf("BC_TextBox::calculate_suggestions %d %s %p\n", __LINE__, current_text, ptr);
368 for(int i = 0; i < fs.total_files(); i++)
370 char *current_name = fs.get_entry(i)->name;
371 if(!strncmp(ptr, current_name, strlen(ptr)))
373 suggestions.append(current_name);
374 //printf("BC_TextBox::calculate_suggestions %d %s\n", __LINE__, current_name);
379 // Accept all entries
380 for(int i = 0; i < fs.total_files(); i++)
382 //printf("BC_TextBox::calculate_suggestions %d %s\n", __LINE__, fs.get_entry(i)->name);
383 suggestions.append(fs.get_entry(i)->name);
385 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
387 // Add 1 to column to keep /
388 set_suggestions(&suggestions, suggestion_column);
389 //printf("BC_TextBox::calculate_suggestions %d\n", __LINE__);
392 // Get entries from current listbox with matching trailing characters
395 // printf("BC_TextBox::calculate_suggestions %d %d\n",
398 for(int i = 0; i < entries->size(); i++)
400 char *current_name = entries->get(i)->get_text();
402 //printf("BC_TextBox::calculate_suggestions %d %s %s\n", __LINE__, current_text, current_name);
403 if(!strncmp(current_text, current_name, strlen(current_text)))
405 suggestions.append(current_name);
409 set_suggestions(&suggestions, 0);
416 void BC_TextBox::set_suggestions(ArrayList<char*> *suggestions, int column)
419 this->suggestions->remove_all_objects();
420 this->suggestion_column = column;
424 for(int i = 0; i < suggestions->size(); i++)
426 this->suggestions->append(new BC_ListBoxItem(suggestions->get(i)));
429 // Show the popup without taking focus
430 if(suggestions->size() > 1)
432 if(!suggestions_popup)
435 get_parent()->add_subwindow(suggestions_popup =
436 new BC_TextBoxSuggestions(this, x, y));
437 suggestions_popup->set_is_suggestions(1);
438 suggestions_popup->activate(0);
442 suggestions_popup->update(this->suggestions,
446 suggestions_popup->activate(0);
450 // Show the highlighted text
451 if(suggestions->size() == 1)
453 highlight_letter1 = wtext_update();
454 text_update(wtext,wlen, text,tsize);
455 char *current_suggestion = suggestions->get(0);
456 int col = highlight_letter1 - suggestion_column;
457 if( col < 0 ) col = 0;
458 char *cur = current_suggestion + col;
460 highlight_letter2 = wtext_update();
461 //printf("BC_TextBox::set_suggestions %d %d\n", __LINE__, suggestion_column);
465 delete suggestions_popup;
466 suggestions_popup = 0;
471 if(!suggestions || !this->suggestions->size())
473 delete suggestions_popup;
474 suggestions_popup = 0;
478 void BC_TextBox::wset_selection(int char1, int char2, int ibeam)
480 highlight_letter1 = char1;
481 highlight_letter2 = char2;
482 ibeam_letter = ibeam;
486 // count utf8 chars in text which occur before cp
487 int BC_TextBox::wcpos(const char *text, const char *cp)
490 const unsigned char *bp = (const unsigned char *)text;
491 const unsigned char *ep = (const unsigned char *)cp;
492 while( bp < ep && *bp != 0 ) {
495 if( ch < 0x80 ) continue;
497 int n = i<0? 0 : i<32? 1 : i<48? 2 : i<56? 3 : i<60? 4 : 5;
498 for( i=n; bp < ep && --i>=0 && (*bp&0xc0) == 0x80; ++bp );
503 void BC_TextBox::set_selection(int char1, int char2, int ibeam)
505 const char *cp = get_text();
506 wset_selection(wcpos(cp, cp+char1), wcpos(cp, cp+char2), wcpos(cp, cp+ibeam));
509 int BC_TextBox::update(const char *text)
511 //printf("BC_TextBox::update 1 %d %s %s\n", tstrcmp(text), text, this->text);
512 // Don't update if contents are the same
513 if(!tstrcmp(text)) return 0;
515 int wtext_len = wtext_update();
516 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
517 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
518 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
523 int BC_TextBox::update(const wchar_t *wtext)
525 int wtext_len = wcslen(wtext);
526 if( wtext_len >= wsize ) wtext_len = wsize;
527 wcsncpy(this->wtext, wtext, wtext_len);
529 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
530 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
531 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
536 int BC_TextBox::update(int64_t value)
538 char string[BCTEXTLEN];
539 sprintf(string, "%jd", value);
544 int BC_TextBox::update(float value)
546 char string[BCTEXTLEN];
547 sprintf(string, "%0.*f", precision, value);
552 void BC_TextBox::disable()
557 if(active) top_level->deactivate();
563 void BC_TextBox::enable()
573 int BC_TextBox::get_enabled()
578 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
580 return (pixels - 4) /
581 (window->get_text_ascent(font) + 1 +
582 window->get_text_descent(font) + 1);
585 int BC_TextBox::calculate_row_h(int rows,
586 BC_WindowBase *parent_window,
591 (parent_window->get_text_ascent(font) + 1 +
592 parent_window->get_text_descent(font) + 1) +
593 (has_border ? 4 : 0);
596 const char* BC_TextBox::get_text()
598 int wtext_len = wtext_update();
599 text_update(wtext,wtext_len, text,tsize);
603 const wchar_t* BC_TextBox::get_wtext()
609 void BC_TextBox::set_text(char *text, int isz)
611 if( size > 0 || isz < 0 ) return;
620 int BC_TextBox::get_text_rows()
622 int wtext_len = wtext_update();
624 for(int i = 0; i < wtext_len; i++) {
625 if(wtext[i] == '\n') result++;
631 int BC_TextBox::get_row_h(int rows)
633 return rows * text_height + top_margin + bottom_margin;
636 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
639 if(w < 0) w = get_w();
642 new_h = get_row_h(rows);
651 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
652 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
653 BC_WindowBase::reposition_window(x, y, w, new_h);
659 void BC_TextBox::draw_border()
661 BC_Resources *resources = get_resources();
663 set_color(background_color);
664 draw_box(0, 0, left_margin, get_h());
665 draw_box(get_w() - right_margin, 0, right_margin, get_h());
670 draw_3d_border(0, 0, w, h,
671 resources->text_border1,
672 resources->text_border2_hi,
673 resources->text_border3_hi,
674 resources->text_border4);
676 draw_3d_border(0, 0, w, h,
677 resources->text_border1,
678 resources->text_border2,
679 resources->text_border3,
680 resources->text_border4);
684 void BC_TextBox::draw_cursor()
686 // set_color(background_color);
694 draw_box(ibeam_x + text_x,
703 void BC_TextBox::draw(int flush)
706 int row_begin, row_end;
707 int highlight_x1, highlight_x2;
709 BC_Resources *resources = get_resources();
711 //printf("BC_TextBox::draw %d %s\n", __LINE__, text);
714 background_color = resources->text_background;
716 background_color = high_color;
718 background_color = back_color;
719 set_color(background_color);
720 draw_box(0, 0, w, h);
722 int wtext_len = wtext_update();
724 // Draw text with selection
727 for(i=0, j=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
730 wchar_t *wtext_row = &wtext[i];
731 for(j=0; j<BCTEXTLEN-1 && i<wtext_len && wtext[i]!='\n'; ++i, ++j);
732 if( (row_end=i) < wtext_len ) ++i;
734 if(k > top_margin-text_height && k < get_h()-bottom_margin) {
735 // Draw highlighted region of row
736 if(highlight_letter2 > highlight_letter1 &&
737 highlight_letter2 > row_begin &&
738 highlight_letter1 <= row_end) {
739 if(active && enabled && get_has_focus())
740 set_color(resources->text_highlight);
742 set_color(resources->text_inactive_highlight);
744 if(highlight_letter1 >= row_begin &&
745 highlight_letter1 <= row_end)
746 highlight_x1 = positions[highlight_letter1];
750 if(highlight_letter2 > row_begin &&
751 highlight_letter2 <= row_end)
752 highlight_x2 = positions[highlight_letter2];
754 highlight_x2 = get_w();
756 draw_box(highlight_x1 + text_x, k,
757 highlight_x2 - highlight_x1, text_height);
760 // Draw text over highlight
761 int len = row_end - row_begin;
763 set_color(enabled ? resources->text_default : DMGREY);
764 draw_wtext(text_x, k + text_ascent, wtext_row, len,
765 0, &positions[wtext_row - wtext]);
768 // Get ibeam location
769 if(ibeam_letter >= row_begin && ibeam_letter <= row_end) {
771 ibeam_y = k - text_y;
772 ibeam_x = positions[ibeam_letter];
777 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
779 if( wtext_len == 0 ) {
789 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
799 int BC_TextBox::focus_in_event()
805 int BC_TextBox::focus_out_event()
811 int BC_TextBox::cursor_enter_event()
813 if(top_level->event_win == win && enabled)
827 int BC_TextBox::cursor_leave_event()
839 int BC_TextBox::button_press_event()
843 if(!enabled) return 0;
844 if(get_buttonpress() != WHEEL_UP &&
845 get_buttonpress() != WHEEL_DOWN &&
846 get_buttonpress() != LEFT_BUTTON &&
847 get_buttonpress() != MIDDLE_BUTTON) return 0;
851 if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
853 int cursor_letter = 0;
854 int wtext_len = wtext_update();
855 int update_scroll = 0;
858 if(top_level->event_win == win)
863 top_level->deactivate();
868 if(get_buttonpress() == WHEEL_UP)
870 text_y += text_height;
871 text_y = MIN(text_y, top_margin);
875 if(get_buttonpress() == WHEEL_DOWN)
877 int min_y = -(get_text_rows() *
881 text_y -= text_height;
882 text_y = MAX(text_y, min_y);
883 text_y = MIN(text_y, top_margin);
889 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
891 //printf("BC_TextBox::button_press_event %d %d\n", __LINE__, cursor_letter);
894 if(get_triple_click())
896 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
898 select_line(highlight_letter1, highlight_letter2, cursor_letter);
899 highlight_letter3 = highlight_letter1;
900 highlight_letter4 = highlight_letter2;
901 ibeam_letter = highlight_letter2;
902 copy_selection(PRIMARY_SELECTION);
905 if(get_double_click())
908 select_word(highlight_letter1, highlight_letter2, cursor_letter);
909 highlight_letter3 = highlight_letter1;
910 highlight_letter4 = highlight_letter2;
911 ibeam_letter = highlight_letter2;
912 copy_selection(PRIMARY_SELECTION);
915 if(get_buttonpress() == MIDDLE_BUTTON)
917 highlight_letter3 = highlight_letter4 =
918 ibeam_letter = highlight_letter1 =
919 highlight_letter2 = cursor_letter;
920 paste_selection(PRIMARY_SELECTION);
925 highlight_letter3 = highlight_letter4 =
926 ibeam_letter = highlight_letter1 =
927 highlight_letter2 = cursor_letter;
931 // Handle scrolling by highlighting text
932 if(text_selected || word_selected || line_selected)
934 set_repeat(top_level->get_resources()->scroll_repeat);
937 if(ibeam_letter < 0) ibeam_letter = 0;
938 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
942 if(update_scroll && yscroll)
944 yscroll->update_length(get_text_rows(),
946 yscroll->get_handlelength(),
953 if(active && (!yscroll || !yscroll->is_event_win()))
955 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
956 // Suggestion popup is not active but must be deactivated.
957 if(suggestions_popup)
960 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
961 // // Pass event to suggestions popup
962 // if(!suggestions_popup->button_press_event())
964 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
965 // top_level->deactivate();
970 top_level->deactivate();
978 int BC_TextBox::button_release_event()
983 if(text_selected || word_selected || line_selected)
989 // Stop scrolling by highlighting text
990 unset_repeat(top_level->get_resources()->scroll_repeat);
996 int BC_TextBox::cursor_motion_event()
998 int cursor_letter, letter1, letter2;
1001 if(text_selected || word_selected || line_selected)
1003 cursor_letter = get_cursor_letter(top_level->cursor_x,
1004 top_level->cursor_y);
1006 //printf("BC_TextBox::cursor_motion_event %d cursor_letter=%d\n", __LINE__, cursor_letter);
1010 select_line(letter1, letter2, cursor_letter);
1015 select_word(letter1, letter2, cursor_letter);
1020 letter1 = letter2 = cursor_letter;
1023 if(letter1 <= highlight_letter3)
1025 highlight_letter1 = letter1;
1026 highlight_letter2 = highlight_letter4;
1027 ibeam_letter = letter1;
1030 if(letter2 >= highlight_letter4)
1032 highlight_letter2 = letter2;
1033 highlight_letter1 = highlight_letter3;
1034 ibeam_letter = letter2;
1037 copy_selection(PRIMARY_SELECTION);
1050 int BC_TextBox::activate()
1052 top_level->active_subwindow = this;
1055 top_level->set_repeat(top_level->get_resources()->blink_rate);
1059 int BC_TextBox::deactivate()
1061 //printf("BC_TextBox::deactivate %d suggestions_popup=%p\n", __LINE__, suggestions_popup);
1063 top_level->unset_repeat(top_level->get_resources()->blink_rate);
1064 if(suggestions_popup)
1066 // Must deactivate instead of delete since this is called from BC_ListBox::button_press_event
1067 // suggestions_popup->deactivate();
1069 delete suggestions_popup;
1070 suggestions_popup = 0;
1077 int BC_TextBox::repeat_event(int64_t duration)
1080 int cursor_y = get_cursor_y();
1081 //int cursor_x = get_cursor_x();
1083 if(duration == top_level->get_resources()->tooltip_delay &&
1084 tooltip_text && tooltip_text[0] != 0 && highlighted)
1091 if(duration == top_level->get_resources()->blink_rate &&
1095 // don't flash if keypress
1096 if(skip_cursor->get_difference() < 500)
1098 // printf("BC_TextBox::repeat_event 1 %lld %lld\n",
1099 // skip_cursor->get_difference(),
1105 if(!(text_selected || word_selected || line_selected))
1114 if(duration == top_level->get_resources()->scroll_repeat &&
1115 (text_selected || word_selected || line_selected))
1118 if(get_cursor_y() < top_margin)
1120 difference = get_cursor_y() - top_margin ;
1123 if(get_cursor_y() > get_h() - bottom_margin)
1125 difference = get_cursor_y() -
1126 (get_h() - bottom_margin);
1128 if(difference != 0) {
1129 int min_y = -(get_text_rows() * text_height -
1130 get_h() + bottom_margin);
1132 text_y -= difference;
1133 // printf("BC_TextBox::repeat_event %d %d %d\n",
1137 text_y = MAX(min_y, text_y);
1138 text_y = MIN(text_y, top_margin);
1145 if(get_cursor_x() < left_margin)
1147 int difference = left_margin - get_cursor_x();
1149 text_x += difference;
1150 text_x = MIN(text_x, left_margin);
1154 else if(get_cursor_x() > get_w() - right_margin)
1156 int difference = get_cursor_x() - (get_w() - right_margin);
1157 int new_text_x = text_x - difference;
1159 // Get width of current row
1162 int wtext_len = wtext_update();
1165 for(int i = 0, k = text_y; i < wtext_len; k += text_height)
1168 while(wtext[i] != '\n' && i < wtext_len) {
1172 if(wtext[i] == '\n') i++;
1174 if(cursor_y >= k && cursor_y < k + text_height) {
1175 row_width = get_text_width(font,
1177 row_end - row_begin);
1183 min_x = -row_width + get_w() - left_margin - BCCURSORW;
1184 new_text_x = MAX(new_text_x, min_x);
1185 new_text_x = MIN(new_text_x, left_margin);
1187 if(new_text_x < text_x) text_x = new_text_x;
1196 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
1198 if((top_level->get_keypress() == RETURN) ||
1199 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255))
1202 wchar_t *temp_string = top_level->get_wkeystring(&len);
1203 if(top_level->get_keypress() == RETURN) {
1204 temp_string[0] = '\n'; temp_string[1] = 0;
1207 insert_text(temp_string, len);
1215 int BC_TextBox::keypress_event()
1217 // Result == 2 contents changed
1218 // Result == 1 trapped keypress
1219 // Result == 0 nothing
1221 int dispatch_event = 0;
1223 if(!active || !enabled) return 0;
1225 int wtext_len = wtext_update();
1226 last_keypress = get_keypress();
1227 //printf("BC_TextBox::keypress_event %d %x\n", __LINE__, last_keypress)
1228 switch(last_keypress)
1231 // Deactivate the suggestions
1232 if(suggestions && suggestions_popup)
1234 delete suggestions_popup;
1235 suggestions_popup = 0;
1240 top_level->deactivate();
1252 top_level->deactivate();
1258 default_keypress(dispatch_event, result);
1265 // Handle like a default keypress
1267 top_level->cycle_textboxes(1);
1274 top_level->cycle_textboxes(-1);
1279 if(ibeam_letter > 0)
1281 int old_ibeam_letter = ibeam_letter;
1291 while(ibeam_letter > 0 && isalnum(wtext[ibeam_letter - 1]))
1297 if(top_level->shift_down())
1299 // Initialize highlighting
1300 if(highlight_letter1 == highlight_letter2)
1302 highlight_letter1 = ibeam_letter;
1303 highlight_letter2 = old_ibeam_letter;
1306 // Extend left highlight
1307 if(highlight_letter1 == old_ibeam_letter)
1309 highlight_letter1 = ibeam_letter;
1312 // Shrink right highlight
1313 if(highlight_letter2 == old_ibeam_letter)
1315 highlight_letter2 = ibeam_letter;
1320 highlight_letter1 = highlight_letter2 = ibeam_letter;
1325 if(keypress_draw) draw(1);
1331 if(ibeam_letter < wtext_len)
1333 int old_ibeam_letter = ibeam_letter;
1342 while(ibeam_letter < wtext_len && isalnum(wtext[ibeam_letter++]))
1349 if(top_level->shift_down())
1351 // Initialize highlighting
1352 if(highlight_letter1 == highlight_letter2)
1354 highlight_letter1 = old_ibeam_letter;
1355 highlight_letter2 = ibeam_letter;
1358 // Shrink left highlight
1359 if(highlight_letter1 == old_ibeam_letter)
1361 highlight_letter1 = ibeam_letter;
1364 // Expand right highlight
1365 if(highlight_letter2 == old_ibeam_letter)
1367 highlight_letter2 = ibeam_letter;
1372 highlight_letter1 = highlight_letter2 = ibeam_letter;
1376 if(keypress_draw) draw(1);
1382 if(suggestions && suggestions_popup)
1384 // Pass to suggestions popup
1385 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1386 suggestions_popup->activate(1);
1387 suggestions_popup->keypress_event();
1391 if(ibeam_letter > 0)
1393 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
1394 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1395 ibeam_y + text_y - text_height);
1396 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
1399 if(top_level->shift_down())
1401 // Initialize highlighting
1402 if(highlight_letter1 == highlight_letter2)
1404 highlight_letter1 = new_letter;
1405 highlight_letter2 = ibeam_letter;
1408 // Expand left highlight
1409 if(highlight_letter1 == ibeam_letter)
1411 highlight_letter1 = new_letter;
1414 // Shrink right highlight
1415 if(highlight_letter2 == ibeam_letter)
1417 highlight_letter2 = new_letter;
1421 highlight_letter1 = highlight_letter2 = new_letter;
1423 if(highlight_letter1 > highlight_letter2)
1425 int temp = highlight_letter1;
1426 highlight_letter1 = highlight_letter2;
1427 highlight_letter2 = temp;
1429 ibeam_letter = new_letter;
1432 if(keypress_draw) draw(1);
1438 if(ibeam_letter > 0)
1440 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1441 ibeam_y + text_y - get_h());
1444 if(top_level->shift_down())
1446 // Initialize highlighting
1447 if(highlight_letter1 == highlight_letter2)
1449 highlight_letter1 = new_letter;
1450 highlight_letter2 = ibeam_letter;
1453 // Expand left highlight
1454 if(highlight_letter1 == ibeam_letter)
1456 highlight_letter1 = new_letter;
1459 // Shrink right highlight
1460 if(highlight_letter2 == ibeam_letter)
1462 highlight_letter2 = new_letter;
1466 highlight_letter1 = highlight_letter2 = new_letter;
1468 if(highlight_letter1 > highlight_letter2)
1470 int temp = highlight_letter1;
1471 highlight_letter1 = highlight_letter2;
1472 highlight_letter2 = temp;
1474 ibeam_letter = new_letter;
1477 if(keypress_draw) draw(1);
1483 // printf("BC_TextBox::keypress_event %d %p %p\n",
1486 // suggestions_popup);
1487 if(suggestions && suggestions_popup)
1489 // Pass to suggestions popup
1490 suggestions_popup->activate(1);
1491 suggestions_popup->keypress_event();
1495 // if(ibeam_letter > 0)
1498 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1499 ibeam_y + text_y + text_height);
1500 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1502 if(top_level->shift_down())
1504 // Initialize highlighting
1505 if(highlight_letter1 == highlight_letter2)
1507 highlight_letter1 = new_letter;
1508 highlight_letter2 = ibeam_letter;
1511 // Shrink left highlight
1512 if(highlight_letter1 == ibeam_letter)
1514 highlight_letter1 = new_letter;
1517 // Expand right highlight
1518 if(highlight_letter2 == ibeam_letter)
1520 highlight_letter2 = new_letter;
1524 highlight_letter1 = highlight_letter2 = new_letter;
1526 if(highlight_letter1 > highlight_letter2)
1528 int temp = highlight_letter1;
1529 highlight_letter1 = highlight_letter2;
1530 highlight_letter2 = temp;
1532 ibeam_letter = new_letter;
1535 if(keypress_draw) draw(1);
1537 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1545 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1546 ibeam_y + text_y + get_h());
1547 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1549 if(top_level->shift_down())
1551 // Initialize highlighting
1552 if(highlight_letter1 == highlight_letter2)
1554 highlight_letter1 = new_letter;
1555 highlight_letter2 = ibeam_letter;
1558 // Shrink left highlight
1559 if(highlight_letter1 == ibeam_letter)
1561 highlight_letter1 = new_letter;
1564 // Expand right highlight
1565 if(highlight_letter2 == ibeam_letter)
1567 highlight_letter2 = new_letter;
1571 highlight_letter1 = highlight_letter2 = new_letter;
1573 if(highlight_letter1 > highlight_letter2)
1575 int temp = highlight_letter1;
1576 highlight_letter1 = highlight_letter2;
1577 highlight_letter2 = temp;
1579 ibeam_letter = new_letter;
1582 if(keypress_draw) draw(1);
1584 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1591 delete suggestions_popup;
1592 suggestions_popup = 0;
1594 int old_ibeam_letter = ibeam_letter;
1596 while(ibeam_letter < wtext_len && wtext[ibeam_letter] != '\n')
1599 if(top_level->shift_down())
1602 if(highlight_letter1 == highlight_letter2)
1604 highlight_letter2 = ibeam_letter;
1605 highlight_letter1 = old_ibeam_letter;
1609 if(highlight_letter1 == old_ibeam_letter)
1611 highlight_letter1 = highlight_letter2;
1612 highlight_letter2 = ibeam_letter;
1616 if(highlight_letter2 == old_ibeam_letter)
1618 highlight_letter2 = ibeam_letter;
1622 highlight_letter1 = highlight_letter2 = ibeam_letter;
1625 if(keypress_draw) draw(1);
1632 delete suggestions_popup;
1633 suggestions_popup = 0;
1635 int old_ibeam_letter = ibeam_letter;
1637 while(ibeam_letter > 0 && wtext[ibeam_letter - 1] != '\n')
1640 if(top_level->shift_down())
1643 if(highlight_letter1 == highlight_letter2)
1645 highlight_letter2 = old_ibeam_letter;
1646 highlight_letter1 = ibeam_letter;
1650 if(highlight_letter1 == old_ibeam_letter)
1652 highlight_letter1 = ibeam_letter;
1656 if(highlight_letter2 == old_ibeam_letter)
1658 highlight_letter2 = highlight_letter1;
1659 highlight_letter1 = ibeam_letter;
1663 highlight_letter1 = highlight_letter2 = ibeam_letter;
1666 if(keypress_draw) draw(1);
1672 if(suggestions_popup)
1674 delete suggestions_popup;
1675 suggestions_popup = 0;
1678 if(highlight_letter1 == highlight_letter2)
1680 if(ibeam_letter > 0)
1682 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1688 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1689 highlight_letter2 = ibeam_letter = highlight_letter1;
1693 if(keypress_draw) draw(1);
1699 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1700 if(highlight_letter1 == highlight_letter2)
1702 if(ibeam_letter < wtext_len)
1704 delete_selection(ibeam_letter, ibeam_letter + 1, wtext_len);
1709 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1710 highlight_letter2 = ibeam_letter = highlight_letter1;
1714 if(keypress_draw) draw(1);
1724 if(get_keypress() == 'c' || get_keypress() == 'C')
1726 if(highlight_letter1 != highlight_letter2)
1728 copy_selection(SECONDARY_SELECTION);
1733 if(get_keypress() == 'v' || get_keypress() == 'V')
1735 paste_selection(SECONDARY_SELECTION);
1737 if(keypress_draw) draw(1);
1742 if(get_keypress() == 'x' || get_keypress() == 'X')
1744 if(highlight_letter1 != highlight_letter2)
1746 copy_selection(SECONDARY_SELECTION);
1747 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1748 highlight_letter2 = ibeam_letter = highlight_letter1;
1752 if(keypress_draw) draw(1);
1760 default_keypress(dispatch_event, result);
1764 if(result) skip_cursor->update();
1765 if(dispatch_event && handle_event())
1772 int BC_TextBox::uses_text()
1778 void BC_TextBox::delete_selection(int letter1, int letter2, int wtext_len)
1781 for(i=letter1, j=letter2; j<wtext_len; i++, j++) {
1782 wtext[i] = wtext[j];
1790 void BC_TextBox::insert_text(const wchar_t *wcp, int len)
1792 if( len < 0 ) len = wcslen(wcp);
1793 int wtext_len = wtext_update();
1794 if(highlight_letter1 < highlight_letter2)
1796 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1797 highlight_letter2 = ibeam_letter = highlight_letter1;
1798 wtext_len = wtext_update();
1803 for(i=wtext_len-1, j=wtext_len+len-1; i>=ibeam_letter; i--, j--) {
1804 if( j >= wsize ) continue;
1805 wtext[j] = wtext[i];
1808 for(i = ibeam_letter, j = 0; j < len; j++, i++) {
1809 if( i >= wsize ) break;
1812 if( (wlen+=len) > wsize ) wlen = wsize;
1813 if( (ibeam_letter+=len) > wsize ) ibeam_letter = wsize;
1814 wtext[wlen] = 0; // wtext allocated wsize+1
1818 int BC_TextBox::is_separator(const char *txt, int i)
1820 if( i != 0 || separators[0] != '+' ) return !isalnum(txt[i]);
1821 return txt[0] != '+' && txt[0] != '-' && !isalnum(txt[0]);
1824 // used for time entry
1825 void BC_TextBox::do_separators(int ibeam_left)
1829 // Remove separators from text
1830 int wtext_len = wtext_update();
1831 for(int i = 0; i < wtext_len; ) {
1832 if( !iswalnum(wtext[i]) ) {
1833 for(int j = i; j < wtext_len - 1; j++)
1834 wtext[j] = wtext[j + 1];
1835 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1841 wtext[wtext_len] = 0;
1847 // Insert separators into text
1848 int separator_len = strlen(separators);
1849 for(int i = 0; i < separator_len; i++) {
1851 // Insert a separator
1852 if( is_separator(separators,i) ) {
1853 for(int j = wtext_len; j >= i; j--) {
1854 wtext[j + 1] = wtext[j];
1856 if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1858 wtext[i] = separators[i];
1862 wtext[i] = separators[i];
1867 wtext[separator_len] = 0;
1868 wlen = separator_len;
1872 void BC_TextBox::get_ibeam_position(int &x, int &y)
1874 int i, row_begin, row_end;
1875 int wtext_len = wtext_update();
1879 for( i=0; i<wtext_len; ) {
1881 for(; i<wtext_len && wtext[i]!='\n'; i++);
1884 if( ibeam_letter >= row_begin && ibeam_letter <= row_end ) {
1885 x = get_text_width(font, &wtext[row_begin], ibeam_letter - row_begin);
1886 //printf("BC_TextBox::get_ibeam_position %d %d %d %d %d\n", ibeam_letter, row_begin, row_end, x, y);
1890 if( i < wtext_len && wtext[i] == '\n' ) {
1895 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1901 void BC_TextBox::set_text_row(int row)
1903 text_x = left_margin;
1904 text_y = -(row * text_height) + top_margin;
1908 int BC_TextBox::get_text_row()
1910 return -(text_y - top_margin) / text_height;
1913 void BC_TextBox::find_ibeam(int dispatch_event)
1916 int old_x = text_x, old_y = text_y;
1918 get_ibeam_position(x, y);
1920 if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1922 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1923 if(text_x > left_margin) text_x = left_margin;
1926 if(left_margin + text_x + x < left_margin)
1928 text_x = -(x - (get_w() / 4)) + left_margin;
1929 if(text_x > left_margin) text_x = left_margin;
1932 int text_row = y / text_height;
1933 if( text_row < rows ) text_y = top_margin;
1935 int pix_rows = get_h() - bottom_margin - (y + text_y);
1936 if( pix_rows < text_height )
1937 text_y -= text_height * ((2*text_height-1-pix_rows) / text_height);
1939 pix_rows = y + text_y - top_margin;
1940 if( pix_rows < 0 ) {
1941 text_y += text_height * ((text_height-1-pix_rows) / text_height);
1942 if( text_y > top_margin ) text_y = top_margin;
1945 if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1949 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1951 int i, j, k, row_begin, row_end, result = 0, done = 0;
1952 int column1, column2;
1953 int got_visible_row = 0;
1955 // Select complete row if cursor above the window
1956 //printf("BC_TextBox::get_cursor_letter %d %d\n", __LINE__, text_y);
1957 if(cursor_y < text_y - text_height)
1963 int wtext_len = wtext_update();
1965 for(i=0, k=text_y; i<wtext_len && k<get_h() && !done; k+=text_height) {
1966 // Simulate drawing of 1 row
1968 for(j = 0; wtext[i]!='\n' && i<wtext_len; i++);
1972 int first_visible_row = 0;
1973 int last_visible_row = 0;
1974 if( k+text_height > top_margin && !got_visible_row) {
1975 first_visible_row = 1;
1976 got_visible_row = 1;
1979 if( (k+text_height >= get_h() - bottom_margin ||
1980 (row_end >= wtext_len && k < get_h() - bottom_margin &&
1981 k + text_height > 0)) )
1982 last_visible_row = 1;
1984 // Cursor is inside vertical range of row
1985 if((cursor_y >= top_margin &&
1986 cursor_y < get_h() - bottom_margin &&
1987 cursor_y >= k && cursor_y < k + text_height) ||
1988 // Cursor is above 1st row
1989 (cursor_y < k + text_height && first_visible_row) ||
1990 // Cursor is below last row
1991 (cursor_y >= k && last_visible_row))
1993 column1 = column2 = 0;
1994 for(j = row_begin; j<wsize && j<=row_end && !done; j++) {
1995 column2 = get_text_width(font, &wtext[row_begin], j-row_begin) + text_x;
1996 if((column2 + column1) / 2 >= cursor_x) {
1999 // printf("BC_TextBox::get_cursor_letter %d %d %d %d\n",
2000 // __LINE__, result, first_visible_row, last_visible_row);
2011 if(wtext[i] == '\n') i++;
2013 // Select complete row if last visible & cursor is below window
2014 if(last_visible_row && cursor_y > k + text_height * 2)
2017 if(i >= wtext_len && !done) {
2023 // printf("BC_TextBox::get_cursor_letter %d cursor_y=%d k=%d h=%d %d %d\n",
2024 // __LINE__, cursor_y, k, get_h(), first_visible_row, last_visible_row);
2025 if(result < 0) result = 0;
2026 if(result > wtext_len) {
2027 //printf("BC_TextBox::get_cursor_letter %d\n", __LINE__);
2035 int BC_TextBox::get_cursor_letter2(int cursor_x, int cursor_y)
2037 int i, j, k, row_begin, row_end, result = 0, done = 0;
2038 int column1, column2;
2039 int wtext_len = wtext_update();
2041 if(cursor_y < text_y) {
2046 for(i = 0, k = text_y; i < wtext_len && !done; k += text_height) {
2048 for(; wtext[i] != '\n' && i < wtext_len; i++);
2051 if(cursor_y >= k && cursor_y < k + text_height) {
2052 column1 = column2 = 0;
2053 for(j = 0; j <= row_end - row_begin && !done; j++) {
2054 column2 = get_text_width(font, &wtext[row_begin], j) + text_x;
2055 if((column2 + column1) / 2 >= cursor_x) {
2056 result = row_begin + j - 1;
2067 if(wtext[i] == '\n') i++;
2069 if(i >= wtext_len && !done) {
2073 if(result < 0) result = 0;
2074 if(result > wtext_len) result = wtext_len;
2079 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
2081 int wtext_len = wtext_update();
2082 if(!wtext_len) return;
2084 letter1 = letter2 = ibeam_letter;
2086 if(iswalnum(wtext[letter1])) letter1--;
2087 } while(letter1 > 0 && iswalnum(wtext[letter1]));
2089 if( !iswalnum(wtext[letter1]) ) letter1++;
2092 if( iswalnum(wtext[letter2]) ) letter2++;
2093 } while( letter2 < wtext_len && isalnum(wtext[letter2]) );
2095 if( letter2 < wtext_len && wtext[letter2] == ' ') letter2++;
2097 if(letter1 < 0) letter1 = 0;
2098 if(letter2 < 0) letter2 = 0;
2099 if(letter1 > wtext_len) letter1 = wtext_len;
2100 if(letter2 > wtext_len) letter2 = wtext_len;
2103 void BC_TextBox::select_line(int &letter1, int &letter2, int ibeam_letter)
2105 int wtext_len = wtext_update();
2106 if(!wtext_len) return;
2108 letter1 = letter2 = ibeam_letter;
2110 // Rewind to previous linefeed
2112 if( wtext[letter1] != '\n' ) letter1--;
2113 } while( letter1 > 0 && wtext[letter1] != '\n' );
2114 if( wtext[letter1] == '\n' ) letter1++;
2116 // Advance to next linefeed
2118 if( wtext[letter2] != '\n' ) letter2++;
2119 } while( letter2 < wtext_len && wtext[letter2] != '\n' );
2120 if( letter2 < wtext_len && wtext[letter2] == '\n') letter2++;
2122 if(letter1 < 0) letter1 = 0;
2123 if(letter2 < 0) letter2 = 0;
2124 if(letter1 > wtext_len) letter1 = wtext_len;
2125 if(letter2 > wtext_len) letter2 = wtext_len;
2128 void BC_TextBox::copy_selection(int clipboard_num)
2130 int wtext_len = wtext_update();
2131 if(!wtext_len) return;
2133 if(highlight_letter1 >= wtext_len || highlight_letter2 > wtext_len ||
2134 highlight_letter1 < 0 || highlight_letter2 < 0 ||
2135 highlight_letter2 - highlight_letter1 <= 0) return;
2136 int clip_len = highlight_letter2 - highlight_letter1;
2137 char ctext[clip_len+1];
2138 //printf(" BC_TextBox::copy_selection %d %d %d\n",highlight_letter1, highlight_letter2, clip_len);
2139 text_update(&wtext[highlight_letter1],clip_len, ctext,clip_len+1);
2140 get_clipboard()->to_clipboard(ctext, clip_len, clipboard_num);
2144 void BC_TextBox::paste_selection(int clipboard_num)
2146 int len = get_clipboard()->clipboard_len(clipboard_num);
2149 char cstring[len]; wchar_t wstring[len]; --len;
2150 get_clipboard()->from_clipboard(cstring, len, clipboard_num);
2151 //printf("BC_TextBox::paste_selection %d '%*.*s'\n",len,len,len,cstring);
2152 BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
2153 cstring,(len+1), (char *)wstring,(len+1)*sizeof(wchar_t));
2154 insert_text(wstring, len);
2158 void BC_TextBox::set_keypress_draw(int value)
2160 keypress_draw = value;
2163 int BC_TextBox::get_last_keypress()
2165 return last_keypress;
2168 int BC_TextBox::get_ibeam_letter()
2170 return ibeam_letter;
2173 void BC_TextBox::set_ibeam_letter(int number, int redraw)
2175 this->ibeam_letter = number;
2182 void BC_TextBox::set_separators(const char *separators)
2184 this->separators = (char*)separators;
2187 int BC_TextBox::get_rows()
2198 BC_TextBoxSuggestions::BC_TextBoxSuggestions(BC_TextBox *text_box,
2206 text_box->suggestions,
2213 this->text_box = text_box;
2215 set_justify(LISTBOX_LEFT);
2218 BC_TextBoxSuggestions::~BC_TextBoxSuggestions()
2222 int BC_TextBoxSuggestions::selection_changed()
2225 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2226 BC_ListBoxItem *item = get_selection(0, 0);
2227 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2231 char *current_suggestion = item->get_text();
2232 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2233 // int text_box_len = strlen(text_box->text);
2234 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2235 strcpy(text_box->text + text_box->suggestion_column, current_suggestion);
2236 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2237 *(text_box->text + text_box->suggestion_column + strlen(current_suggestion)) = 0;
2239 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2241 text_box->handle_event();
2251 int BC_TextBoxSuggestions::handle_event()
2253 char *current_suggestion = 0;
2254 BC_ListBoxItem *item = get_selection(0, 0);
2255 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2256 if(item && (current_suggestion=item->get_text()) != 0)
2258 int col = text_box->suggestion_column;
2259 int len = BCTEXTLEN-1 - col;
2260 char *cp = &text_box->text[col];
2261 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2262 strncpy(cp, current_suggestion, len);
2263 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2264 if( (col=strlen(current_suggestion)) >= len )
2266 text_box->dirty = 1;
2270 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2271 text_box->highlight_letter1 =
2272 text_box->highlight_letter2 =
2273 text_box->ibeam_letter = text_box->tstrlen();
2274 text_box->wtext_update();
2276 text_box->handle_event();
2277 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2282 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2283 int x, int y, int w, int rows,
2284 const char *default_text, int default_size)
2286 this->parent_window = parent_window;
2291 this->default_text = default_text;
2292 this->default_wtext = 0;
2293 this->default_size = default_size;
2296 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2297 int x, int y, int w, int rows,
2298 const wchar_t *default_wtext, int default_size)
2300 this->parent_window = parent_window;
2305 this->default_text = 0;
2306 this->default_wtext = default_wtext;
2307 this->default_size = default_size;
2310 BC_ScrollTextBox::~BC_ScrollTextBox()
2319 void BC_ScrollTextBox::create_objects()
2321 // Must be created first
2322 parent_window->add_subwindow(text = default_wtext ?
2323 new BC_ScrollTextBoxText(this, default_wtext) :
2324 new BC_ScrollTextBoxText(this, default_text));
2325 parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
2326 text->yscroll = yscroll;
2327 yscroll->bound_to = text;
2331 int BC_ScrollTextBox::handle_event()
2336 int BC_ScrollTextBox::get_x()
2341 int BC_ScrollTextBox::get_y()
2346 int BC_ScrollTextBox::get_w()
2351 int BC_ScrollTextBox::get_h()
2353 return this->text->get_h();
2356 int BC_ScrollTextBox::get_rows()
2362 const char* BC_ScrollTextBox::get_text()
2364 return text->get_text();
2367 const wchar_t* BC_ScrollTextBox::get_wtext()
2369 return text->get_wtext();
2372 void BC_ScrollTextBox::set_text(char *text, int isz)
2374 this->text->set_text(text, isz);
2375 yscroll->update_length(this->text->get_text_rows(),
2376 this->text->get_text_row(),
2377 yscroll->get_handlelength(),
2381 int BC_ScrollTextBox::set_text_row(int n)
2383 text->set_text_row(n);
2384 yscroll->update_value(n);
2388 void BC_ScrollTextBox::update(const char *text)
2390 this->text->update(text);
2391 yscroll->update_length(this->text->get_text_rows(),
2392 this->text->get_text_row(),
2393 yscroll->get_handlelength(),
2397 void BC_ScrollTextBox::update(const wchar_t *wtext)
2399 this->text->update(wtext);
2400 yscroll->update_length(this->text->get_text_rows(),
2401 this->text->get_text_row(),
2402 yscroll->get_handlelength(),
2406 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
2413 text->reposition_window(x,
2415 w - yscroll->get_span(),
2417 yscroll->reposition_window(x + w - yscroll->get_span(),
2419 BC_TextBox::calculate_row_h(rows,
2421 yscroll->update_length(text->get_text_rows(),
2422 text->get_text_row(),
2427 void BC_ScrollTextBox::set_selection(int char1, int char2, int ibeam)
2429 this->text->set_selection(char1, char2, ibeam);
2432 void BC_ScrollTextBox::wset_selection(int char1, int char2, int ibeam)
2434 this->text->wset_selection(char1, char2, ibeam);
2443 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const char *text)
2444 : BC_TextBox(gui->x, gui->y,
2445 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2446 gui->rows, gui->default_size, (char*)text, 1, MEDIUMFONT)
2451 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const wchar_t *wtext)
2452 : BC_TextBox(gui->x, gui->y,
2453 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2454 gui->rows, gui->default_size, (wchar_t*)wtext, 1, MEDIUMFONT)
2459 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
2468 int BC_ScrollTextBoxText::handle_event()
2470 gui->yscroll->update_length(get_text_rows(),
2472 gui->yscroll->get_handlelength(),
2474 return gui->handle_event();
2477 int BC_ScrollTextBoxText::motion_event()
2479 gui->yscroll->update_length(get_text_rows(),
2481 gui->yscroll->get_handlelength(),
2487 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
2488 : BC_ScrollBar(gui->x +
2490 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2493 BC_TextBox::calculate_row_h(gui->rows,
2494 gui->parent_window),
2495 gui->text->get_text_rows(),
2502 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
2506 int BC_ScrollTextBoxYScroll::handle_event()
2508 gui->text->set_text_row(get_position());
2521 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const char *text)
2522 : BC_TextBox(x, y, popup->text_w, 1, text, BCTEXTLEN)
2524 this->popup = popup;
2527 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const wchar_t *wtext)
2528 : BC_TextBox(x, y, popup->text_w, 1, wtext, BCTEXTLEN)
2530 this->popup = popup;
2533 BC_PopupTextBoxText::~BC_PopupTextBoxText()
2543 int BC_PopupTextBoxText::handle_event()
2545 popup->handle_event();
2549 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
2551 popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
2552 popup->list_h, popup->list_format, popup->list_items, 0, 0, 1, 0, 1)
2554 this->popup = popup;
2556 int BC_PopupTextBoxList::handle_event()
2558 BC_ListBoxItem *item = get_selection(0, 0);
2561 popup->textbox->update(item->get_text());
2562 popup->handle_event();
2570 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window,
2571 ArrayList<BC_ListBoxItem*> *list_items,
2572 const char *default_text, int x, int y,
2573 int text_w, int list_h, int list_format)
2577 this->list_h = list_h;
2578 this->list_format = list_format;
2579 this->default_text = (char*)default_text;
2580 this->default_wtext = 0;
2581 this->text_w = text_w;
2582 this->parent_window = parent_window;
2583 this->list_items = list_items;
2586 BC_PopupTextBox::~BC_PopupTextBox()
2596 int BC_PopupTextBox::create_objects()
2598 int x = this->x, y = this->y;
2599 parent_window->add_subwindow(textbox = default_wtext ?
2600 new BC_PopupTextBoxText(this, x, y, default_wtext) :
2601 new BC_PopupTextBoxText(this, x, y, default_text));
2602 x += textbox->get_w();
2603 parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
2607 void BC_PopupTextBox::update(const char *text)
2609 textbox->update(text);
2612 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
2614 listbox->update(data,
2621 const char* BC_PopupTextBox::get_text()
2623 return textbox->get_text();
2626 const wchar_t* BC_PopupTextBox::get_wtext()
2628 return textbox->get_wtext();
2631 int BC_PopupTextBox::get_number()
2633 return listbox->get_selection_number(0, 0);
2636 int BC_PopupTextBox::get_x()
2641 int BC_PopupTextBox::get_y()
2646 int BC_PopupTextBox::get_w()
2648 return textbox->get_w() + listbox->get_w();
2651 int BC_PopupTextBox::get_h()
2653 return textbox->get_h();
2656 int BC_PopupTextBox::handle_event()
2661 void BC_PopupTextBox::reposition_window(int x, int y)
2666 textbox->reposition_window(x1,
2669 textbox->get_rows());
2670 x1 += textbox->get_w();
2671 listbox->reposition_window(x1, y1, -1, -1, 0);
2672 // if(flush) parent_window->flush();
2688 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2689 int64_t default_value,
2694 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2696 this->popup = popup;
2699 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2700 float default_value,
2705 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2707 this->popup = popup;
2710 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
2722 int BC_TumbleTextBoxText::handle_event()
2724 popup->handle_event();
2728 int BC_TumbleTextBoxText::button_press_event()
2732 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
2734 if(get_buttonpress() == 4)
2736 popup->tumbler->handle_up_event();
2739 if(get_buttonpress() == 5)
2741 popup->tumbler->handle_down_event();
2751 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2752 int64_t default_value,
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,
2785 this->default_value = default_value;
2786 this->text_w = text_w;
2787 this->parent_window = parent_window;
2793 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2794 float default_value_f,
2804 this->min_f = min_f;
2805 this->max_f = max_f;
2806 this->default_value_f = default_value_f;
2807 this->text_w = text_w;
2808 this->parent_window = parent_window;
2814 BC_TumbleTextBox::~BC_TumbleTextBox()
2816 // Recursive delete. Normally ~BC_TumbleTextBox is never called but textbox
2817 // is deleted anyway by the windowbase so textbox deletes this.
2818 if(tumbler) delete tumbler;
2820 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
2829 void BC_TumbleTextBox::reset()
2836 void BC_TumbleTextBox::set_precision(int precision)
2838 this->precision = precision;
2841 void BC_TumbleTextBox::set_increment(float value)
2843 this->increment = value;
2844 if(tumbler) tumbler->set_increment(value);
2847 void BC_TumbleTextBox::set_log_floatincrement(int value)
2849 this->log_floatincrement = value;
2850 if(tumbler) tumbler->set_log_floatincrement(value);
2853 int BC_TumbleTextBox::create_objects()
2855 int x = this->x, y = this->y;
2859 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2865 textbox->set_precision(precision);
2868 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2875 x += textbox->get_w();
2878 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox,
2884 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox,
2890 tumbler->set_increment(increment);
2894 const char* BC_TumbleTextBox::get_text()
2896 return textbox->get_text();
2899 const wchar_t* BC_TumbleTextBox::get_wtext()
2901 return textbox->get_wtext();
2904 BC_TextBox* BC_TumbleTextBox::get_textbox()
2909 int BC_TumbleTextBox::update(const char *value)
2911 textbox->update(value);
2915 int BC_TumbleTextBox::update(int64_t value)
2917 textbox->update(value);
2921 int BC_TumbleTextBox::update(float value)
2923 textbox->update(value);
2928 int BC_TumbleTextBox::get_x()
2933 int BC_TumbleTextBox::get_y()
2938 int BC_TumbleTextBox::get_w()
2940 return textbox->get_w() + tumbler->get_w();
2943 int BC_TumbleTextBox::get_h()
2945 return textbox->get_h();
2948 void BC_TumbleTextBox::disable()
2950 if( !get_enabled() ) return;
2951 tumbler->hide_window(0);
2952 return textbox->disable();
2955 void BC_TumbleTextBox::enable()
2957 if( get_enabled() ) return;
2958 tumbler->show_window(0);
2959 return textbox->enable();
2962 int BC_TumbleTextBox::get_enabled()
2964 return textbox->get_enabled();
2967 int BC_TumbleTextBox::handle_event()
2972 void BC_TumbleTextBox::reposition_window(int x, int y)
2977 textbox->reposition_window(x,
2981 tumbler->reposition_window(x + textbox->get_w(),
2983 // if(flush) parent_window->flush();
2987 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2989 tumbler->set_boundaries(min, max);
2992 void BC_TumbleTextBox::set_boundaries(float min, float max)
2994 tumbler->set_boundaries(min, max);