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;
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::wset_selection(int char1, int char2, int ibeam)
481 highlight_letter1 = char1;
482 highlight_letter2 = char2;
483 ibeam_letter = ibeam;
487 // count utf8 chars in text which occur before cp
488 int BC_TextBox::wcpos(const char *text, const char *cp)
491 const unsigned char *bp = (const unsigned char *)text;
492 const unsigned char *ep = (const unsigned char *)cp;
493 while( bp < ep && *bp != 0 ) {
496 if( ch < 0x80 ) continue;
498 int n = i<0? 0 : i<32? 1 : i<48? 2 : i<56? 3 : i<60? 4 : 5;
499 for( i=n; bp < ep && --i>=0 && (*bp&0xc0) == 0x80; ++bp );
504 void BC_TextBox::set_selection(int char1, int char2, int ibeam)
506 const char *cp = get_text();
507 wset_selection(wcpos(cp, cp+char1), wcpos(cp, cp+char2), wcpos(cp, cp+ibeam));
510 int BC_TextBox::update(const char *text)
512 //printf("BC_TextBox::update 1 %d %s %s\n", tstrcmp(text), text, this->text);
513 // Don't update if contents are the same
514 if(!tstrcmp(text)) return 0;
516 int wtext_len = wtext_update();
517 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
518 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
519 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
524 int BC_TextBox::update(const wchar_t *wtext)
526 int wtext_len = wcslen(wtext);
527 if( wtext_len >= wsize ) wtext_len = wsize;
528 wcsncpy(this->wtext, wtext, wtext_len);
530 if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
531 if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
532 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
537 int BC_TextBox::update(int64_t value)
539 char string[BCTEXTLEN];
540 sprintf(string, "%jd", value);
545 int BC_TextBox::update(float value)
547 char string[BCTEXTLEN];
548 sprintf(string, "%0.*f", precision, value);
553 void BC_TextBox::disable()
558 if(active) top_level->deactivate();
564 void BC_TextBox::enable()
574 int BC_TextBox::get_enabled()
579 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
581 return (pixels - 4) /
582 (window->get_text_ascent(font) + 1 +
583 window->get_text_descent(font) + 1);
586 int BC_TextBox::calculate_row_h(int rows,
587 BC_WindowBase *parent_window,
592 (parent_window->get_text_ascent(font) + 1 +
593 parent_window->get_text_descent(font) + 1) +
594 (has_border ? 4 : 0);
597 const char* BC_TextBox::get_text()
599 int wtext_len = wtext_update();
600 text_update(wtext,wtext_len, text,tsize);
604 const wchar_t* BC_TextBox::get_wtext()
610 void BC_TextBox::set_text(char *text, int isz)
612 if( size > 0 || isz < 0 ) return;
621 int BC_TextBox::get_text_rows()
623 int wtext_len = wtext_update();
625 for(int i = 0; i < wtext_len; i++) {
626 if(wtext[i] == '\n') result++;
632 int BC_TextBox::get_row_h(int rows)
634 return rows * text_height + top_margin + bottom_margin;
637 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
640 if(w < 0) w = get_w();
643 new_h = get_row_h(rows);
652 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
653 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
654 BC_WindowBase::reposition_window(x, y, w, new_h);
660 void BC_TextBox::draw_border()
662 BC_Resources *resources = get_resources();
664 set_color(background_color);
665 draw_box(0, 0, left_margin, get_h());
666 draw_box(get_w() - right_margin, 0, right_margin, get_h());
671 draw_3d_border(0, 0, w, h,
672 resources->text_border1,
673 resources->text_border2_hi,
674 resources->text_border3_hi,
675 resources->text_border4);
677 draw_3d_border(0, 0, w, h,
678 resources->text_border1,
679 resources->text_border2,
680 resources->text_border3,
681 resources->text_border4);
685 void BC_TextBox::draw_cursor()
687 // set_color(background_color);
695 draw_box(ibeam_x + text_x,
704 void BC_TextBox::draw(int flush)
707 int row_begin, row_end;
708 int highlight_x1, highlight_x2;
710 BC_Resources *resources = get_resources();
712 //printf("BC_TextBox::draw %d %s\n", __LINE__, text);
715 background_color = resources->text_background;
717 background_color = high_color;
719 background_color = back_color;
720 set_color(background_color);
721 draw_box(0, 0, w, h);
723 int wtext_len = wtext_update();
725 // Draw text with selection
728 for(i=0, j=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
731 wchar_t *wtext_row = &wtext[i];
732 for(j=0; j<BCTEXTLEN-1 && i<wtext_len && wtext[i]!='\n'; ++i, ++j);
733 if( (row_end=i) < wtext_len ) ++i;
735 if(k > top_margin-text_height && k < get_h()-bottom_margin) {
736 // Draw highlighted region of row
737 if( highlight_letter2 > highlight_letter1 &&
738 highlight_letter2 > row_begin &&
739 highlight_letter1 <= row_end ) {
740 int color = active && enabled && get_has_focus() ?
741 resources->text_highlight :
742 resources->text_inactive_highlight;
743 if( unicode_active >= 0 )
746 if(highlight_letter1 >= row_begin &&
747 highlight_letter1 <= row_end)
748 highlight_x1 = positions[highlight_letter1];
752 if(highlight_letter2 > row_begin &&
753 highlight_letter2 <= row_end)
754 highlight_x2 = positions[highlight_letter2];
756 highlight_x2 = get_w();
758 draw_box(highlight_x1 + text_x, k,
759 highlight_x2 - highlight_x1, text_height);
762 // Draw text over highlight
763 int len = row_end - row_begin;
765 set_color(enabled ? resources->text_default : DMGREY);
766 draw_wtext(text_x, k + text_ascent, wtext_row, len,
767 0, &positions[wtext_row - wtext]);
770 positions[wtext_row - wtext] = 0;
772 // Get ibeam location
773 if(ibeam_letter >= row_begin && ibeam_letter <= row_end) {
775 ibeam_y = k - text_y;
776 ibeam_x = positions[ibeam_letter];
781 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
783 // ibeam_x = ibeam_y = !wtext_len ? 0 : -1;
784 ibeam_x = 0; ibeam_y = k - text_y;
787 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
797 int BC_TextBox::focus_in_event()
803 int BC_TextBox::focus_out_event()
809 int BC_TextBox::cursor_enter_event()
811 if(top_level->event_win == win && enabled)
825 int BC_TextBox::cursor_leave_event()
837 int BC_TextBox::button_press_event()
841 if(!enabled) return 0;
842 if(get_buttonpress() != WHEEL_UP &&
843 get_buttonpress() != WHEEL_DOWN &&
844 get_buttonpress() != LEFT_BUTTON &&
845 get_buttonpress() != MIDDLE_BUTTON) return 0;
849 if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
851 int cursor_letter = 0;
852 int wtext_len = wtext_update();
853 int update_scroll = 0;
856 if(top_level->event_win == win)
861 top_level->deactivate();
866 if(get_buttonpress() == WHEEL_UP)
868 text_y += text_height;
869 text_y = MIN(text_y, top_margin);
873 if(get_buttonpress() == WHEEL_DOWN)
875 int min_y = -(get_text_rows() *
879 text_y -= text_height;
880 text_y = MAX(text_y, min_y);
881 text_y = MIN(text_y, top_margin);
887 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
889 //printf("BC_TextBox::button_press_event %d %d\n", __LINE__, cursor_letter);
892 if(get_triple_click())
894 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
896 select_line(highlight_letter1, highlight_letter2, cursor_letter);
897 highlight_letter3 = highlight_letter1;
898 highlight_letter4 = highlight_letter2;
899 ibeam_letter = highlight_letter2;
900 copy_selection(PRIMARY_SELECTION);
903 if(get_double_click())
906 select_word(highlight_letter1, highlight_letter2, cursor_letter);
907 highlight_letter3 = highlight_letter1;
908 highlight_letter4 = highlight_letter2;
909 ibeam_letter = highlight_letter2;
910 copy_selection(PRIMARY_SELECTION);
913 if(get_buttonpress() == MIDDLE_BUTTON)
915 highlight_letter3 = highlight_letter4 =
916 ibeam_letter = highlight_letter1 =
917 highlight_letter2 = cursor_letter;
918 paste_selection(PRIMARY_SELECTION);
923 highlight_letter3 = highlight_letter4 =
924 ibeam_letter = highlight_letter1 =
925 highlight_letter2 = cursor_letter;
929 // Handle scrolling by highlighting text
930 if(text_selected || word_selected || line_selected)
932 set_repeat(top_level->get_resources()->scroll_repeat);
935 if(ibeam_letter < 0) ibeam_letter = 0;
936 if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
940 if(update_scroll && yscroll)
942 yscroll->update_length(get_text_rows(),
944 yscroll->get_handlelength(),
951 if(active && (!yscroll || !yscroll->is_event_win()))
953 //printf("BC_TextBox::button_press_event %d\n", __LINE__);
954 // Suggestion popup is not active but must be deactivated.
955 if(suggestions_popup)
958 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
959 // // Pass event to suggestions popup
960 // if(!suggestions_popup->button_press_event())
962 // printf("BC_TextBox::button_press_event %d\n", __LINE__);
963 // top_level->deactivate();
968 top_level->deactivate();
976 int BC_TextBox::button_release_event()
981 if(text_selected || word_selected || line_selected)
987 // Stop scrolling by highlighting text
988 unset_repeat(top_level->get_resources()->scroll_repeat);
994 int BC_TextBox::cursor_motion_event()
996 int cursor_letter, letter1, letter2;
999 if(text_selected || word_selected || line_selected)
1001 cursor_letter = get_cursor_letter(top_level->cursor_x,
1002 top_level->cursor_y);
1004 //printf("BC_TextBox::cursor_motion_event %d cursor_letter=%d\n", __LINE__, cursor_letter);
1008 select_line(letter1, letter2, cursor_letter);
1013 select_word(letter1, letter2, cursor_letter);
1018 letter1 = letter2 = cursor_letter;
1021 if(letter1 <= highlight_letter3)
1023 highlight_letter1 = letter1;
1024 highlight_letter2 = highlight_letter4;
1025 ibeam_letter = letter1;
1028 if(letter2 >= highlight_letter4)
1030 highlight_letter2 = letter2;
1031 highlight_letter1 = highlight_letter3;
1032 ibeam_letter = letter2;
1035 copy_selection(PRIMARY_SELECTION);
1048 int BC_TextBox::activate()
1050 top_level->active_subwindow = this;
1053 top_level->set_repeat(top_level->get_resources()->blink_rate);
1057 int BC_TextBox::deactivate()
1059 //printf("BC_TextBox::deactivate %d suggestions_popup=%p\n", __LINE__, suggestions_popup);
1061 top_level->unset_repeat(top_level->get_resources()->blink_rate);
1062 if(suggestions_popup)
1064 // Must deactivate instead of delete since this is called from BC_ListBox::button_press_event
1065 // suggestions_popup->deactivate();
1067 delete suggestions_popup;
1068 suggestions_popup = 0;
1075 int BC_TextBox::repeat_event(int64_t duration)
1078 int cursor_y = get_cursor_y();
1079 //int cursor_x = get_cursor_x();
1081 if(duration == top_level->get_resources()->tooltip_delay &&
1082 tooltip_text && tooltip_text[0] != 0 && highlighted)
1089 if(duration == top_level->get_resources()->blink_rate &&
1093 // don't flash if keypress
1094 if(skip_cursor->get_difference() < 500)
1096 // printf("BC_TextBox::repeat_event 1 %lld %lld\n",
1097 // skip_cursor->get_difference(),
1103 if(!(text_selected || word_selected || line_selected))
1112 if(duration == top_level->get_resources()->scroll_repeat &&
1113 (text_selected || word_selected || line_selected))
1116 if(get_cursor_y() < top_margin)
1118 difference = get_cursor_y() - top_margin ;
1121 if(get_cursor_y() > get_h() - bottom_margin)
1123 difference = get_cursor_y() -
1124 (get_h() - bottom_margin);
1126 if(difference != 0) {
1127 int min_y = -(get_text_rows() * text_height -
1128 get_h() + bottom_margin);
1130 text_y -= difference;
1131 // printf("BC_TextBox::repeat_event %d %d %d\n",
1135 text_y = MAX(min_y, text_y);
1136 text_y = MIN(text_y, top_margin);
1143 if(get_cursor_x() < left_margin)
1145 int difference = left_margin - get_cursor_x();
1147 text_x += difference;
1148 text_x = MIN(text_x, left_margin);
1152 else if(get_cursor_x() > get_w() - right_margin)
1154 int difference = get_cursor_x() - (get_w() - right_margin);
1155 int new_text_x = text_x - difference;
1157 // Get width of current row
1160 int wtext_len = wtext_update();
1163 for(int i = 0, k = text_y; i < wtext_len; k += text_height)
1166 while(wtext[i] != '\n' && i < wtext_len) {
1170 if(wtext[i] == '\n') i++;
1172 if(cursor_y >= k && cursor_y < k + text_height) {
1173 row_width = get_text_width(font,
1175 row_end - row_begin);
1181 min_x = -row_width + get_w() - left_margin - BCCURSORW;
1182 new_text_x = MAX(new_text_x, min_x);
1183 new_text_x = MIN(new_text_x, left_margin);
1185 if(new_text_x < text_x) text_x = new_text_x;
1194 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
1196 if( (top_level->get_keypress() == RETURN) ||
1197 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255)) {
1199 wchar_t *temp_string = top_level->get_wkeystring(&len);
1200 if(top_level->get_keypress() == RETURN) {
1201 temp_string[0] = '\n'; temp_string[1] = 0;
1204 insert_text(temp_string, len);
1212 int BC_TextBox::keypress_event()
1214 // Result == 2 contents changed
1215 // Result == 1 trapped keypress
1216 // Result == 0 nothing
1218 int dispatch_event = 0;
1220 if(!active || !enabled) return 0;
1222 int wtext_len = wtext_update();
1223 last_keypress = get_keypress();
1225 if( unicode_active >= 0 ) {
1228 switch( last_keypress ) {
1229 //unicode active acitons
1231 for( int i=highlight_letter1+1; i<highlight_letter2; ++i ) {
1232 int ch = nib(wtext[i]);
1233 if( ch < 0 ) return 1;
1234 wch = (wch<<4) + ch;
1238 unicode_active = -1;
1244 unicode_active = -1;
1249 if(ibeam_letter > 0) {
1250 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1251 highlight_letter2 = --ibeam_letter;
1252 if( highlight_letter1 >= highlight_letter2 )
1253 unicode_active = -1;
1258 case '0': case '1': case '2': case '3': case '4':
1259 case '5': case '6': case '7': case '8': case '9':
1260 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1261 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': {
1262 int n = nib(last_keypress);
1263 wch = n < 10 ? '0'+n : 'A'+n-10;
1277 insert_text(&wch, wlen);
1279 if( unicode_active >= 0 )
1280 highlight_letter2 = ibeam_letter;
1282 highlight_letter1 = highlight_letter2 = 0;
1288 //printf("BC_TextBox::keypress_event %d %x\n", __LINE__, last_keypress)
1289 switch(last_keypress) {
1291 // Deactivate the suggestions
1292 if(suggestions && suggestions_popup) {
1293 delete suggestions_popup;
1294 suggestions_popup = 0;
1298 top_level->deactivate();
1305 top_level->deactivate();
1310 default_keypress(dispatch_event, result);
1315 // Handle like a default keypress
1317 top_level->cycle_textboxes(1);
1322 top_level->cycle_textboxes(-1);
1327 if(ibeam_letter > 0) {
1328 int old_ibeam_letter = ibeam_letter;
1336 while(ibeam_letter > 0 && isalnum(wtext[ibeam_letter - 1]))
1341 if(top_level->shift_down()) {
1342 // Initialize highlighting
1343 if(highlight_letter1 == highlight_letter2) {
1344 highlight_letter1 = ibeam_letter;
1345 highlight_letter2 = old_ibeam_letter;
1347 else if(highlight_letter1 == old_ibeam_letter) {
1348 // Extend left highlight
1349 highlight_letter1 = ibeam_letter;
1351 else if(highlight_letter2 == old_ibeam_letter) {
1352 // Shrink right highlight
1353 highlight_letter2 = ibeam_letter;
1357 highlight_letter1 = highlight_letter2 = ibeam_letter;
1362 if(keypress_draw) draw(1);
1368 if(ibeam_letter < wtext_len) {
1369 int old_ibeam_letter = ibeam_letter;
1376 while(ibeam_letter < wtext_len && isalnum(wtext[ibeam_letter++]));
1382 if(top_level->shift_down()) {
1383 // Initialize highlighting
1384 if(highlight_letter1 == highlight_letter2) {
1385 highlight_letter1 = old_ibeam_letter;
1386 highlight_letter2 = ibeam_letter;
1388 else if(highlight_letter1 == old_ibeam_letter) {
1389 // Shrink left highlight
1390 highlight_letter1 = ibeam_letter;
1392 else if(highlight_letter2 == old_ibeam_letter) {
1393 // Expand right highlight
1394 highlight_letter2 = ibeam_letter;
1398 highlight_letter1 = highlight_letter2 = ibeam_letter;
1402 if(keypress_draw) draw(1);
1408 if(suggestions && suggestions_popup) {
1409 // Pass to suggestions popup
1410 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1411 suggestions_popup->activate(1);
1412 suggestions_popup->keypress_event();
1415 else if(ibeam_letter > 0) {
1416 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
1417 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1418 ibeam_y + text_y - text_height);
1419 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
1422 if(top_level->shift_down()) {
1423 // Initialize highlighting
1424 if(highlight_letter1 == highlight_letter2) {
1425 highlight_letter1 = new_letter;
1426 highlight_letter2 = ibeam_letter;
1428 else if(highlight_letter1 == ibeam_letter) {
1429 // Expand left highlight
1430 highlight_letter1 = new_letter;
1432 else if(highlight_letter2 == ibeam_letter) {
1433 // Shrink right highlight
1434 highlight_letter2 = new_letter;
1438 highlight_letter1 = highlight_letter2 = new_letter;
1440 if(highlight_letter1 > highlight_letter2) {
1441 int temp = highlight_letter1;
1442 highlight_letter1 = highlight_letter2;
1443 highlight_letter2 = temp;
1445 ibeam_letter = new_letter;
1448 if(keypress_draw) draw(1);
1454 if(ibeam_letter > 0) {
1455 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1456 ibeam_y + text_y - get_h());
1459 if(top_level->shift_down()) {
1460 // Initialize highlighting
1461 if(highlight_letter1 == highlight_letter2) {
1462 highlight_letter1 = new_letter;
1463 highlight_letter2 = ibeam_letter;
1465 else if(highlight_letter1 == ibeam_letter) {
1466 // Expand left highlight
1467 highlight_letter1 = new_letter;
1469 else if(highlight_letter2 == ibeam_letter) {
1470 // Shrink right highlight
1471 highlight_letter2 = new_letter;
1475 highlight_letter1 = highlight_letter2 = new_letter;
1477 if(highlight_letter1 > highlight_letter2) {
1478 int temp = highlight_letter1;
1479 highlight_letter1 = highlight_letter2;
1480 highlight_letter2 = temp;
1482 ibeam_letter = new_letter;
1485 if(keypress_draw) draw(1);
1491 // printf("BC_TextBox::keypress_event %d %p %p\n",
1494 // suggestions_popup);
1495 if(suggestions && suggestions_popup) {
1496 // Pass to suggestions popup
1497 suggestions_popup->activate(1);
1498 suggestions_popup->keypress_event();
1502 // if(ibeam_letter > 0)
1505 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1506 ibeam_y + text_y + text_height);
1507 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1509 if(top_level->shift_down()) {
1510 // Initialize highlighting
1511 if(highlight_letter1 == highlight_letter2) {
1512 highlight_letter1 = new_letter;
1513 highlight_letter2 = ibeam_letter;
1515 else if(highlight_letter1 == ibeam_letter) {
1516 // Shrink left highlight
1517 highlight_letter1 = new_letter;
1519 else if(highlight_letter2 == ibeam_letter) {
1520 // Expand right highlight
1521 highlight_letter2 = new_letter;
1525 highlight_letter1 = highlight_letter2 = new_letter;
1527 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);
1544 int new_letter = get_cursor_letter2(ibeam_x + text_x,
1545 ibeam_y + text_y + get_h());
1546 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1548 if(top_level->shift_down()) {
1549 // Initialize highlighting
1550 if(highlight_letter1 == highlight_letter2) {
1551 highlight_letter1 = new_letter;
1552 highlight_letter2 = ibeam_letter;
1554 else if(highlight_letter1 == ibeam_letter) {
1555 // Shrink left highlight
1556 highlight_letter1 = new_letter;
1558 else if(highlight_letter2 == ibeam_letter) {
1559 // Expand right highlight
1560 highlight_letter2 = new_letter;
1564 highlight_letter1 = highlight_letter2 = new_letter;
1566 if(highlight_letter1 > highlight_letter2) {
1567 int temp = highlight_letter1;
1568 highlight_letter1 = highlight_letter2;
1569 highlight_letter2 = temp;
1571 ibeam_letter = new_letter;
1574 if(keypress_draw) draw(1);
1576 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1581 delete suggestions_popup;
1582 suggestions_popup = 0;
1584 int old_ibeam_letter = ibeam_letter;
1586 while(ibeam_letter < wtext_len && wtext[ibeam_letter] != '\n')
1589 if(top_level->shift_down()) {
1591 if(highlight_letter1 == highlight_letter2) {
1592 highlight_letter2 = ibeam_letter;
1593 highlight_letter1 = old_ibeam_letter;
1595 else if(highlight_letter1 == old_ibeam_letter) {
1597 highlight_letter1 = highlight_letter2;
1598 highlight_letter2 = ibeam_letter;
1600 else if(highlight_letter2 == old_ibeam_letter) {
1602 highlight_letter2 = ibeam_letter;
1606 highlight_letter1 = highlight_letter2 = ibeam_letter;
1609 if(keypress_draw) draw(1);
1614 delete suggestions_popup;
1615 suggestions_popup = 0;
1617 int old_ibeam_letter = ibeam_letter;
1619 while(ibeam_letter > 0 && wtext[ibeam_letter - 1] != '\n')
1622 if(top_level->shift_down())
1625 if(highlight_letter1 == highlight_letter2)
1627 highlight_letter2 = old_ibeam_letter;
1628 highlight_letter1 = ibeam_letter;
1632 if(highlight_letter1 == old_ibeam_letter)
1634 highlight_letter1 = ibeam_letter;
1638 if(highlight_letter2 == old_ibeam_letter)
1640 highlight_letter2 = highlight_letter1;
1641 highlight_letter1 = ibeam_letter;
1645 highlight_letter1 = highlight_letter2 = ibeam_letter;
1648 if(keypress_draw) draw(1);
1653 if(suggestions_popup) {
1654 delete suggestions_popup;
1655 suggestions_popup = 0;
1658 if(highlight_letter1 == highlight_letter2) {
1659 if(ibeam_letter > 0) {
1660 delete_selection(ibeam_letter - 1, ibeam_letter, wtext_len);
1665 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1666 highlight_letter2 = ibeam_letter = highlight_letter1;
1670 if(keypress_draw) draw(1);
1676 //printf("BC_TextBox::keypress_event %d\n", __LINE__);
1677 if(highlight_letter1 == highlight_letter2) {
1678 if(ibeam_letter < wtext_len) {
1679 delete_selection(ibeam_letter, ibeam_letter + 1, wtext_len);
1683 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1684 highlight_letter2 = ibeam_letter = highlight_letter1;
1688 if(keypress_draw) draw(1);
1695 switch( get_keypress() ) {
1696 case 'c': case 'C': {
1697 if(highlight_letter1 != highlight_letter2) {
1698 copy_selection(SECONDARY_SELECTION);
1702 case 'v': case 'V': {
1703 paste_selection(SECONDARY_SELECTION);
1705 if(keypress_draw) draw(1);
1709 case 'x': case 'X': {
1710 if(highlight_letter1 != highlight_letter2) {
1711 copy_selection(SECONDARY_SELECTION);
1712 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1713 highlight_letter2 = ibeam_letter = highlight_letter1;
1717 if(keypress_draw) draw(1);
1721 case 'u': case 'U': {
1722 if( shift_down() ) {
1723 unicode_active = ibeam_letter;
1725 insert_text(&wkey, 1);
1727 highlight_letter1 = unicode_active;
1728 highlight_letter2 = ibeam_letter;
1737 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( unicode_active < 0 && highlight_letter1 < highlight_letter2 ) {
1773 delete_selection(highlight_letter1, highlight_letter2, wtext_len);
1774 highlight_letter2 = ibeam_letter = highlight_letter1;
1775 wtext_len = wtext_update();
1779 for(i=wtext_len-1, j=wtext_len+len-1; i>=ibeam_letter; i--, j--) {
1780 if( j >= wsize ) continue;
1781 wtext[j] = wtext[i];
1784 for(i = ibeam_letter, j = 0; j < len; j++, i++) {
1785 if( i >= wsize ) break;
1788 if( (wlen+=len) > wsize ) wlen = wsize;
1789 if( (ibeam_letter+=len) > wsize ) ibeam_letter = wsize;
1790 wtext[wlen] = 0; // wtext allocated wsize+1
1794 int BC_TextBox::is_separator(const char *txt, int i)
1796 if( i != 0 || separators[0] != '+' ) return !isalnum(txt[i]);
1797 return txt[0] != '+' && txt[0] != '-' && !isalnum(txt[0]);
1800 // used for time entry
1801 void BC_TextBox::do_separators(int ibeam_left)
1805 // Remove separators from text
1806 int wtext_len = wtext_update();
1807 for(int i = 0; i < wtext_len; ) {
1808 if( !iswalnum(wtext[i]) ) {
1809 for(int j = i; j < wtext_len - 1; j++)
1810 wtext[j] = wtext[j + 1];
1811 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1817 wtext[wtext_len] = 0;
1823 // Insert separators into text
1824 int separator_len = strlen(separators);
1825 for(int i = 0; i < separator_len; i++) {
1827 // Insert a separator
1828 if( is_separator(separators,i) ) {
1829 for(int j = wtext_len; j >= i; j--) {
1830 wtext[j + 1] = wtext[j];
1832 if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1834 wtext[i] = separators[i];
1838 wtext[i] = separators[i];
1843 wtext[separator_len] = 0;
1844 wlen = separator_len;
1848 void BC_TextBox::get_ibeam_position(int &x, int &y)
1850 int i, row_begin, row_end;
1851 int wtext_len = wtext_update();
1854 for( i=0; i<wtext_len; ) {
1856 for(; i<wtext_len && wtext[i]!='\n'; i++);
1859 if( ibeam_letter >= row_begin && ibeam_letter <= row_end ) {
1860 x = get_text_width(font, &wtext[row_begin], ibeam_letter - row_begin);
1861 //printf("BC_TextBox::get_ibeam_position %d %d %d %d %d\n", ibeam_letter, row_begin, row_end, x, y);
1865 if( i < wtext_len && wtext[i] == '\n' ) {
1870 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1876 void BC_TextBox::set_text_row(int row)
1878 text_x = left_margin;
1879 text_y = -(row * text_height) + top_margin;
1883 int BC_TextBox::get_text_row()
1885 return -(text_y - top_margin) / text_height;
1888 void BC_TextBox::find_ibeam(int dispatch_event)
1891 int old_x = text_x, old_y = text_y;
1893 get_ibeam_position(x, y);
1895 if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1897 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1898 if(text_x > left_margin) text_x = left_margin;
1901 if(left_margin + text_x + x < left_margin)
1903 text_x = -(x - (get_w() / 4)) + left_margin;
1904 if(text_x > left_margin) text_x = left_margin;
1907 int text_row = y / text_height;
1908 if( text_row < rows ) text_y = top_margin;
1910 int pix_rows = get_h() - bottom_margin - (y + text_y);
1911 if( pix_rows < text_height )
1912 text_y -= text_height * ((2*text_height-1-pix_rows) / text_height);
1914 pix_rows = y + text_y - top_margin;
1915 if( pix_rows < 0 ) {
1916 text_y += text_height * ((text_height-1-pix_rows) / text_height);
1917 if( text_y > top_margin ) text_y = top_margin;
1920 if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1924 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1926 int i, j, k, row_begin, row_end, result = 0, done = 0;
1927 int column1, column2;
1928 int got_visible_row = 0;
1930 // Select complete row if cursor above the window
1931 //printf("BC_TextBox::get_cursor_letter %d %d\n", __LINE__, text_y);
1932 if(cursor_y < text_y - text_height)
1938 int wtext_len = wtext_update();
1940 for(i=0, k=text_y; i<wtext_len && k<get_h() && !done; k+=text_height) {
1941 // Simulate drawing of 1 row
1943 for(j = 0; wtext[i]!='\n' && i<wtext_len; i++);
1947 int first_visible_row = 0;
1948 int last_visible_row = 0;
1949 if( k+text_height > top_margin && !got_visible_row) {
1950 first_visible_row = 1;
1951 got_visible_row = 1;
1954 if( (k+text_height >= get_h() - bottom_margin ||
1955 (row_end >= wtext_len && k < get_h() - bottom_margin &&
1956 k + text_height > 0)) )
1957 last_visible_row = 1;
1959 // Cursor is inside vertical range of row
1960 if((cursor_y >= top_margin &&
1961 cursor_y < get_h() - bottom_margin &&
1962 cursor_y >= k && cursor_y < k + text_height) ||
1963 // Cursor is above 1st row
1964 (cursor_y < k + text_height && first_visible_row) ||
1965 // Cursor is below last row
1966 (cursor_y >= k && last_visible_row))
1968 column1 = column2 = 0;
1969 for(j = row_begin; j<wsize && j<=row_end && !done; j++) {
1970 column2 = get_text_width(font, &wtext[row_begin], j-row_begin) + text_x;
1971 if((column2 + column1) / 2 >= cursor_x) {
1974 // printf("BC_TextBox::get_cursor_letter %d %d %d %d\n",
1975 // __LINE__, result, first_visible_row, last_visible_row);
1986 if(wtext[i] == '\n') i++;
1988 // Select complete row if last visible & cursor is below window
1989 if(last_visible_row && cursor_y > k + text_height * 2)
1992 if(i >= wtext_len && !done) {
1998 // printf("BC_TextBox::get_cursor_letter %d cursor_y=%d k=%d h=%d %d %d\n",
1999 // __LINE__, cursor_y, k, get_h(), first_visible_row, last_visible_row);
2000 if(result < 0) result = 0;
2001 if(result > wtext_len) {
2002 //printf("BC_TextBox::get_cursor_letter %d\n", __LINE__);
2010 int BC_TextBox::get_cursor_letter2(int cursor_x, int cursor_y)
2012 int i, j, k, row_begin, row_end, result = 0, done = 0;
2013 int column1, column2;
2014 int wtext_len = wtext_update();
2016 if(cursor_y < text_y) {
2021 for(i = 0, k = text_y; i < wtext_len && !done; k += text_height) {
2023 for(; wtext[i] != '\n' && i < wtext_len; i++);
2026 if(cursor_y >= k && cursor_y < k + text_height) {
2027 column1 = column2 = 0;
2028 for(j = 0; j <= row_end - row_begin && !done; j++) {
2029 column2 = get_text_width(font, &wtext[row_begin], j) + text_x;
2030 if((column2 + column1) / 2 >= cursor_x) {
2031 result = row_begin + j - 1;
2042 if(wtext[i] == '\n') i++;
2044 if(i >= wtext_len && !done) {
2048 if(result < 0) result = 0;
2049 if(result > wtext_len) result = wtext_len;
2054 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
2056 int wtext_len = wtext_update();
2057 letter1 = letter2 = ibeam_letter;
2058 if( letter1 < 0 ) letter1 = 0;
2059 if( letter2 < 0 ) letter2 = 0;
2060 if( letter1 > wtext_len ) letter1 = wtext_len;
2061 if( letter2 > wtext_len ) letter2 = wtext_len;
2062 if( !wtext_len ) return;
2063 for( int i=letter1; i>=0 && iswalnum(wtext[i]); --i ) letter1 = i;
2064 for( int i=letter2; i<wtext_len && iswalnum(wtext[i]); ) letter2 = ++i;
2065 if( letter2 < wtext_len && wtext[letter2] == ' ' ) ++letter2;
2069 void BC_TextBox::select_line(int &letter1, int &letter2, int ibeam_letter)
2071 int wtext_len = wtext_update();
2072 letter1 = letter2 = ibeam_letter;
2073 if( letter1 < 0 ) letter1 = 0;
2074 if( letter2 < 0 ) letter2 = 0;
2075 if( letter1 > wtext_len ) letter1 = wtext_len;
2076 if( letter2 > wtext_len ) letter2 = wtext_len;
2077 if( !wtext_len ) return;
2078 for( int i=letter1; i>=0 && wtext[i]!='\n'; --i ) letter1 = i;
2079 for( int i=letter2; i<wtext_len && wtext[i]!='\n'; ) letter2 = ++i;
2082 void BC_TextBox::copy_selection(int clipboard_num)
2084 int wtext_len = wtext_update();
2085 if(!wtext_len) return;
2087 if(highlight_letter1 >= wtext_len || highlight_letter2 > wtext_len ||
2088 highlight_letter1 < 0 || highlight_letter2 < 0 ||
2089 highlight_letter2 - highlight_letter1 <= 0) return;
2090 int clip_len = highlight_letter2 - highlight_letter1;
2091 //printf(" BC_TextBox::copy_selection %d %d %d\n",highlight_letter1, highlight_letter2, clip_len);
2092 char ctext[4*clip_len+4];
2093 clip_len = text_update(&wtext[highlight_letter1],clip_len, ctext,4*clip_len+4);
2094 get_clipboard()->to_clipboard(ctext, clip_len, clipboard_num);
2098 void BC_TextBox::paste_selection(int clipboard_num)
2100 int len = get_clipboard()->clipboard_len(clipboard_num);
2103 char cstring[len]; wchar_t wstring[len];
2104 get_clipboard()->from_clipboard(cstring, len, clipboard_num); --len;
2105 //printf("BC_TextBox::paste_selection %d '%*.*s'\n",len,len,len,cstring);
2106 len = BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
2107 cstring,len, (char *)wstring,(len+1)*sizeof(wchar_t)) / sizeof(wchar_t);
2108 insert_text(wstring, len);
2112 void BC_TextBox::set_keypress_draw(int value)
2114 keypress_draw = value;
2117 int BC_TextBox::get_last_keypress()
2119 return last_keypress;
2122 int BC_TextBox::get_ibeam_letter()
2124 return ibeam_letter;
2127 void BC_TextBox::set_ibeam_letter(int number, int redraw)
2129 this->ibeam_letter = number;
2136 void BC_TextBox::set_separators(const char *separators)
2138 this->separators = (char*)separators;
2141 int BC_TextBox::get_rows()
2152 BC_TextBoxSuggestions::BC_TextBoxSuggestions(BC_TextBox *text_box,
2160 text_box->suggestions,
2167 this->text_box = text_box;
2169 set_justify(LISTBOX_LEFT);
2172 BC_TextBoxSuggestions::~BC_TextBoxSuggestions()
2176 int BC_TextBoxSuggestions::selection_changed()
2179 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2180 BC_ListBoxItem *item = get_selection(0, 0);
2181 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2185 char *current_suggestion = item->get_text();
2186 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2187 // int text_box_len = strlen(text_box->text);
2188 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2189 strcpy(text_box->text + text_box->suggestion_column, current_suggestion);
2190 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2191 *(text_box->text + text_box->suggestion_column + strlen(current_suggestion)) = 0;
2193 //printf("BC_TextBoxSuggestions::selection_changed %d\n", __LINE__);
2195 text_box->handle_event();
2205 int BC_TextBoxSuggestions::handle_event()
2207 char *current_suggestion = 0;
2208 BC_ListBoxItem *item = get_selection(0, 0);
2209 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2210 if(item && (current_suggestion=item->get_text()) != 0)
2212 int col = text_box->suggestion_column;
2213 int len = BCTEXTLEN-1 - col;
2214 char *cp = &text_box->text[col];
2215 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2216 strncpy(cp, current_suggestion, len);
2217 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2218 if( (col=strlen(current_suggestion)) >= len )
2220 text_box->dirty = 1;
2224 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2225 text_box->highlight_letter1 =
2226 text_box->highlight_letter2 =
2227 text_box->ibeam_letter = text_box->tstrlen();
2228 text_box->wtext_update();
2230 text_box->handle_event();
2231 //printf("BC_TextBoxSuggestions::handle_event %d\n", __LINE__);
2236 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2237 int x, int y, int w, int rows,
2238 const char *default_text, int default_size)
2240 this->parent_window = parent_window;
2245 this->default_text = default_text;
2246 this->default_wtext = 0;
2247 this->default_size = default_size;
2250 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
2251 int x, int y, int w, int rows,
2252 const wchar_t *default_wtext, int default_size)
2254 this->parent_window = parent_window;
2259 this->default_text = 0;
2260 this->default_wtext = default_wtext;
2261 this->default_size = default_size;
2264 BC_ScrollTextBox::~BC_ScrollTextBox()
2273 void BC_ScrollTextBox::create_objects()
2275 // Must be created first
2276 parent_window->add_subwindow(text = default_wtext ?
2277 new BC_ScrollTextBoxText(this, default_wtext) :
2278 new BC_ScrollTextBoxText(this, default_text));
2279 parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
2280 text->yscroll = yscroll;
2281 yscroll->bound_to = text;
2285 int BC_ScrollTextBox::handle_event()
2290 int BC_ScrollTextBox::get_x()
2295 int BC_ScrollTextBox::get_y()
2300 int BC_ScrollTextBox::get_w()
2305 int BC_ScrollTextBox::get_h()
2307 return this->text->get_h();
2310 int BC_ScrollTextBox::get_rows()
2316 const char* BC_ScrollTextBox::get_text()
2318 return text->get_text();
2321 const wchar_t* BC_ScrollTextBox::get_wtext()
2323 return text->get_wtext();
2326 void BC_ScrollTextBox::set_text(char *text, int isz)
2328 this->text->set_text(text, isz);
2329 yscroll->update_length(this->text->get_text_rows(),
2330 this->text->get_text_row(),
2331 yscroll->get_handlelength(),
2335 int BC_ScrollTextBox::set_text_row(int n)
2337 text->set_text_row(n);
2338 yscroll->update_value(n);
2342 void BC_ScrollTextBox::update(const char *text)
2344 this->text->update(text);
2345 yscroll->update_length(this->text->get_text_rows(),
2346 this->text->get_text_row(),
2347 yscroll->get_handlelength(),
2351 void BC_ScrollTextBox::update(const wchar_t *wtext)
2353 this->text->update(wtext);
2354 yscroll->update_length(this->text->get_text_rows(),
2355 this->text->get_text_row(),
2356 yscroll->get_handlelength(),
2360 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
2367 text->reposition_window(x,
2369 w - yscroll->get_span(),
2371 yscroll->reposition_window(x + w - yscroll->get_span(),
2373 BC_TextBox::calculate_row_h(rows,
2375 yscroll->update_length(text->get_text_rows(),
2376 text->get_text_row(),
2381 void BC_ScrollTextBox::set_selection(int char1, int char2, int ibeam)
2383 this->text->set_selection(char1, char2, ibeam);
2386 void BC_ScrollTextBox::wset_selection(int char1, int char2, int ibeam)
2388 this->text->wset_selection(char1, char2, ibeam);
2391 int BC_ScrollTextBox::get_ibeam_letter()
2393 return this->text->get_ibeam_letter();
2402 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const char *text)
2403 : BC_TextBox(gui->x, gui->y,
2404 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2405 gui->rows, gui->default_size, (char*)text, 1, MEDIUMFONT)
2410 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const wchar_t *wtext)
2411 : BC_TextBox(gui->x, gui->y,
2412 gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2413 gui->rows, gui->default_size, (wchar_t*)wtext, 1, MEDIUMFONT)
2418 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
2427 int BC_ScrollTextBoxText::handle_event()
2429 gui->yscroll->update_length(get_text_rows(),
2431 gui->yscroll->get_handlelength(),
2433 return gui->handle_event();
2436 int BC_ScrollTextBoxText::motion_event()
2438 gui->yscroll->update_length(get_text_rows(),
2440 gui->yscroll->get_handlelength(),
2446 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
2447 : BC_ScrollBar(gui->x +
2449 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
2452 BC_TextBox::calculate_row_h(gui->rows,
2453 gui->parent_window),
2454 gui->text->get_text_rows(),
2461 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
2465 int BC_ScrollTextBoxYScroll::handle_event()
2467 gui->text->set_text_row(get_position());
2480 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const char *text)
2481 : BC_TextBox(x, y, popup->text_w, 1, text, BCTEXTLEN)
2483 this->popup = popup;
2486 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y, const wchar_t *wtext)
2487 : BC_TextBox(x, y, popup->text_w, 1, wtext, BCTEXTLEN)
2489 this->popup = popup;
2492 BC_PopupTextBoxText::~BC_PopupTextBoxText()
2502 int BC_PopupTextBoxText::handle_event()
2504 popup->handle_event();
2508 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
2510 popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
2511 popup->list_h, popup->list_format, popup->list_items, 0, 0, 1, 0, 1)
2513 this->popup = popup;
2515 int BC_PopupTextBoxList::handle_event()
2517 BC_ListBoxItem *item = get_selection(0, 0);
2520 popup->textbox->update(item->get_text());
2521 popup->handle_event();
2529 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window,
2530 ArrayList<BC_ListBoxItem*> *list_items,
2531 const char *default_text, int x, int y,
2532 int text_w, int list_h, int list_format)
2536 this->list_h = list_h;
2537 this->list_format = list_format;
2538 this->default_text = (char*)default_text;
2539 this->default_wtext = 0;
2540 this->text_w = text_w;
2541 this->parent_window = parent_window;
2542 this->list_items = list_items;
2545 BC_PopupTextBox::~BC_PopupTextBox()
2555 int BC_PopupTextBox::create_objects()
2557 int x = this->x, y = this->y;
2558 parent_window->add_subwindow(textbox = default_wtext ?
2559 new BC_PopupTextBoxText(this, x, y, default_wtext) :
2560 new BC_PopupTextBoxText(this, x, y, default_text));
2561 x += textbox->get_w();
2562 parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
2566 void BC_PopupTextBox::update(const char *text)
2568 textbox->update(text);
2571 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
2573 listbox->update(data,
2580 const char* BC_PopupTextBox::get_text()
2582 return textbox->get_text();
2585 const wchar_t* BC_PopupTextBox::get_wtext()
2587 return textbox->get_wtext();
2590 int BC_PopupTextBox::get_number()
2592 return listbox->get_selection_number(0, 0);
2595 int BC_PopupTextBox::get_x()
2600 int BC_PopupTextBox::get_y()
2605 int BC_PopupTextBox::get_w()
2607 return textbox->get_w() + listbox->get_w();
2610 int BC_PopupTextBox::get_h()
2612 return textbox->get_h();
2615 int BC_PopupTextBox::handle_event()
2620 void BC_PopupTextBox::reposition_window(int x, int y)
2625 textbox->reposition_window(x1,
2628 textbox->get_rows());
2629 x1 += textbox->get_w();
2630 listbox->reposition_window(x1, y1, -1, -1, 0);
2631 // if(flush) parent_window->flush();
2647 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2648 int64_t default_value,
2653 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2655 this->popup = popup;
2658 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
2659 float default_value,
2664 : BC_TextBox(x, y, popup->text_w, 1, default_value)
2666 this->popup = popup;
2669 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
2681 int BC_TumbleTextBoxText::handle_event()
2683 popup->handle_event();
2687 int BC_TumbleTextBoxText::button_press_event()
2691 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
2693 if(get_buttonpress() == 4)
2695 popup->tumbler->handle_up_event();
2698 if(get_buttonpress() == 5)
2700 popup->tumbler->handle_down_event();
2710 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2711 int64_t default_value,
2723 this->default_value = default_value;
2724 this->text_w = text_w;
2725 this->parent_window = parent_window;
2731 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2744 this->default_value = default_value;
2745 this->text_w = text_w;
2746 this->parent_window = parent_window;
2752 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window,
2753 float default_value_f,
2763 this->min_f = min_f;
2764 this->max_f = max_f;
2765 this->default_value_f = default_value_f;
2766 this->text_w = text_w;
2767 this->parent_window = parent_window;
2773 BC_TumbleTextBox::~BC_TumbleTextBox()
2775 // Recursive delete. Normally ~BC_TumbleTextBox is never called but textbox
2776 // is deleted anyway by the windowbase so textbox deletes this.
2777 if(tumbler) delete tumbler;
2779 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
2788 void BC_TumbleTextBox::reset()
2795 void BC_TumbleTextBox::set_precision(int precision)
2797 this->precision = precision;
2800 void BC_TumbleTextBox::set_increment(float value)
2802 this->increment = value;
2803 if(tumbler) tumbler->set_increment(value);
2806 void BC_TumbleTextBox::set_log_floatincrement(int value)
2808 this->log_floatincrement = value;
2809 if(tumbler) tumbler->set_log_floatincrement(value);
2812 int BC_TumbleTextBox::create_objects()
2814 int x = this->x, y = this->y;
2818 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2824 textbox->set_precision(precision);
2827 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
2834 x += textbox->get_w();
2837 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox,
2843 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox,
2849 tumbler->set_increment(increment);
2853 const char* BC_TumbleTextBox::get_text()
2855 return textbox->get_text();
2858 const wchar_t* BC_TumbleTextBox::get_wtext()
2860 return textbox->get_wtext();
2863 BC_TextBox* BC_TumbleTextBox::get_textbox()
2868 int BC_TumbleTextBox::update(const char *value)
2870 textbox->update(value);
2874 int BC_TumbleTextBox::update(int64_t value)
2876 textbox->update(value);
2880 int BC_TumbleTextBox::update(float value)
2882 textbox->update(value);
2887 int BC_TumbleTextBox::get_x()
2892 int BC_TumbleTextBox::get_y()
2897 int BC_TumbleTextBox::get_w()
2899 return textbox->get_w() + tumbler->get_w();
2902 int BC_TumbleTextBox::get_h()
2904 return textbox->get_h();
2907 void BC_TumbleTextBox::disable()
2909 if( !get_enabled() ) return;
2910 tumbler->hide_window(0);
2911 return textbox->disable();
2914 void BC_TumbleTextBox::enable()
2916 if( get_enabled() ) return;
2917 tumbler->show_window(0);
2918 return textbox->enable();
2921 int BC_TumbleTextBox::get_enabled()
2923 return textbox->get_enabled();
2926 int BC_TumbleTextBox::handle_event()
2931 void BC_TumbleTextBox::reposition_window(int x, int y)
2936 textbox->reposition_window(x,
2940 tumbler->reposition_window(x + textbox->get_w(),
2942 // if(flush) parent_window->flush();
2946 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2948 tumbler->set_boundaries(min, max);
2951 void BC_TumbleTextBox::set_boundaries(float min, float max)
2953 tumbler->set_boundaries(min, max);