r717: Made the highlighted text color of the menus WHITE
[cinelerra_cv/mob.git] / guicast / bctextbox.C
blob9248811999cf7052fe639163aa78e09627a1cc55
1 #include "bcclipboard.h"
2 #include "bclistboxitem.h"
3 #include "bcresources.h"
4 #include "bctextbox.h"
5 #include "clip.h"
6 #include "colors.h"
7 #include <ctype.h>
8 #include "cursors.h"
9 #include "keys.h"
10 #include <math.h>
11 #include "bctimer.h"
12 #include "vframe.h"
14 #include <string.h>
16 #define VERTICAL_MARGIN 2
17 #define VERTICAL_MARGIN_NOBORDER 0
18 #define HORIZONTAL_MARGIN 4
19 #define HORIZONTAL_MARGIN_NOBORDER 2
21 BC_TextBox::BC_TextBox(int x, 
22         int y, 
23         int w, 
24         int rows, 
25         char *text, 
26         int has_border, 
27         int font)
28  : BC_SubWindow(x, y, w, 0, -1)
30         skip_cursor = 0;
31         reset_parameters(rows, has_border, font);
32         strcpy(this->text, text);
35 BC_TextBox::BC_TextBox(int x, 
36         int y, 
37         int w, 
38         int rows, 
39         int64_t text, 
40         int has_border, 
41         int font)
42  : BC_SubWindow(x, y, w, 0, -1)
44         skip_cursor = 0;
45         reset_parameters(rows, has_border, font);
46         sprintf(this->text, "%lld", text);
49 BC_TextBox::BC_TextBox(int x, 
50         int y, 
51         int w, 
52         int rows, 
53         float text, 
54         int has_border, 
55         int font,
56         int precision)
57  : BC_SubWindow(x, y, w, 0, -1)
59         skip_cursor = 0;
60         reset_parameters(rows, has_border, font);
61         this->precision = precision;
62         sprintf(this->text, "%0.*f", precision, text);
65 BC_TextBox::BC_TextBox(int x, 
66         int y, 
67         int w, 
68         int rows, 
69         int text, 
70         int has_border, 
71         int font)
72  : BC_SubWindow(x, y, w, 0, -1)
74         skip_cursor = 0;
75         reset_parameters(rows, has_border, font);
76         sprintf(this->text, "%d", text);
79 BC_TextBox::~BC_TextBox()
81         if(skip_cursor) delete skip_cursor;
84 int BC_TextBox::reset_parameters(int rows, int has_border, int font)
86         this->rows = rows;
87         this->has_border = has_border;
88         this->font = font;
89         text_start = 0;
90         text_end = 0;
91         highlight_letter1 = highlight_letter2 = 0;
92         highlight_letter3 = highlight_letter4 = 0;
93         ibeam_letter = 0;
94         active = 0;
95         text_selected = word_selected = 0;
96         text_x = 0;
97         enabled = 1;
98         highlighted = 0;
99         precision = 4;
100         if (!skip_cursor)
101                 skip_cursor = new Timer;
102         keypress_draw = 1;
103         last_keypress = 0;
104         separators = 0;
105         return 0;
108 int BC_TextBox::initialize()
110         if (!skip_cursor)
111                 skip_cursor = new Timer;
112         skip_cursor->update();
113 // Get dimensions
114         text_ascent = get_text_ascent(font) + 1;
115         text_descent = get_text_descent(font) + 1;
116         text_height = text_ascent + text_descent;
117         ibeam_letter = strlen(text);
118         if(has_border)
119         {
120                 left_margin = right_margin = HORIZONTAL_MARGIN;
121                 top_margin = bottom_margin = VERTICAL_MARGIN;
122         }
123         else
124         {
125                 left_margin = right_margin = HORIZONTAL_MARGIN_NOBORDER;
126                 top_margin = bottom_margin = VERTICAL_MARGIN_NOBORDER;
127         }
128         h = get_row_h(rows);
129         text_x = left_margin;
130         text_y = top_margin;
131         find_ibeam(0);
133 // Create the subwindow
134         BC_SubWindow::initialize();
136         BC_Resources *resources = get_resources();
137         if(has_border)
138         {
139                 back_color = resources->text_background;
140                 high_color = resources->text_background_hi;
141         }
142         else 
143         {
144                 high_color = resources->text_background_noborder_hi;
145                 back_color = bg_color;
146         }
148         draw();
149         set_cursor(IBEAM_CURSOR);
150         return 0;
153 int BC_TextBox::calculate_h(BC_WindowBase *gui, 
154         int font, 
155         int has_border,
156         int rows)
158         return rows * (gui->get_text_ascent(font) + 1 + 
159                 gui->get_text_descent(font) + 1) +
160                 2 * (has_border ? VERTICAL_MARGIN : VERTICAL_MARGIN_NOBORDER);
163 void BC_TextBox::set_precision(int precision)
165         this->precision = precision;
168 int BC_TextBox::update(char *text)
170 //printf("BC_TextBox::update 1 %d %s %s\n", strcmp(text, this->text), text, this->text);
171         int text_len = strlen(text);
172 // Don't update if contents are the same
173         if(!strcmp(text, this->text)) return 0;
176         strcpy(this->text, text);
177         if(highlight_letter1 > text_len) highlight_letter1 = text_len;
178         if(highlight_letter2 > text_len) highlight_letter2 = text_len;
179         if(ibeam_letter > text_len) ibeam_letter = text_len;
180         draw();
181         return 0;
184 int BC_TextBox::update(int64_t value)
186         char string[BCTEXTLEN];
187         sprintf(string, "%lld", value);
190         update(string);
191         return 0;
194 int BC_TextBox::update(float value)
196         char string[BCTEXTLEN];
197         sprintf(string, "%0.*f", precision, value);
199         update(string);
200         return 0;
203 void BC_TextBox::disable()
205         if(enabled)
206         {
207                 enabled = 0;
208                 if(top_level)
209                 {
210                         if(active) top_level->deactivate();
211                         draw();
212                 }
213         }
216 void BC_TextBox::enable()
218         if(!enabled)
219         {
220                 enabled = 1;
221                 if(top_level)
222                 {
223                         draw();
224                 }
225         }
228 int BC_TextBox::get_enabled()
230         return enabled;
233 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
235         return (pixels - 4) / 
236                 (window->get_text_ascent(font) + 1 + 
237                         window->get_text_descent(font) + 1);
240 int BC_TextBox::calculate_row_h(int rows, 
241         BC_WindowBase *parent_window, 
242         int has_border, 
243         int font)
245         return rows * 
246                 (parent_window->get_text_ascent(font) + 1 + 
247                 parent_window->get_text_descent(font) + 1) +
248                 (has_border ? 4 : 0);
251 char* BC_TextBox::get_text()
253         return text;
256 int BC_TextBox::get_text_rows()
258         int text_len = strlen(text);
259         int result = 1;
260         for(int i = 0; i < text_len; i++)
261         {
262                 if(text[i] == 0xa) result++;
263         }
264         return result;
268 int BC_TextBox::get_row_h(int rows)
270         return rows * text_height + top_margin + bottom_margin;
273 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
275         int new_h = get_h();
276         if(w < 0) w = get_w();
277         if(rows != -1)
278         {
279                 new_h = get_row_h(rows);
280                 this->rows = rows;
281         }
283         if(x != get_x() || 
284                 y != get_y() || 
285                 w != get_w() || 
286                 new_h != get_h())
287         {
288 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
289 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
290                 BC_WindowBase::reposition_window(x, y, w, new_h);
291                 draw();
292         }
293         return 0;
296 void BC_TextBox::draw_border()
298         BC_Resources *resources = get_resources();
299 // Clear margins
300         set_color(background_color);
301         draw_box(0, 0, left_margin, get_h());
302         draw_box(get_w() - right_margin, 0, right_margin, get_h());
304         if(has_border)
305         {
306                 if(highlighted)
307                         draw_3d_border(0, 0, w, h,
308                                 resources->button_shadow, 
309                                 resources->button_uphighlighted,
310                                 resources->button_highlighted,
311                                 resources->button_light);
312                 else
313                         draw_3d_border(0, 0, w, h, 
314                                 resources->text_border1, 
315                                 resources->text_border2,
316                                 resources->text_border3,
317                                 resources->text_border4);
318         }
321 void BC_TextBox::draw_cursor()
323 //      set_color(background_color);
324         set_color(WHITE);
325         set_inverse();
327         draw_box(ibeam_x + text_x, 
328                 ibeam_y + text_y, 
329                 BCCURSORW, 
330                 text_height);
331         set_opaque();
335 void BC_TextBox::draw()
337         int i, j, k, text_len;
338         int row_begin, row_end;
339         int highlight_x1, highlight_x2;
340         int need_ibeam = 1;
341         BC_Resources *resources = get_resources();
343 //printf("BC_TextBox::draw 1 %s\n", text);
344 // Background
345         if(has_border)
346         {
347                 background_color = resources->text_background;
348         }
349         else
350         {
351                 if(highlighted)
352                 {
353                         background_color = high_color;
354                 }
355                 else
356                 {
357                         background_color = back_color;
358                 }
359         }
361         set_color(background_color);
362         draw_box(0, 0, w, h);
364 // Draw text with selection
365         set_font(font);
366         text_len = strlen(text);
367 //printf("BC_TextBox::draw 0 %s %d %d %d %d\n", text, text_y, text_len, get_w(), text_height);
369         for(i = 0, k = text_y; i < text_len && k < get_h(); k += text_height)
370         {
371 // Draw row of text
372                 if(text[i] == '\n') i++;
373                 row_begin = i;
374                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
375                 {
376                         text_row[j] = text[i];
377                 }
378                 row_end = i;
379                 text_row[j] = 0;
381 //printf("BC_TextBox::draw 1 %d %d %c\n", row_begin, row_end, text_row[j - 1]);
383                 if(k > -text_height + top_margin && k < get_h() - bottom_margin)
384                 {
385 // Draw highlighted region of row
386                         if(highlight_letter2 > highlight_letter1 &&
387                                 highlight_letter2 > row_begin && highlight_letter1 < row_end)
388                         {
389                                 if(active && enabled && get_has_focus())
390                                         set_color(resources->text_highlight);
391                                 else
392                                         set_color(resources->text_inactive_highlight);
394                                 if(highlight_letter1 >= row_begin && highlight_letter1 < row_end)
395                                         highlight_x1 = get_text_width(font, text_row, highlight_letter1 - row_begin);
396                                 else
397                                         highlight_x1 = 0;
399                                 if(highlight_letter2 > row_begin && highlight_letter2 <= row_end)
400                                         highlight_x2 = get_text_width(font, text_row, highlight_letter2 - row_begin);
401                                 else
402                                         highlight_x2 = get_w();
404                                 draw_box(highlight_x1 + text_x, 
405                                         k, 
406                                         highlight_x2 - highlight_x1, 
407                                         text_height);
408                         }
410 // Draw text over highlight
411                         if(enabled)
412                                 set_color(resources->text_default);
413                         else
414                                 set_color(MEGREY);
416                         draw_text(text_x, k + text_ascent, text_row);
418 // Get ibeam location
419                         if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
420                         {
421                                 need_ibeam = 0;
422                                 ibeam_y = k - text_y;
423                                 ibeam_x = get_text_width(font, text_row, ibeam_letter - row_begin);
424                         }
425                 }
426         }
428 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
429         if(need_ibeam)
430         {
431                 ibeam_x = 0;
432                 ibeam_y = 0;
433         }
435 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
436 // Draw solid cursor
437         if (active) 
438                 draw_cursor();
440 // Border
441         draw_border();
442         flash();
443         flush();   
446 int BC_TextBox::focus_in_event()
448         draw();
449         return 1;
452 int BC_TextBox::focus_out_event()
454         draw();
455         return 1;
458 int BC_TextBox::cursor_enter_event()
460         if(top_level->event_win == win && enabled)
461         {
462                 tooltip_done = 0;
464                 if(!highlighted)
465                 {
466                         highlighted = 1;
467                         draw_border();
468                         flash();
469                         flush();   
470                 }
471         }
472         return 0;
475 int BC_TextBox::cursor_leave_event()
477         if(highlighted)
478         {
479                 highlighted = 0;
480                 draw_border();
481                 hide_tooltip();
482                 flash();
483                 flush();   
484         }
485         return 0;
488 int BC_TextBox::button_press_event()
490         if(get_buttonpress() > 2) return 0;
492         int cursor_letter = 0;
493         int text_len = strlen(text);
495         if(!enabled) return 0;
497         if(top_level->event_win == win)
498         {
499                 if(!active)
500                 {
501                         hide_tooltip();
502                         top_level->deactivate();
503                         activate();
504                 }
506                 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
507                 if(get_double_click())
508                 {
509                         word_selected = 1;
510                         select_word(highlight_letter1, highlight_letter2, cursor_letter);
511                         highlight_letter3 = highlight_letter1;
512                         highlight_letter4 = highlight_letter2;
513                         ibeam_letter = highlight_letter2;
514                         copy_selection(PRIMARY_SELECTION);
515                 }
516                 else
517                 if(get_buttonpress() == 2)
518                 {
519                         highlight_letter3 = highlight_letter4 = 
520                                 ibeam_letter = highlight_letter1 = 
521                                 highlight_letter2 = cursor_letter;
522                         paste_selection(PRIMARY_SELECTION);
523                 }
524                 else
525                 {
526                         text_selected = 1;
527                         highlight_letter3 = highlight_letter4 = 
528                                 ibeam_letter = highlight_letter1 = 
529                                 highlight_letter2 = cursor_letter;
530                 }
531                 
532                 if(ibeam_letter < 0) ibeam_letter = 0;
533                 if(ibeam_letter > text_len) ibeam_letter = text_len;
534                 draw();
535                 return 1;
536         }
537         else
538         if(active)
539         {
540                 top_level->deactivate();
541         }
543         return 0;
546 int BC_TextBox::button_release_event()
548         if(active)
549         {
550                 hide_tooltip();
551                 if(text_selected || word_selected)
552                 {
553                         text_selected = 0;
554                         word_selected = 0;
555                 }
556         }
557         return 0;
560 int BC_TextBox::cursor_motion_event()
562         int cursor_letter, text_len = strlen(text), letter1, letter2;
563         if(active)
564         {
565                 if(text_selected || word_selected)
566                 {
567                         cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
568                         if(word_selected)
569                         {
570                                 select_word(letter1, letter2, cursor_letter);
571                         }
572                         else
573                         if(text_selected)
574                         {
575                                 letter1 = letter2 = cursor_letter;
576                         }
578                         if(letter1 <= highlight_letter3)
579                         {
580                                 highlight_letter1 = letter1;
581                                 highlight_letter2 = highlight_letter4;
582                                 ibeam_letter = letter1;
583                         }
584                         else
585                         if(letter2 >= highlight_letter4)
586                         {
587                                 highlight_letter2 = letter2;
588                                 highlight_letter1 = highlight_letter3;
589                                 ibeam_letter = letter2;
590                         }
591                         
592                         copy_selection(PRIMARY_SELECTION);
593                         find_ibeam(1);
594                         draw();
595                         return 1;
596                 }
597         }
598         return 0;
601 int BC_TextBox::activate()
603         top_level->active_subwindow = this;
604         active = 1;
605         draw();
606         top_level->set_repeat(top_level->get_resources()->blink_rate);
607         return 0;
610 int BC_TextBox::deactivate()
612         active = 0;
613         top_level->unset_repeat(top_level->get_resources()->blink_rate);
614         draw();
615         return 0;
618 int BC_TextBox::repeat_event(int64_t duration)
620         int result = 0;
622         if(duration == top_level->get_resources()->tooltip_delay &&
623                 tooltip_text[0] != 0 &&
624                 highlighted)
625         {
626                 show_tooltip();
627                 tooltip_done = 1;
628                 result = 1;
629         }
630                 
631         if(duration == top_level->get_resources()->blink_rate && 
632                 active &&
633                 get_has_focus())
634         {
635                 if(skip_cursor->get_difference() < duration)
636                 {
637 // printf("BC_TextBox::repeat_event 1 %lld %lld\n", 
638 // skip_cursor->get_difference(), 
639 // duration);
640                         return 1;
641                 }
642                 draw_cursor();
643                 flash();
644                 flush();   
645                 result = 1;
646         }
647         return result;
650 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
652     if((top_level->get_keypress() == RETURN) ||
653 //              (top_level->get_keypress() > 30 && top_level->get_keypress() < 127))
654                 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255))
655         {
656 // Substitute UNIX linefeed
657                 if(top_level->get_keypress() == RETURN) 
658                         temp_string[0] = 0xa;
659                 else
660                         temp_string[0] = top_level->get_keypress();
661                 temp_string[1] = 0;
662                 insert_text(temp_string);
663                 find_ibeam(1);
664                 draw();
665                 dispatch_event = 1;
666                 result = 1;
667         }
670 int BC_TextBox::select_whole_text(int select)
672         if (select == 1) 
673         {
674                 highlight_letter1 = 0;
675                 highlight_letter2 = strlen(text);
676                 text_selected = word_selected = 0;      
677                 ibeam_letter = highlight_letter1;
678                 find_ibeam(1);
679                 if(keypress_draw) draw();
680         } else
681         if (select == -1)
682         {
683                 ibeam_letter = strlen(text);
684                 highlight_letter1 = ibeam_letter;
685                 highlight_letter2 = ibeam_letter;
686                 text_selected = word_selected = 0;
687                 find_ibeam(1);
688                 if(keypress_draw) draw();
689         }
690         return highlight_letter2 - highlight_letter1;
693 void BC_TextBox::cycle_textboxes(int amout)
695         top_level->cycle_textboxes(amout);
698 int BC_TextBox::keypress_event()
700 // Result == 2 contents changed
701 // Result == 1 trapped keypress
702 // Result == 0 nothing
703         int result = 0;
704         int text_len;
705         int dispatch_event = 0;
707         if(!active || !enabled) return 0;
709         text_len = strlen(text);
710         last_keypress = get_keypress();
711         switch(get_keypress())
712         {
713                 case ESC:
714                         top_level->deactivate();
715                         result = 0;
716                         break;
718                 case RETURN:
719                         if(rows == 1)
720                         {
721                                 top_level->deactivate();
722                                 dispatch_event = 1;
723                                 result = 0;
724                         }
725                         else
726                         {
727                                 default_keypress(dispatch_event, result);
728                         }
729                         break;
730 // Handle like a default keypress
732                 case TAB:
733                         cycle_textboxes(1);
734                         result = 1;
735                         break;
737                 case LEFTTAB:
738                         cycle_textboxes(-1);
739                         result = 1;
740                         break;
742                 case LEFT:
743                         if(ibeam_letter > 0)
744                         {
745                                 int old_ibeam_letter = ibeam_letter;
746 // Single character
747                                 if(!ctrl_down())
748                                 {
749                                         ibeam_letter--;
750                                 }
751                                 else
752 // Word
753                                 {
754                                         ibeam_letter--;
755                                         while(ibeam_letter > 0 && isalnum(text[ibeam_letter - 1]))
756                                                 ibeam_letter--;
757                                 }
760 // Extend selection
761                                 if(top_level->shift_down())
762                                 {
763 // Initialize highlighting
764                                         if(highlight_letter1 == highlight_letter2)
765                                         {
766                                                 highlight_letter1 = ibeam_letter;
767                                                 highlight_letter2 = old_ibeam_letter;
768                                         }
769                                         else
770 // Extend left highlight
771                                         if(highlight_letter1 == old_ibeam_letter)
772                                         {
773                                                 highlight_letter1 = ibeam_letter;
774                                         }
775                                         else
776 // Shrink right highlight
777                                         if(highlight_letter2 == old_ibeam_letter)
778                                         {
779                                                 highlight_letter2 = ibeam_letter;
780                                         }
781                                 }
782                                 else
783                                 {
784                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
785                                 }
788                                 find_ibeam(1);
789                                 if(keypress_draw) draw();
790                         }
791                         result = 1;
792                         break;
794                 case RIGHT:
795                         if(ibeam_letter < text_len)
796                         {
797                                 int old_ibeam_letter = ibeam_letter;
798 // Single character
799                                 if(!ctrl_down())
800                                 {
801                                         ibeam_letter++;
802                                 }
803                                 else
804 // Word
805                                 {
806                                         while(ibeam_letter < text_len && isalnum(text[ibeam_letter++]))
807                                                 ;
808                                 }
812 // Extend selection
813                                 if(top_level->shift_down())
814                                 {
815 // Initialize highlighting
816                                         if(highlight_letter1 == highlight_letter2)
817                                         {
818                                                 highlight_letter1 = old_ibeam_letter;
819                                                 highlight_letter2 = ibeam_letter;
820                                         }
821                                         else
822 // Shrink left highlight
823                                         if(highlight_letter1 == old_ibeam_letter)
824                                         {
825                                                 highlight_letter1 = ibeam_letter;
826                                         }
827                                         else
828 // Expand right highlight
829                                         if(highlight_letter2 == old_ibeam_letter)
830                                         {
831                                                 highlight_letter2 = ibeam_letter;
832                                         }
833                                 }
834                                 else
835                                 {
836                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
837                                 }
839                                 find_ibeam(1);
840                                 if(keypress_draw) draw();
841                         }
842                         result = 1;
843                         break;
845                 case UP:
846                         if(ibeam_letter > 0)
847                         {
848 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
849                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
850                                         ibeam_y + text_y - text_height);
851 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
853 // Extend selection
854                                 if(top_level->shift_down())
855                                 {
856 // Initialize highlighting
857                                         if(highlight_letter1 == highlight_letter2)
858                                         {
859                                                 highlight_letter1 = new_letter;
860                                                 highlight_letter2 = ibeam_letter;
861                                         }
862                                         else
863 // Expand left highlight
864                                         if(highlight_letter1 == ibeam_letter)
865                                         {
866                                                 highlight_letter1 = new_letter;
867                                         }
868                                         else
869 // Shrink right highlight
870                                         if(highlight_letter2 == ibeam_letter)
871                                         {
872                                                 highlight_letter2 = new_letter;
873                                         }
874                                 }
875                                 else
876                                         highlight_letter1 = highlight_letter2 = new_letter;
878                                 if(highlight_letter1 > highlight_letter2)
879                                 {
880                                         int temp = highlight_letter1;
881                                         highlight_letter1 = highlight_letter2;
882                                         highlight_letter2 = temp;
883                                 }
884                                 ibeam_letter = new_letter;
886                                 find_ibeam(1);
887                                 if(keypress_draw) draw();
888                         }
889                         result = 1;
890                         break;
892                 case PGUP:
893                         if(ibeam_letter > 0)
894                         {
895                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
896                                         ibeam_y + text_y - get_h());
898 // Extend selection
899                                 if(top_level->shift_down())
900                                 {
901 // Initialize highlighting
902                                         if(highlight_letter1 == highlight_letter2)
903                                         {
904                                                 highlight_letter1 = new_letter;
905                                                 highlight_letter2 = ibeam_letter;
906                                         }
907                                         else
908 // Expand left highlight
909                                         if(highlight_letter1 == ibeam_letter)
910                                         {
911                                                 highlight_letter1 = new_letter;
912                                         }
913                                         else
914 // Shrink right highlight
915                                         if(highlight_letter2 == ibeam_letter)
916                                         {
917                                                 highlight_letter2 = new_letter;
918                                         }
919                                 }
920                                 else
921                                         highlight_letter1 = highlight_letter2 = new_letter;
923                                 if(highlight_letter1 > highlight_letter2)
924                                 {
925                                         int temp = highlight_letter1;
926                                         highlight_letter1 = highlight_letter2;
927                                         highlight_letter2 = temp;
928                                 }
929                                 ibeam_letter = new_letter;
931                                 find_ibeam(1);
932                                 if(keypress_draw) draw();
933                         }
934                         result = 1;
935                         break;
937                 case DOWN:
938 //                      if(ibeam_letter > 0)
939                         {
940 // Extend selection
941                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
942                                         ibeam_y + text_y + text_height);
943 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
945                                 if(top_level->shift_down())
946                                 {
947 // Initialize highlighting
948                                         if(highlight_letter1 == highlight_letter2)
949                                         {
950                                                 highlight_letter1 = new_letter;
951                                                 highlight_letter2 = ibeam_letter;
952                                         }
953                                         else
954 // Shrink left highlight
955                                         if(highlight_letter1 == ibeam_letter)
956                                         {
957                                                 highlight_letter1 = new_letter;
958                                         }
959                                         else
960 // Expand right highlight
961                                         if(highlight_letter2 == ibeam_letter)
962                                         {
963                                                 highlight_letter2 = new_letter;
964                                         }
965                                 }
966                                 else
967                                         highlight_letter1 = highlight_letter2 = new_letter;
969                                 if(highlight_letter1 > highlight_letter2)
970                                 {
971                                         int temp = highlight_letter1;
972                                         highlight_letter1 = highlight_letter2;
973                                         highlight_letter2 = temp;
974                                 }
975                                 ibeam_letter = new_letter;
977                                 find_ibeam(1);
978                                 if(keypress_draw) draw();
980 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
981                         }
982                         result = 1;
983                         break;
985                 case PGDN:
986                         {
987 // Extend selection
988                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
989                                         ibeam_y + text_y + get_h());
990 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
992                                 if(top_level->shift_down())
993                                 {
994 // Initialize highlighting
995                                         if(highlight_letter1 == highlight_letter2)
996                                         {
997                                                 highlight_letter1 = new_letter;
998                                                 highlight_letter2 = ibeam_letter;
999                                         }
1000                                         else
1001 // Shrink left highlight
1002                                         if(highlight_letter1 == ibeam_letter)
1003                                         {
1004                                                 highlight_letter1 = new_letter;
1005                                         }
1006                                         else
1007 // Expand right highlight
1008                                         if(highlight_letter2 == ibeam_letter)
1009                                         {
1010                                                 highlight_letter2 = new_letter;
1011                                         }
1012                                 }
1013                                 else
1014                                         highlight_letter1 = highlight_letter2 = new_letter;
1016                                 if(highlight_letter1 > highlight_letter2)
1017                                 {
1018                                         int temp = highlight_letter1;
1019                                         highlight_letter1 = highlight_letter2;
1020                                         highlight_letter2 = temp;
1021                                 }
1022                                 ibeam_letter = new_letter;
1024                                 find_ibeam(1);
1025                                 if(keypress_draw) draw();
1027 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1028                         }
1029                         result = 1;
1030                         break;
1031                 
1032                 case END:
1033                 {
1034                         int old_ibeam_letter = ibeam_letter;
1036                         while(ibeam_letter < text_len && text[ibeam_letter] != '\n')
1037                                 ibeam_letter++;
1039                         if(top_level->shift_down())
1040                         {
1041 // Begin selection
1042                                 if(highlight_letter1 == highlight_letter2)
1043                                 {
1044                                         highlight_letter2 = ibeam_letter;
1045                                         highlight_letter1 = old_ibeam_letter;
1046                                 }
1047                                 else
1048 // Shrink selection
1049                                 if(highlight_letter1 == old_ibeam_letter)
1050                                 {
1051                                         highlight_letter1 = highlight_letter2;
1052                                         highlight_letter2 = ibeam_letter;
1053                                 }
1054                                 else
1055 // Extend selection
1056                                 if(highlight_letter2 == old_ibeam_letter)
1057                                 {
1058                                         highlight_letter2 = ibeam_letter;
1059                                 }
1060                         }
1061                         else
1062                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1064                         find_ibeam(1);
1065                         if(keypress_draw) draw();
1066                         result = 1;
1067                         break;
1068                 }
1070                 case HOME:
1071                 {
1072                         int old_ibeam_letter = ibeam_letter;
1074                         while(ibeam_letter > 0 && text[ibeam_letter - 1] != '\n')
1075                                 ibeam_letter--;
1077                         if(top_level->shift_down())
1078                         {
1079 // Begin selection
1080                                 if(highlight_letter1 == highlight_letter2)
1081                                 {
1082                                         highlight_letter2 = old_ibeam_letter;
1083                                         highlight_letter1 = ibeam_letter;
1084                                 }
1085                                 else
1086 // Extend selection
1087                                 if(highlight_letter1 == old_ibeam_letter)
1088                                 {
1089                                         highlight_letter1 = ibeam_letter;
1090                                 }
1091                                 else
1092 // Shrink selection
1093                                 if(highlight_letter2 == old_ibeam_letter)
1094                                 {
1095                                         highlight_letter2 = highlight_letter1;
1096                                         highlight_letter1 = ibeam_letter;
1097                                 }
1098                         }
1099                         else
1100                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1102                         find_ibeam(1);
1103                         if(keypress_draw) draw();
1104                         result = 1;
1105                         break;
1106                 }
1108         case BACKSPACE:
1109                         if(highlight_letter1 == highlight_letter2)
1110                         {
1111                                 if(ibeam_letter > 0)
1112                                 {
1113                                         delete_selection(ibeam_letter - 1, ibeam_letter, text_len);
1114                                         ibeam_letter--;
1115                                 }
1116                         }
1117                         else
1118                         {
1119                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1120                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1121                         }
1123                         find_ibeam(1);
1124                         if(keypress_draw) draw();
1125                         dispatch_event = 1;
1126                         result = 1;
1127                 break;
1129                 case DELETE:
1130                         if(highlight_letter1 == highlight_letter2)
1131                         {
1132                                 if(ibeam_letter < text_len)
1133                                 {
1134                                         delete_selection(ibeam_letter, ibeam_letter + 1, text_len);
1135                                 }
1136                         }
1137                         else
1138                         {
1139                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1140                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1141                         }
1142                         
1143                         find_ibeam(1);
1144                         if(keypress_draw) draw();
1145                         dispatch_event = 1;
1146                         result = 1;
1147                         break;
1151                 default:
1152                         if(ctrl_down())
1153                         {
1154                                 if(get_keypress() == 'c' || get_keypress() == 'C')
1155                                 {
1156                                         if(highlight_letter1 != highlight_letter2)
1157                                         {
1158                                                 copy_selection(SECONDARY_SELECTION);
1159                                                 result = 1;
1160                                         }
1161                                 }
1162                                 else
1163                                 if(get_keypress() == 'v' || get_keypress() == 'V')
1164                                 {
1165                                         paste_selection(SECONDARY_SELECTION);
1166                                         find_ibeam(1);
1167                                         if(keypress_draw) draw();
1168                                         dispatch_event = 1;
1169                                         result = 1;
1170                                 }
1171                                 else
1172                                 if(get_keypress() == 'x' || get_keypress() == 'X')
1173                                 {
1174                                         if(highlight_letter1 != highlight_letter2)
1175                                         {
1176                                                 copy_selection(SECONDARY_SELECTION);
1177                                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1178                                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1179                                         }
1181                                         find_ibeam(1);
1182                                         if(keypress_draw) draw();
1183                                         dispatch_event = 1;
1184                                         result = 1;
1185                                 }
1186                                 
1187                                 break;
1188                         }
1190                         default_keypress(dispatch_event, result);
1191                         break;
1192         }
1194         if(dispatch_event) skip_cursor->update();
1195         if(dispatch_event) handle_event();
1196 //printf("BC_TextBox::keypress_event 100 %d\n", ibeam_letter);
1197         return result;
1202 int BC_TextBox::uses_text()
1204         return 1;
1207 void BC_TextBox::delete_selection(int letter1, int letter2, int text_len)
1209         int i, j;
1210         
1211         for(i = letter1, j = letter2; j < text_len; i++, j++)
1212         {
1213                 text[i] = text[j];
1214         }
1215         text[i] = 0;
1217         do_separators(1);
1220 void BC_TextBox::insert_text(char *string)
1222         int i, j, text_len, string_len;
1224         string_len = strlen(string);
1225         text_len = strlen(text);
1226         if(highlight_letter1 < highlight_letter2)
1227         {
1228                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1229                 highlight_letter2 = ibeam_letter = highlight_letter1;
1230         }
1232         text_len = strlen(text);
1234         for(i = text_len, j = text_len + string_len; i >= ibeam_letter; i--, j--)
1235                 text[j] = text[i];
1237         for(i = ibeam_letter, j = 0; j < string_len; j++, i++)
1238                 text[i] = string[j];
1240         ibeam_letter += string_len;
1242         do_separators(0);
1245 void BC_TextBox::do_separators(int ibeam_left)
1247         if(separators)
1248         {
1249 // Remove separators from text
1250                 int text_len = strlen(text);
1251                 int separator_len = strlen(separators);
1252                 for(int i = 0; i < text_len; i++)
1253                 {
1254                         if(!isalnum(text[i]))
1255                         {
1256                                 for(int j = i; j < text_len - 1; j++)
1257                                         text[j] = text[j + 1];
1258                                 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1259                                 text_len--;
1260                                 i--;
1261                         }
1262                 }
1263                 text[text_len] = 0;
1270 // Insert separators into text
1271                 for(int i = 0; i < separator_len; i++)
1272                 {
1273                         if(i < text_len)
1274                         {
1275 // Insert a separator
1276                                 if(!isalnum(separators[i]))
1277                                 {
1278                                         for(int j = text_len; j >= i; j--)
1279                                         {
1280                                                 text[j + 1] = text[j];
1281                                         }
1282                                         if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1283                                         text_len++;
1284                                         text[i] = separators[i];
1285                                 }
1286                         }
1287                         else
1288                         if(i >= text_len)
1289                         {
1290                                 text[i] = separators[i];
1291                         }
1292                 }
1294 // Truncate text
1295                 text[separator_len] = 0;
1296         }
1300 void BC_TextBox::get_ibeam_position(int &x, int &y)
1302         int i, j, k, row_begin, row_end, text_len;
1304         text_len = strlen(text);
1305         y = 0;
1306         x = 0;
1307         for(i = 0; i < text_len; )
1308         {
1309                 row_begin = i;
1310                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1311                 {
1312                         text_row[j] = text[i];
1313                 }
1315                 row_end = i;
1316                 text_row[j] = 0;
1318                 if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
1319                 {
1320                         x = get_text_width(font, text_row, ibeam_letter - row_begin);
1321 //printf("BC_TextBox::get_ibeam_position 9 %d %d\n", x, y);
1322                         return;
1323                 }
1325                 if(text[i] == '\n')
1326                 {
1327                         i++;
1328                         y += text_height;
1329                 }
1330         }
1331 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1333         x = 0;
1334         return;
1337 void BC_TextBox::set_text_row(int row)
1339         text_y = -(row * text_height) + top_margin;
1340         draw();
1343 int BC_TextBox::get_text_row()
1345         return -(text_y - top_margin) / text_height;
1348 void BC_TextBox::find_ibeam(int dispatch_event)
1350         int x, y;
1351         int old_x = text_x, old_y = text_y;
1353         get_ibeam_position(x, y);
1355         if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1356         {
1357                 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1358                 if(text_x > left_margin) text_x = left_margin;
1359         }
1360         else
1361         if(left_margin + text_x + x < left_margin)
1362         {
1363                 text_x = -(x - (get_w() / 4)) + left_margin;
1364                 if(text_x > left_margin) text_x = left_margin;
1365         }
1367         while(y + text_y >= get_h() - text_height - bottom_margin)
1368         {
1369                 text_y -= text_height;
1370 //              text_y = -(y - (get_h() / 2)) + top_margin;
1371 //              if(text_y > top_margin) text_y = top_margin;
1372         }
1374         while(y + text_y < top_margin)
1375         {
1376                 text_y += text_height;
1377                 if(text_y > top_margin) 
1378                 {
1379                         text_y = top_margin;
1380                         break;
1381                 }
1382         }
1384         if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1387 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1389         int i, j, k, l, row_begin, row_end, text_len, result = 0, done = 0;
1390         text_len = strlen(text);
1392         if(cursor_y < text_y)
1393         {
1394                 result = 0;
1395                 done = 1;
1396         }
1398         for(i = 0, k = text_y; i < text_len && !done; k += text_height)
1399         {
1400                 row_begin = i;
1401                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1402                 {
1403                         text_row[j] = text[i];
1404                 }
1405                 row_end = i;
1406                 text_row[j] = 0;
1408                 if(cursor_y >= k && cursor_y < k + text_height)
1409                 {
1410                         for(j = 0; j <= row_end - row_begin && !done; j++)
1411                         {
1412                                 l = get_text_width(font, text_row, j) + text_x;
1413                                 if(l > cursor_x)
1414                                 {
1415                                         result = row_begin + j - 1;
1416                                         done = 1;
1417                                 }
1418                         }
1419                         if(!done)
1420                         {
1421                                 result = row_end;
1422                                 done = 1;
1423                         }
1424                 }
1425                 if(text[i] == '\n') i++;
1426                 
1427                 if(i >= text_len && !done)
1428                 {
1429                         result = text_len;
1430                 }
1431         }
1432         if(result < 0) result = 0;
1433         if(result > text_len) result = text_len;
1434         return result;
1437 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
1439         int text_len = strlen(text);
1440         letter1 = letter2 = ibeam_letter;
1441         do
1442         {
1443                 if(isalnum(text[letter1])) letter1--;
1444         }while(letter1 > 0 && isalnum(text[letter1]));
1445         if(!isalnum(text[letter1])) letter1++;
1447         do
1448         {
1449                 if(isalnum(text[letter2])) letter2++;
1450         }while(letter2 < text_len && isalnum(text[letter2]));
1451         if(letter2 < text_len && text[letter2] == ' ') letter2++;
1453         if(letter1 < 0) letter1 = 0;
1454         if(letter2 < 0) letter2 = 0;
1455         if(letter1 > text_len) letter1 = text_len;
1456         if(letter2 > text_len) letter2 = text_len;
1459 void BC_TextBox::copy_selection(int clipboard_num)
1461         int text_len = strlen(text);
1463         if(highlight_letter1 >= text_len ||
1464                 highlight_letter2 > text_len ||
1465                 highlight_letter1 < 0 ||
1466                 highlight_letter2 < 0 ||
1467                 highlight_letter2 - highlight_letter1 <= 0) return;
1469         get_clipboard()->to_clipboard(&text[highlight_letter1], 
1470                 highlight_letter2 - highlight_letter1, 
1471                 clipboard_num);
1474 void BC_TextBox::paste_selection(int clipboard_num)
1476         int len = get_clipboard()->clipboard_len(clipboard_num);
1477         if(len)
1478         {
1479                 char *string = new char[len + 1];
1480                 get_clipboard()->from_clipboard(string, len, clipboard_num);
1481                 insert_text(string);
1482         }
1485 void BC_TextBox::set_keypress_draw(int value)
1487         keypress_draw = value;
1490 int BC_TextBox::get_last_keypress()
1492         return last_keypress;
1495 int BC_TextBox::get_ibeam_letter()
1497         return ibeam_letter;
1500 void BC_TextBox::set_ibeam_letter(int number, int redraw)
1502         this->ibeam_letter = number;
1503         if(redraw)
1504         {
1505                 draw();
1506         }
1509 void BC_TextBox::set_separators(char *separators)
1511         this->separators = separators;
1529 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window, 
1530         int x, 
1531         int y, 
1532         int w,
1533         int rows,
1534         char *default_text)
1536         this->parent_window = parent_window;
1537         this->x = x;
1538         this->y = y;
1539         this->w = w;
1540         this->rows = rows;
1541         this->default_text = default_text;
1544 BC_ScrollTextBox::~BC_ScrollTextBox()
1546         delete yscroll;
1547         if(text)
1548         {
1549                 text->gui = 0;
1550                 delete text;
1551         }
1554 void BC_ScrollTextBox::create_objects()
1556 // Must be created first
1557         parent_window->add_subwindow(text = new BC_ScrollTextBoxText(this));
1558         parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
1561 int BC_ScrollTextBox::handle_event()
1563         return 1;
1566 int BC_ScrollTextBox::get_x()
1568         return x;
1571 int BC_ScrollTextBox::get_y()
1573         return y;
1576 int BC_ScrollTextBox::get_w()
1578         return w;
1581 int BC_ScrollTextBox::get_rows()
1583         return rows;
1587 char* BC_ScrollTextBox::get_text()
1589         return text->get_text();
1592 void BC_ScrollTextBox::update(char *text)
1594         this->text->update(text);
1595         yscroll->update_length(this->text->get_text_rows(),
1596                 this->text->get_text_row(),
1597                 yscroll->get_handlelength());
1600 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
1602         this->x = x;
1603         this->y = y;
1604         this->w = w;
1605         this->rows = rows;
1606         text->reposition_window(x, 
1607                 y, 
1608                 w - yscroll->get_span(), 
1609                 rows);
1610         yscroll->reposition_window(x + w - yscroll->get_span(), 
1611                 y, 
1612                 BC_TextBox::calculate_row_h(rows, 
1613                         parent_window));
1614         yscroll->update_length(text->get_text_rows(),
1615                 text->get_text_row(),
1616                 rows);
1627 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui)
1628  : BC_TextBox(gui->x, 
1629         gui->y, 
1630         gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1631         gui->rows,
1632         gui->default_text)
1634         this->gui = gui;
1637 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
1639         if(gui)
1640         {
1641                 gui->text = 0;
1642                 delete gui;
1643         }
1646 int BC_ScrollTextBoxText::handle_event()
1648         gui->yscroll->update_length(get_text_rows(),
1649                 get_text_row(),
1650                 gui->yscroll->get_handlelength());
1651         return gui->handle_event();
1654 int BC_ScrollTextBoxText::motion_event()
1656         gui->yscroll->update_length(get_text_rows(),
1657                 get_text_row(),
1658                 gui->yscroll->get_handlelength());
1659         return 1;
1663 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
1664  : BC_ScrollBar(gui->x + 
1665                         gui->w - 
1666                         get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1667                 gui->y, 
1668                 SCROLL_VERT, 
1669                 BC_TextBox::calculate_row_h(gui->rows, 
1670                         gui->parent_window), 
1671                 gui->text->get_text_rows(), 
1672                 0, 
1673                 gui->rows)
1675         this->gui = gui;
1678 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
1682 int BC_ScrollTextBoxYScroll::handle_event()
1684         gui->text->set_text_row(get_position());
1685         return 1;
1697 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y)
1698  : BC_TextBox(x, y, popup->text_w, 1, popup->default_text)
1700         this->popup = popup;
1703 BC_PopupTextBoxText::~BC_PopupTextBoxText()
1705         if(popup)
1706         {
1707                 popup->textbox = 0;
1708                 delete popup;
1709                 popup = 0;
1710         }
1714 int BC_PopupTextBoxText::handle_event()
1716         popup->handle_event();
1717         return 1;
1720 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
1721  : BC_ListBox(x,
1722         y,
1723         popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
1724         popup->list_h,
1725         LISTBOX_TEXT,
1726         popup->list_items,
1727         0,
1728         0,
1729         1,
1730         0,
1731         1)
1733         this->popup = popup;
1735 int BC_PopupTextBoxList::handle_event()
1737         popup->textbox->update(get_selection(0, 0)->get_text());
1738         popup->handle_event();
1739         return 1;
1745 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window, 
1746                 ArrayList<BC_ListBoxItem*> *list_items,
1747                 char *default_text,
1748                 int x, 
1749                 int y, 
1750                 int text_w,
1751                 int list_h)
1753         this->x = x;
1754         this->y = y;
1755         this->list_h = list_h;
1756         this->default_text = default_text;
1757         this->text_w = text_w;
1758         this->parent_window = parent_window;
1759         this->list_items = list_items;
1762 BC_PopupTextBox::~BC_PopupTextBox()
1764         delete listbox;
1765         if(textbox) 
1766         {
1767                 textbox->popup = 0;
1768                 delete textbox;
1769         }
1772 int BC_PopupTextBox::create_objects()
1774         int x = this->x, y = this->y;
1775         parent_window->add_subwindow(textbox = new BC_PopupTextBoxText(this, x, y));
1776         x += textbox->get_w();
1777         parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
1778         return 0;
1781 void BC_PopupTextBox::update(char *text)
1783         textbox->update(text);
1786 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
1788         listbox->update(data, 
1789                 0, 
1790                 0,
1791                 1);
1795 char* BC_PopupTextBox::get_text()
1797         return textbox->get_text();
1800 int BC_PopupTextBox::get_number()
1802         return listbox->get_selection_number(0, 0);
1805 int BC_PopupTextBox::get_x()
1807         return x;
1810 int BC_PopupTextBox::get_y()
1812         return y;
1815 int BC_PopupTextBox::get_w()
1817         return textbox->get_w() + listbox->get_w();
1820 int BC_PopupTextBox::get_h()
1822         return textbox->get_h();
1825 int BC_PopupTextBox::handle_event()
1827         return 1;
1830 void BC_PopupTextBox::reposition_window(int x, int y)
1832         this->x = x;
1833         this->y = y;
1834         int x1 = x, y1 = y;
1835         textbox->reposition_window(x1, y1);
1836         x1 += textbox->get_w();
1837         listbox->reposition_window(x1, y1);
1853 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1854         int64_t default_value,
1855         int64_t min,
1856         int64_t max,
1857         int x, 
1858         int y)
1859  : BC_TextBox(x, 
1860         y, 
1861         popup->text_w, 
1862         1, 
1863         default_value)
1865         this->popup = popup;
1868 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1869         float default_value,
1870         float min,
1871         float max,
1872         int x, 
1873         int y)
1874  : BC_TextBox(x, 
1875         y, 
1876         popup->text_w, 
1877         1, 
1878         default_value)
1880         this->popup = popup;
1883 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
1885         if(popup)
1886         {
1887                 popup->textbox = 0;
1888                 delete popup;
1889                 popup = 0;
1890         }
1895 int BC_TumbleTextBoxText::handle_event()
1897         popup->handle_event();
1898         return 1;
1901 int BC_TumbleTextBoxText::button_press_event()
1903         if(is_event_win())
1904         {
1905                 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
1906                 if(get_buttonpress() == 4)
1907                 {
1908                         popup->tumbler->handle_up_event();
1909                 }
1910                 else
1911                 if(get_buttonpress() == 5)
1912                 {
1913                         popup->tumbler->handle_down_event();
1914                 }
1915                 return 1;
1916         }
1917         return 0;
1923 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1924                 int64_t default_value,
1925                 int64_t min,
1926                 int64_t max,
1927                 int x, 
1928                 int y, 
1929                 int text_w)
1931         reset();
1932         this->x = x;
1933         this->y = y;
1934         this->min = min;
1935         this->max = max;
1936         this->default_value = default_value;
1937         this->text_w = text_w;
1938         this->parent_window = parent_window;
1939         use_float = 0;
1940         precision = 4;
1941         increment = 1;
1944 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1945                 int default_value,
1946                 int min,
1947                 int max,
1948                 int x, 
1949                 int y, 
1950                 int text_w)
1952         reset();
1953         this->x = x;
1954         this->y = y;
1955         this->min = min;
1956         this->max = max;
1957         this->default_value = default_value;
1958         this->text_w = text_w;
1959         this->parent_window = parent_window;
1960         use_float = 0;
1961         precision = 4;
1962         increment = 1;
1965 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1966                 float default_value_f,
1967                 float min_f,
1968                 float max_f,
1969                 int x, 
1970                 int y, 
1971                 int text_w)
1973         reset();
1974         this->x = x;
1975         this->y = y;
1976         this->min_f = min_f;
1977         this->max_f = max_f;
1978         this->default_value_f = default_value_f;
1979         this->text_w = text_w;
1980         this->parent_window = parent_window;
1981         use_float = 1;
1982         precision = 4;
1983         increment = 1;
1986 BC_TumbleTextBox::~BC_TumbleTextBox()
1988 // Recursive delete.  Normally ~BC_TumbleTextBox is never called but textbox
1989 // is deleted anyway by the windowbase so textbox deletes this.
1990         if(tumbler) delete tumbler;
1991         tumbler = 0;
1992 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
1993         if(textbox)
1994         {
1995                 textbox->popup = 0;
1996                 delete textbox;
1997         }
1998         textbox = 0;
2001 void BC_TumbleTextBox::reset()
2003         textbox = 0;
2004         tumbler = 0;
2005         increment = 1.0;
2008 void BC_TumbleTextBox::set_precision(int precision)
2010         this->precision = precision;
2013 void BC_TumbleTextBox::set_increment(float value)
2015         this->increment = value;
2016         if(tumbler) tumbler->set_increment(value);
2019 int BC_TumbleTextBox::create_objects()
2021         int x = this->x, y = this->y;
2023         if(use_float)
2024         {
2025                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
2026                         default_value_f,
2027                         min_f, 
2028                         max_f, 
2029                         x, 
2030                         y));
2031                 textbox->set_precision(precision);
2032         }
2033         else
2034                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
2035                         default_value,
2036                         min, 
2037                         max, 
2038                         x, 
2039                         y));
2041         x += textbox->get_w();
2043         if(use_float)
2044                 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox, 
2045                         min_f,
2046                         max_f,
2047                         x, 
2048                         y));
2049         else
2050                 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox, 
2051                         min, 
2052                         max, 
2053                         x, 
2054                         y));
2056         tumbler->set_increment(increment);
2057         return 0;
2060 char* BC_TumbleTextBox::get_text()
2062         return textbox->get_text();
2065 int BC_TumbleTextBox::update(char *value)
2067         textbox->update(value);
2068         return 0;
2071 int BC_TumbleTextBox::update(int64_t value)
2073         textbox->update(value);
2074         return 0;
2077 int BC_TumbleTextBox::update(float value)
2079         textbox->update(value);
2080         return 0;
2084 int BC_TumbleTextBox::get_x()
2086         return x;
2089 int BC_TumbleTextBox::get_y()
2091         return y;
2094 int BC_TumbleTextBox::get_w()
2096         return textbox->get_w() + tumbler->get_w();
2099 int BC_TumbleTextBox::get_h()
2101         return textbox->get_h();
2104 int BC_TumbleTextBox::handle_event()
2106         return 1;
2109 int BC_TumbleTextBox::reposition_widget(int x, int y, int w, int h) {
2110         reposition_window(x, y);
2111         return(0);
2114 void BC_TumbleTextBox::reposition_window(int x, int y)
2116         this->x = x;
2117         this->y = y;
2118         
2119         textbox->reposition_window(x, 
2120                 y, 
2121                 text_w, 
2122                 1);
2123         tumbler->reposition_window(x + textbox->get_w(),
2124                 y);
2128 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2130         tumbler->set_boundaries(min, max);
2133 void BC_TumbleTextBox::set_boundaries(float min, float max)
2135         tumbler->set_boundaries(min, max);