r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / guicast / bctextbox.C
blob58be4ddfe8cfc639f94a6087c76154d467aacac5
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 BC_TextBox::BC_TextBox(int x, 
17         int y, 
18         int w, 
19         int rows, 
20         char *text, 
21         int has_border, 
22         int font)
23  : BC_SubWindow(x, y, w, 0, -1)
25         skip_cursor = 0;
26         reset_parameters(rows, has_border, font);
27         strcpy(this->text, text);
30 BC_TextBox::BC_TextBox(int x, 
31         int y, 
32         int w, 
33         int rows, 
34         int64_t text, 
35         int has_border, 
36         int font)
37  : BC_SubWindow(x, y, w, 0, -1)
39         skip_cursor = 0;
40         reset_parameters(rows, has_border, font);
41         sprintf(this->text, "%lld", text);
44 BC_TextBox::BC_TextBox(int x, 
45         int y, 
46         int w, 
47         int rows, 
48         float text, 
49         int has_border, 
50         int font)
51  : BC_SubWindow(x, y, w, 0, -1)
53         skip_cursor = 0;
54         reset_parameters(rows, has_border, font);
55         sprintf(this->text, "%0.4f", text);
58 BC_TextBox::BC_TextBox(int x, 
59         int y, 
60         int w, 
61         int rows, 
62         int text, 
63         int has_border, 
64         int font)
65  : BC_SubWindow(x, y, w, 0, -1)
67         skip_cursor = 0;
68         reset_parameters(rows, has_border, font);
69         sprintf(this->text, "%d", text);
72 BC_TextBox::~BC_TextBox()
74         if(skip_cursor) delete skip_cursor;
77 int BC_TextBox::reset_parameters(int rows, int has_border, int font)
79         this->rows = rows;
80         this->has_border = has_border;
81         this->font = font;
82         text_start = 0;
83         text_end = 0;
84         highlight_letter1 = highlight_letter2 = 0;
85         highlight_letter3 = highlight_letter4 = 0;
86         ibeam_letter = 0;
87         active = 0;
88         text_selected = word_selected = 0;
89         text_x = 0;
90         enabled = 1;
91         highlighted = 0;
92         precision = 4;
93         if (!skip_cursor)
94                 skip_cursor = new Timer;
95         keypress_draw = 1;
96         last_keypress = 0;
97         separators = 0;
98         return 0;
101 int BC_TextBox::initialize()
103         if (!skip_cursor)
104                 skip_cursor = new Timer;
105         skip_cursor->update();
106 // Get dimensions
107         text_ascent = get_text_ascent(font) + 1;
108         text_descent = get_text_descent(font) + 1;
109         text_height = text_ascent + text_descent;
110         ibeam_letter = strlen(text);
111         if(has_border)
112         {
113                 left_margin = right_margin = 4;
114                 top_margin = bottom_margin = 2;
115         }
116         else
117         {
118                 left_margin = right_margin = 2;
119                 top_margin = bottom_margin = 0;
120         }
121         h = get_row_h(rows);
122         text_x = left_margin;
123         text_y = top_margin;
124         find_ibeam(0);
126 // Create the subwindow
127         BC_SubWindow::initialize();
129         if(has_border)
130         {
131                 back_color = WHITE;
132                 high_color = LTYELLOW;
133         }
134         else 
135         {
136                 high_color = LTGREY;
137                 back_color = bg_color;
138         }
140         draw();
141         set_cursor(IBEAM_CURSOR);
142         return 0;
145 void BC_TextBox::set_precision(int precision)
147         this->precision = precision;
150 int BC_TextBox::update(char *text)
152 //printf("BC_TextBox::update 1 %d %s %s\n", strcmp(text, this->text), text, this->text);
153         int text_len = strlen(text);
154 // Don't update if contents are the same
155         if(!strcmp(text, this->text)) return 0;
158         strcpy(this->text, text);
159         if(highlight_letter1 > text_len) highlight_letter1 = text_len;
160         if(highlight_letter2 > text_len) highlight_letter2 = text_len;
161         if(ibeam_letter > text_len) ibeam_letter = text_len;
162         draw();
163         return 0;
166 int BC_TextBox::update(int64_t value)
168         char string[BCTEXTLEN];
169         sprintf(string, "%lld", value);
172         update(string);
173         return 0;
176 int BC_TextBox::update(float value)
178         char string[BCTEXTLEN];
179         sprintf(string, "%f", value);
180         char *ptr = strchr(string, '.');
182         if(ptr) ptr[precision + 1] = 0;
184         update(string);
185         return 0;
188 void BC_TextBox::disable()
190         if(enabled)
191         {
192                 enabled = 0;
193                 if(active) top_level->deactivate();
194                 draw();
195         }
198 void BC_TextBox::enable()
200         if(!enabled)
201         {
202                 enabled = 1;
203                 draw();
204         }
207 int BC_TextBox::get_enabled()
209         return enabled;
212 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
214         return (pixels - 4) / 
215                 (window->get_text_ascent(font) + 1 + 
216                         window->get_text_descent(font) + 1);
219 int BC_TextBox::calculate_row_h(int rows, 
220         BC_WindowBase *parent_window, 
221         int has_border, 
222         int font)
224         return rows * 
225                 (parent_window->get_text_ascent(font) + 1 + 
226                 parent_window->get_text_descent(font) + 1) +
227                 (has_border ? 4 : 0);
230 char* BC_TextBox::get_text()
232         return text;
235 int BC_TextBox::get_text_rows()
237         int text_len = strlen(text);
238         int result = 1;
239         for(int i = 0; i < text_len; i++)
240         {
241                 if(text[i] == 0xa) result++;
242         }
243         return result;
247 int BC_TextBox::get_row_h(int rows)
249         return rows * text_height + top_margin + bottom_margin;
252 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
254         int new_h = get_h();
255         if(w < 0) w = get_w();
256         if(rows != -1)
257         {
258                 new_h = get_row_h(rows);
259                 this->rows = rows;
260         }
262         if(x != get_x() || 
263                 y != get_y() || 
264                 w != get_w() || 
265                 new_h != get_h())
266         {
267 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
268 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
269                 BC_WindowBase::reposition_window(x, y, w, new_h);
270                 draw();
271         }
272         return 0;
275 void BC_TextBox::draw_border()
277 // Clear margins
278         set_color(background_color);
279         draw_box(0, 0, left_margin, get_h());
280         draw_box(get_w() - right_margin, 0, right_margin, get_h());
282         if(has_border)
283         {
284                 if(highlighted)
285                         draw_3d_border(0, 0, w, h,
286                                 top_level->get_resources()->button_shadow, 
287                                 top_level->get_resources()->button_uphighlighted,
288                                 top_level->get_resources()->button_highlighted,
289                                 top_level->get_resources()->button_light);
290                 else
291                         draw_3d_border(0, 0, w, h, 
292                                 top_level->get_resources()->button_shadow, 
293                                 BLACK, 
294                                 top_level->get_resources()->button_up,
295                                 top_level->get_resources()->button_light);
296         }
299 void BC_TextBox::draw_cursor()
301         set_color(background_color);
302         set_inverse();
304         draw_box(ibeam_x + text_x, 
305                 ibeam_y + text_y, 
306                 BCCURSORW, 
307                 text_height);
308         set_opaque();
312 void BC_TextBox::draw()
314         int i, j, k, text_len;
315         int row_begin, row_end;
316         int highlight_x1, highlight_x2;
317         int need_ibeam = 1;
319 //printf("BC_TextBox::draw 1 %s\n", text);
320 // Background
321         if(has_border)
322         {
323                 background_color = WHITE;
324         }
325         else
326         {
327                 if(highlighted)
328                 {
329                         background_color = high_color;
330                 }
331                 else
332                 {
333                         background_color = back_color;
334                 }
335         }
337         set_color(background_color);
338         draw_box(0, 0, w, h);
340 // Draw text with selection
341         set_font(font);
342         text_len = strlen(text);
343 //printf("BC_TextBox::draw 0 %s %d %d %d %d\n", text, text_y, text_len, get_w(), text_height);
345         for(i = 0, k = text_y; i < text_len && k < get_h(); k += text_height)
346         {
347 // Draw row of text
348                 if(text[i] == '\n') i++;
349                 row_begin = i;
350                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
351                 {
352                         text_row[j] = text[i];
353                 }
354                 row_end = i;
355                 text_row[j] = 0;
357 //printf("BC_TextBox::draw 1 %d %d %c\n", row_begin, row_end, text_row[j - 1]);
359                 if(k > -text_height + top_margin && k < get_h() - bottom_margin)
360                 {
361 // Draw highlighted region of row
362                         if(highlight_letter2 > highlight_letter1 &&
363                                 highlight_letter2 > row_begin && highlight_letter1 < row_end)
364                         {
365                                 if(active && enabled && get_has_focus())
366                                         set_color(top_level->get_resources()->text_highlight);
367                                 else
368                                         set_color(MEGREY);
370                                 if(highlight_letter1 >= row_begin && highlight_letter1 < row_end)
371                                         highlight_x1 = get_text_width(font, text_row, highlight_letter1 - row_begin);
372                                 else
373                                         highlight_x1 = 0;
375                                 if(highlight_letter2 > row_begin && highlight_letter2 <= row_end)
376                                         highlight_x2 = get_text_width(font, text_row, highlight_letter2 - row_begin);
377                                 else
378                                         highlight_x2 = get_w();
380                                 draw_box(highlight_x1 + text_x, 
381                                         k, 
382                                         highlight_x2 - highlight_x1, 
383                                         text_height);
384                         }
386 // Draw text over highlight
387                         if(enabled)
388                                 set_color(BLACK);
389                         else
390                                 set_color(MEGREY);
392                         draw_text(text_x, k + text_ascent, text_row);
394 // Get ibeam location
395                         if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
396                         {
397                                 need_ibeam = 0;
398                                 ibeam_y = k - text_y;
399                                 ibeam_x = get_text_width(font, text_row, ibeam_letter - row_begin);
400                         }
401                 }
402         }
404 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
405         if(need_ibeam)
406         {
407                 ibeam_x = 0;
408                 ibeam_y = 0;
409         }
411 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
412 // Draw solid cursor
413 //      if(!active)
414 //      {
415                 draw_cursor();
416 //      }
418 // Border
419         draw_border();
420         flash();
421         flush();   
424 int BC_TextBox::focus_in_event()
426         draw();
427         return 1;
430 int BC_TextBox::focus_out_event()
432         draw();
433         return 1;
436 int BC_TextBox::cursor_enter_event()
438         if(top_level->event_win == win && enabled)
439         {
440                 tooltip_done = 0;
442                 if(!highlighted)
443                 {
444                         highlighted = 1;
445                         draw_border();
446                         flash();
447                         flush();   
448                 }
449         }
450         return 0;
453 int BC_TextBox::cursor_leave_event()
455         if(highlighted)
456         {
457                 highlighted = 0;
458                 draw_border();
459                 hide_tooltip();
460                 flash();
461                 flush();   
462         }
463         return 0;
466 int BC_TextBox::button_press_event()
468         if(get_buttonpress() > 2) return 0;
470         int cursor_letter = 0;
471         int text_len = strlen(text);
473         if(!enabled) return 0;
475         if(top_level->event_win == win)
476         {
477                 if(!active)
478                 {
479                         hide_tooltip();
480                         top_level->deactivate();
481                         activate();
482                 }
484                 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
485                 if(get_double_click())
486                 {
487                         word_selected = 1;
488                         select_word(highlight_letter1, highlight_letter2, cursor_letter);
489                         highlight_letter3 = highlight_letter1;
490                         highlight_letter4 = highlight_letter2;
491                         ibeam_letter = highlight_letter2;
492                         copy_selection(PRIMARY_SELECTION);
493                 }
494                 else
495                 if(get_buttonpress() == 2)
496                 {
497                         highlight_letter3 = highlight_letter4 = 
498                                 ibeam_letter = highlight_letter1 = 
499                                 highlight_letter2 = cursor_letter;
500                         paste_selection(PRIMARY_SELECTION);
501                 }
502                 else
503                 {
504                         text_selected = 1;
505                         highlight_letter3 = highlight_letter4 = 
506                                 ibeam_letter = highlight_letter1 = 
507                                 highlight_letter2 = cursor_letter;
508                 }
509                 
510                 if(ibeam_letter < 0) ibeam_letter = 0;
511                 if(ibeam_letter > text_len) ibeam_letter = text_len;
512                 draw();
513                 return 1;
514         }
515         else
516         if(active)
517         {
518                 top_level->deactivate();
519         }
521         return 0;
524 int BC_TextBox::button_release_event()
526         if(active)
527         {
528                 hide_tooltip();
529                 if(text_selected || word_selected)
530                 {
531                         text_selected = 0;
532                         word_selected = 0;
533                 }
534         }
535         return 0;
538 int BC_TextBox::cursor_motion_event()
540         int cursor_letter, text_len = strlen(text), letter1, letter2;
541         if(active)
542         {
543                 if(text_selected || word_selected)
544                 {
545                         cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
546                         if(word_selected)
547                         {
548                                 select_word(letter1, letter2, cursor_letter);
549                         }
550                         else
551                         if(text_selected)
552                         {
553                                 letter1 = letter2 = cursor_letter;
554                         }
556                         if(letter1 <= highlight_letter3)
557                         {
558                                 highlight_letter1 = letter1;
559                                 highlight_letter2 = highlight_letter4;
560                                 ibeam_letter = letter1;
561                         }
562                         else
563                         if(letter2 >= highlight_letter4)
564                         {
565                                 highlight_letter2 = letter2;
566                                 highlight_letter1 = highlight_letter3;
567                                 ibeam_letter = letter2;
568                         }
569                         
570                         copy_selection(PRIMARY_SELECTION);
571                         find_ibeam(1);
572                         draw();
573                         return 1;
574                 }
575         }
576         return 0;
579 int BC_TextBox::activate()
581         top_level->active_subwindow = this;
582         active = 1;
583         draw();
584         top_level->set_repeat(top_level->get_resources()->blink_rate);
585         return 0;
588 int BC_TextBox::deactivate()
590         active = 0;
591         top_level->unset_repeat(top_level->get_resources()->blink_rate);
592         draw();
593         return 0;
596 int BC_TextBox::repeat_event(int64_t duration)
598         int result = 0;
600         if(duration == top_level->get_resources()->tooltip_delay &&
601                 tooltip_text[0] != 0 &&
602                 highlighted)
603         {
604                 show_tooltip();
605                 tooltip_done = 1;
606                 result = 1;
607         }
608                 
609         if(duration == top_level->get_resources()->blink_rate && 
610                 active &&
611                 get_has_focus())
612         {
613                 if(skip_cursor->get_difference() < duration)
614                 {
615 // printf("BC_TextBox::repeat_event 1 %lld %lld\n", 
616 // skip_cursor->get_difference(), 
617 // duration);
618                         return 1;
619                 }
620                 draw_cursor();
621                 flash();
622                 flush();   
623                 result = 1;
624         }
625         return result;
628 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
630     if((top_level->get_keypress() == RETURN) ||
631 //              (top_level->get_keypress() > 30 && top_level->get_keypress() < 127))
632                 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255))
633         {
634 // Substitute UNIX linefeed
635                 if(top_level->get_keypress() == RETURN) 
636                         temp_string[0] = 0xa;
637                 else
638                         temp_string[0] = top_level->get_keypress();
639                 temp_string[1] = 0;
640                 insert_text(temp_string);
641                 find_ibeam(1);
642                 draw();
643                 dispatch_event = 1;
644                 result = 1;
645         }
648 int BC_TextBox::select_whole_text(int select)
650         if (select == 1) 
651         {
652                 highlight_letter1 = 0;
653                 highlight_letter2 = strlen(text);
654                 text_selected = word_selected = 0;      
655                 ibeam_letter = highlight_letter1;
656                 find_ibeam(1);
657                 if(keypress_draw) draw();
658         } else
659         if (select == -1)
660         {
661                 ibeam_letter = strlen(text);
662                 highlight_letter1 = ibeam_letter;
663                 highlight_letter2 = ibeam_letter;
664                 text_selected = word_selected = 0;
665                 find_ibeam(1);
666                 if(keypress_draw) draw();
667         }
668         return highlight_letter2 - highlight_letter1;
671 void BC_TextBox::cycle_textboxes(int amout)
673         top_level->cycle_textboxes(amout);
676 int BC_TextBox::keypress_event()
678 // Result == 2 contents changed
679 // Result == 1 trapped keypress
680 // Result == 0 nothing
681         int result = 0;
682         int text_len;
683         int dispatch_event = 0;
685         if(!active || !enabled) return 0;
687         text_len = strlen(text);
688         last_keypress = get_keypress();
689         switch(get_keypress())
690         {
691                 case ESC:
692                         top_level->deactivate();
693                         result = 0;
694                         break;
696                 case RETURN:
697                         if(rows == 1)
698                         {
699                                 top_level->deactivate();
700                                 dispatch_event = 1;
701                                 result = 0;
702                         }
703                         else
704                         {
705                                 default_keypress(dispatch_event, result);
706                         }
707                         break;
708 // Handle like a default keypress
710                 case TAB:
711                         cycle_textboxes(1);
712                         result = 1;
713                         break;
715                 case LEFTTAB:
716                         cycle_textboxes(-1);
717                         result = 1;
718                         break;
720                 case LEFT:
721                         if(ibeam_letter > 0)
722                         {
723                                 int old_ibeam_letter = ibeam_letter;
724 // Single character
725                                 if(!ctrl_down())
726                                 {
727                                         ibeam_letter--;
728                                 }
729                                 else
730 // Word
731                                 {
732                                         ibeam_letter--;
733                                         while(ibeam_letter > 0 && isalnum(text[ibeam_letter - 1]))
734                                                 ibeam_letter--;
735                                 }
738 // Extend selection
739                                 if(top_level->shift_down())
740                                 {
741 // Initialize highlighting
742                                         if(highlight_letter1 == highlight_letter2)
743                                         {
744                                                 highlight_letter1 = ibeam_letter;
745                                                 highlight_letter2 = old_ibeam_letter;
746                                         }
747                                         else
748 // Extend left highlight
749                                         if(highlight_letter1 == old_ibeam_letter)
750                                         {
751                                                 highlight_letter1 = ibeam_letter;
752                                         }
753                                         else
754 // Shrink right highlight
755                                         if(highlight_letter2 == old_ibeam_letter)
756                                         {
757                                                 highlight_letter2 = ibeam_letter;
758                                         }
759                                 }
760                                 else
761                                 {
762                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
763                                 }
766                                 find_ibeam(1);
767                                 if(keypress_draw) draw();
768                         }
769                         result = 1;
770                         break;
772                 case RIGHT:
773                         if(ibeam_letter < text_len)
774                         {
775                                 int old_ibeam_letter = ibeam_letter;
776 // Single character
777                                 if(!ctrl_down())
778                                 {
779                                         ibeam_letter++;
780                                 }
781                                 else
782 // Word
783                                 {
784                                         while(ibeam_letter < text_len && isalnum(text[ibeam_letter++]))
785                                                 ;
786                                 }
790 // Extend selection
791                                 if(top_level->shift_down())
792                                 {
793 // Initialize highlighting
794                                         if(highlight_letter1 == highlight_letter2)
795                                         {
796                                                 highlight_letter1 = old_ibeam_letter;
797                                                 highlight_letter2 = ibeam_letter;
798                                         }
799                                         else
800 // Shrink left highlight
801                                         if(highlight_letter1 == old_ibeam_letter)
802                                         {
803                                                 highlight_letter1 = ibeam_letter;
804                                         }
805                                         else
806 // Expand right highlight
807                                         if(highlight_letter2 == old_ibeam_letter)
808                                         {
809                                                 highlight_letter2 = ibeam_letter;
810                                         }
811                                 }
812                                 else
813                                 {
814                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
815                                 }
817                                 find_ibeam(1);
818                                 if(keypress_draw) draw();
819                         }
820                         result = 1;
821                         break;
823                 case UP:
824                         if(ibeam_letter > 0)
825                         {
826 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
827                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
828                                         ibeam_y + text_y - text_height);
829 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
831 // Extend selection
832                                 if(top_level->shift_down())
833                                 {
834 // Initialize highlighting
835                                         if(highlight_letter1 == highlight_letter2)
836                                         {
837                                                 highlight_letter1 = new_letter;
838                                                 highlight_letter2 = ibeam_letter;
839                                         }
840                                         else
841 // Expand left highlight
842                                         if(highlight_letter1 == ibeam_letter)
843                                         {
844                                                 highlight_letter1 = new_letter;
845                                         }
846                                         else
847 // Shrink right highlight
848                                         if(highlight_letter2 == ibeam_letter)
849                                         {
850                                                 highlight_letter2 = new_letter;
851                                         }
852                                 }
853                                 else
854                                         highlight_letter1 = highlight_letter2 = new_letter;
856                                 if(highlight_letter1 > highlight_letter2)
857                                 {
858                                         int temp = highlight_letter1;
859                                         highlight_letter1 = highlight_letter2;
860                                         highlight_letter2 = temp;
861                                 }
862                                 ibeam_letter = new_letter;
864                                 find_ibeam(1);
865                                 if(keypress_draw) draw();
866                         }
867                         result = 1;
868                         break;
870                 case PGUP:
871                         if(ibeam_letter > 0)
872                         {
873                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
874                                         ibeam_y + text_y - get_h());
876 // Extend selection
877                                 if(top_level->shift_down())
878                                 {
879 // Initialize highlighting
880                                         if(highlight_letter1 == highlight_letter2)
881                                         {
882                                                 highlight_letter1 = new_letter;
883                                                 highlight_letter2 = ibeam_letter;
884                                         }
885                                         else
886 // Expand left highlight
887                                         if(highlight_letter1 == ibeam_letter)
888                                         {
889                                                 highlight_letter1 = new_letter;
890                                         }
891                                         else
892 // Shrink right highlight
893                                         if(highlight_letter2 == ibeam_letter)
894                                         {
895                                                 highlight_letter2 = new_letter;
896                                         }
897                                 }
898                                 else
899                                         highlight_letter1 = highlight_letter2 = new_letter;
901                                 if(highlight_letter1 > highlight_letter2)
902                                 {
903                                         int temp = highlight_letter1;
904                                         highlight_letter1 = highlight_letter2;
905                                         highlight_letter2 = temp;
906                                 }
907                                 ibeam_letter = new_letter;
909                                 find_ibeam(1);
910                                 if(keypress_draw) draw();
911                         }
912                         result = 1;
913                         break;
915                 case DOWN:
916 //                      if(ibeam_letter > 0)
917                         {
918 // Extend selection
919                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
920                                         ibeam_y + text_y + text_height);
921 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
923                                 if(top_level->shift_down())
924                                 {
925 // Initialize highlighting
926                                         if(highlight_letter1 == highlight_letter2)
927                                         {
928                                                 highlight_letter1 = new_letter;
929                                                 highlight_letter2 = ibeam_letter;
930                                         }
931                                         else
932 // Shrink left highlight
933                                         if(highlight_letter1 == ibeam_letter)
934                                         {
935                                                 highlight_letter1 = new_letter;
936                                         }
937                                         else
938 // Expand right highlight
939                                         if(highlight_letter2 == ibeam_letter)
940                                         {
941                                                 highlight_letter2 = new_letter;
942                                         }
943                                 }
944                                 else
945                                         highlight_letter1 = highlight_letter2 = new_letter;
947                                 if(highlight_letter1 > highlight_letter2)
948                                 {
949                                         int temp = highlight_letter1;
950                                         highlight_letter1 = highlight_letter2;
951                                         highlight_letter2 = temp;
952                                 }
953                                 ibeam_letter = new_letter;
955                                 find_ibeam(1);
956                                 if(keypress_draw) draw();
958 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
959                         }
960                         result = 1;
961                         break;
963                 case PGDN:
964                         {
965 // Extend selection
966                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
967                                         ibeam_y + text_y + get_h());
968 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
970                                 if(top_level->shift_down())
971                                 {
972 // Initialize highlighting
973                                         if(highlight_letter1 == highlight_letter2)
974                                         {
975                                                 highlight_letter1 = new_letter;
976                                                 highlight_letter2 = ibeam_letter;
977                                         }
978                                         else
979 // Shrink left highlight
980                                         if(highlight_letter1 == ibeam_letter)
981                                         {
982                                                 highlight_letter1 = new_letter;
983                                         }
984                                         else
985 // Expand right highlight
986                                         if(highlight_letter2 == ibeam_letter)
987                                         {
988                                                 highlight_letter2 = new_letter;
989                                         }
990                                 }
991                                 else
992                                         highlight_letter1 = highlight_letter2 = new_letter;
994                                 if(highlight_letter1 > highlight_letter2)
995                                 {
996                                         int temp = highlight_letter1;
997                                         highlight_letter1 = highlight_letter2;
998                                         highlight_letter2 = temp;
999                                 }
1000                                 ibeam_letter = new_letter;
1002                                 find_ibeam(1);
1003                                 if(keypress_draw) draw();
1005 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1006                         }
1007                         result = 1;
1008                         break;
1009                 
1010                 case END:
1011                 {
1012                         int old_ibeam_letter = ibeam_letter;
1014                         while(ibeam_letter < text_len && text[ibeam_letter] != '\n')
1015                                 ibeam_letter++;
1017                         if(top_level->shift_down())
1018                         {
1019 // Begin selection
1020                                 if(highlight_letter1 == highlight_letter2)
1021                                 {
1022                                         highlight_letter2 = ibeam_letter;
1023                                         highlight_letter1 = old_ibeam_letter;
1024                                 }
1025                                 else
1026 // Shrink selection
1027                                 if(highlight_letter1 == old_ibeam_letter)
1028                                 {
1029                                         highlight_letter1 = highlight_letter2;
1030                                         highlight_letter2 = ibeam_letter;
1031                                 }
1032                                 else
1033 // Extend selection
1034                                 if(highlight_letter2 == old_ibeam_letter)
1035                                 {
1036                                         highlight_letter2 = ibeam_letter;
1037                                 }
1038                         }
1039                         else
1040                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1042                         find_ibeam(1);
1043                         if(keypress_draw) draw();
1044                         result = 1;
1045                         break;
1046                 }
1048                 case HOME:
1049                 {
1050                         int old_ibeam_letter = ibeam_letter;
1052                         while(ibeam_letter > 0 && text[ibeam_letter - 1] != '\n')
1053                                 ibeam_letter--;
1055                         if(top_level->shift_down())
1056                         {
1057 // Begin selection
1058                                 if(highlight_letter1 == highlight_letter2)
1059                                 {
1060                                         highlight_letter2 = old_ibeam_letter;
1061                                         highlight_letter1 = ibeam_letter;
1062                                 }
1063                                 else
1064 // Extend selection
1065                                 if(highlight_letter1 == old_ibeam_letter)
1066                                 {
1067                                         highlight_letter1 = ibeam_letter;
1068                                 }
1069                                 else
1070 // Shrink selection
1071                                 if(highlight_letter2 == old_ibeam_letter)
1072                                 {
1073                                         highlight_letter2 = highlight_letter1;
1074                                         highlight_letter1 = ibeam_letter;
1075                                 }
1076                         }
1077                         else
1078                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1080                         find_ibeam(1);
1081                         if(keypress_draw) draw();
1082                         result = 1;
1083                         break;
1084                 }
1086         case BACKSPACE:
1087                         if(highlight_letter1 == highlight_letter2)
1088                         {
1089                                 if(ibeam_letter > 0)
1090                                 {
1091                                         delete_selection(ibeam_letter - 1, ibeam_letter, text_len);
1092                                         ibeam_letter--;
1093                                 }
1094                         }
1095                         else
1096                         {
1097                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1098                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1099                         }
1101                         find_ibeam(1);
1102                         if(keypress_draw) draw();
1103                         dispatch_event = 1;
1104                         result = 1;
1105                 break;
1107                 case DELETE:
1108                         if(highlight_letter1 == highlight_letter2)
1109                         {
1110                                 if(ibeam_letter < text_len)
1111                                 {
1112                                         delete_selection(ibeam_letter, ibeam_letter + 1, text_len);
1113                                 }
1114                         }
1115                         else
1116                         {
1117                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1118                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1119                         }
1120                         
1121                         find_ibeam(1);
1122                         if(keypress_draw) draw();
1123                         dispatch_event = 1;
1124                         result = 1;
1125                         break;
1129                 default:
1130                         if(ctrl_down())
1131                         {
1132                                 if(get_keypress() == 'c' || get_keypress() == 'C')
1133                                 {
1134                                         if(highlight_letter1 != highlight_letter2)
1135                                         {
1136                                                 copy_selection(SECONDARY_SELECTION);
1137                                                 result = 1;
1138                                         }
1139                                 }
1140                                 else
1141                                 if(get_keypress() == 'v' || get_keypress() == 'V')
1142                                 {
1143                                         paste_selection(SECONDARY_SELECTION);
1144                                         find_ibeam(1);
1145                                         if(keypress_draw) draw();
1146                                         dispatch_event = 1;
1147                                         result = 1;
1148                                 }
1149                                 else
1150                                 if(get_keypress() == 'x' || get_keypress() == 'X')
1151                                 {
1152                                         if(highlight_letter1 != highlight_letter2)
1153                                         {
1154                                                 copy_selection(SECONDARY_SELECTION);
1155                                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1156                                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1157                                         }
1159                                         find_ibeam(1);
1160                                         if(keypress_draw) draw();
1161                                         dispatch_event = 1;
1162                                         result = 1;
1163                                 }
1164                                 
1165                                 break;
1166                         }
1168                         default_keypress(dispatch_event, result);
1169                         break;
1170         }
1172         if(dispatch_event) skip_cursor->update();
1173         if(dispatch_event) handle_event();
1174 //printf("BC_TextBox::keypress_event 100 %d\n", ibeam_letter);
1175         return result;
1180 int BC_TextBox::uses_text()
1182         return 1;
1185 void BC_TextBox::delete_selection(int letter1, int letter2, int text_len)
1187         int i, j;
1188         
1189         for(i = letter1, j = letter2; j < text_len; i++, j++)
1190         {
1191                 text[i] = text[j];
1192         }
1193         text[i] = 0;
1195         do_separators(1);
1198 void BC_TextBox::insert_text(char *string)
1200         int i, j, text_len, string_len;
1202         string_len = strlen(string);
1203         text_len = strlen(text);
1204         if(highlight_letter1 < highlight_letter2)
1205         {
1206                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1207                 highlight_letter2 = ibeam_letter = highlight_letter1;
1208         }
1210         text_len = strlen(text);
1212         for(i = text_len, j = text_len + string_len; i >= ibeam_letter; i--, j--)
1213                 text[j] = text[i];
1215         for(i = ibeam_letter, j = 0; j < string_len; j++, i++)
1216                 text[i] = string[j];
1218         ibeam_letter += string_len;
1220         do_separators(0);
1223 void BC_TextBox::do_separators(int ibeam_left)
1225         if(separators)
1226         {
1227 // Remove separators from text
1228                 int text_len = strlen(text);
1229                 int separator_len = strlen(separators);
1230                 for(int i = 0; i < text_len; i++)
1231                 {
1232                         if(!isalnum(text[i]))
1233                         {
1234                                 for(int j = i; j < text_len - 1; j++)
1235                                         text[j] = text[j + 1];
1236                                 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1237                                 text_len--;
1238                                 i--;
1239                         }
1240                 }
1241                 text[text_len] = 0;
1248 // Insert separators into text
1249                 for(int i = 0; i < separator_len; i++)
1250                 {
1251                         if(i < text_len)
1252                         {
1253 // Insert a separator
1254                                 if(!isalnum(separators[i]))
1255                                 {
1256                                         for(int j = text_len; j >= i; j--)
1257                                         {
1258                                                 text[j + 1] = text[j];
1259                                         }
1260                                         if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1261                                         text_len++;
1262                                         text[i] = separators[i];
1263                                 }
1264                         }
1265                         else
1266                         if(i >= text_len)
1267                         {
1268                                 text[i] = separators[i];
1269                         }
1270                 }
1272 // Truncate text
1273                 text[separator_len] = 0;
1274         }
1278 void BC_TextBox::get_ibeam_position(int &x, int &y)
1280         int i, j, k, row_begin, row_end, text_len;
1282         text_len = strlen(text);
1283         y = 0;
1284         x = 0;
1285         for(i = 0; i < text_len; )
1286         {
1287                 row_begin = i;
1288                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1289                 {
1290                         text_row[j] = text[i];
1291                 }
1293                 row_end = i;
1294                 text_row[j] = 0;
1296                 if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
1297                 {
1298                         x = get_text_width(font, text_row, ibeam_letter - row_begin);
1299 //printf("BC_TextBox::get_ibeam_position 9 %d %d\n", x, y);
1300                         return;
1301                 }
1303                 if(text[i] == '\n')
1304                 {
1305                         i++;
1306                         y += text_height;
1307                 }
1308         }
1309 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1311         x = 0;
1312         return;
1315 void BC_TextBox::set_text_row(int row)
1317         text_y = -(row * text_height) + top_margin;
1318         draw();
1321 int BC_TextBox::get_text_row()
1323         return -(text_y - top_margin) / text_height;
1326 void BC_TextBox::find_ibeam(int dispatch_event)
1328         int x, y;
1329         int old_x = text_x, old_y = text_y;
1331         get_ibeam_position(x, y);
1333         if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1334         {
1335                 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1336                 if(text_x > left_margin) text_x = left_margin;
1337         }
1338         else
1339         if(left_margin + text_x + x < left_margin)
1340         {
1341                 text_x = -(x - (get_w() / 4)) + left_margin;
1342                 if(text_x > left_margin) text_x = left_margin;
1343         }
1345         while(y + text_y >= get_h() - text_height - bottom_margin)
1346         {
1347                 text_y -= text_height;
1348 //              text_y = -(y - (get_h() / 2)) + top_margin;
1349 //              if(text_y > top_margin) text_y = top_margin;
1350         }
1352         while(y + text_y < top_margin)
1353         {
1354                 text_y += text_height;
1355                 if(text_y > top_margin) 
1356                 {
1357                         text_y = top_margin;
1358                         break;
1359                 }
1360         }
1362         if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1365 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1367         int i, j, k, l, row_begin, row_end, text_len, result = 0, done = 0;
1368         text_len = strlen(text);
1370         if(cursor_y < text_y)
1371         {
1372                 result = 0;
1373                 done = 1;
1374         }
1376         for(i = 0, k = text_y; i < text_len && !done; k += text_height)
1377         {
1378                 row_begin = i;
1379                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1380                 {
1381                         text_row[j] = text[i];
1382                 }
1383                 row_end = i;
1384                 text_row[j] = 0;
1386                 if(cursor_y >= k && cursor_y < k + text_height)
1387                 {
1388                         for(j = 0; j <= row_end - row_begin && !done; j++)
1389                         {
1390                                 l = get_text_width(font, text_row, j) + text_x;
1391                                 if(l > cursor_x)
1392                                 {
1393                                         result = row_begin + j - 1;
1394                                         done = 1;
1395                                 }
1396                         }
1397                         if(!done)
1398                         {
1399                                 result = row_end;
1400                                 done = 1;
1401                         }
1402                 }
1403                 if(text[i] == '\n') i++;
1404                 
1405                 if(i >= text_len && !done)
1406                 {
1407                         result = text_len;
1408                 }
1409         }
1410         if(result < 0) result = 0;
1411         if(result > text_len) result = text_len;
1412         return result;
1415 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
1417         int text_len = strlen(text);
1418         letter1 = letter2 = ibeam_letter;
1419         do
1420         {
1421                 if(isalnum(text[letter1])) letter1--;
1422         }while(letter1 > 0 && isalnum(text[letter1]));
1423         if(!isalnum(text[letter1])) letter1++;
1425         do
1426         {
1427                 if(isalnum(text[letter2])) letter2++;
1428         }while(letter2 < text_len && isalnum(text[letter2]));
1429         if(letter2 < text_len && text[letter2] == ' ') letter2++;
1431         if(letter1 < 0) letter1 = 0;
1432         if(letter2 < 0) letter2 = 0;
1433         if(letter1 > text_len) letter1 = text_len;
1434         if(letter2 > text_len) letter2 = text_len;
1437 void BC_TextBox::copy_selection(int clipboard_num)
1439         int text_len = strlen(text);
1441         if(highlight_letter1 >= text_len ||
1442                 highlight_letter2 > text_len ||
1443                 highlight_letter1 < 0 ||
1444                 highlight_letter2 < 0 ||
1445                 highlight_letter2 - highlight_letter1 <= 0) return;
1447         get_clipboard()->to_clipboard(&text[highlight_letter1], 
1448                 highlight_letter2 - highlight_letter1, 
1449                 clipboard_num);
1452 void BC_TextBox::paste_selection(int clipboard_num)
1454         int len = get_clipboard()->clipboard_len(clipboard_num);
1455         if(len)
1456         {
1457                 char *string = new char[len + 1];
1458                 get_clipboard()->from_clipboard(string, len, clipboard_num);
1459                 insert_text(string);
1460         }
1463 void BC_TextBox::set_keypress_draw(int value)
1465         keypress_draw = value;
1468 int BC_TextBox::get_last_keypress()
1470         return last_keypress;
1473 int BC_TextBox::get_ibeam_letter()
1475         return ibeam_letter;
1478 void BC_TextBox::set_ibeam_letter(int number, int redraw)
1480         this->ibeam_letter = number;
1481         if(redraw)
1482         {
1483                 draw();
1484         }
1487 void BC_TextBox::set_separators(char *separators)
1489         this->separators = separators;
1507 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window, 
1508         int x, 
1509         int y, 
1510         int w,
1511         int rows,
1512         char *default_text)
1514         this->parent_window = parent_window;
1515         this->x = x;
1516         this->y = y;
1517         this->w = w;
1518         this->rows = rows;
1519         this->default_text = default_text;
1522 BC_ScrollTextBox::~BC_ScrollTextBox()
1524         delete yscroll;
1525         if(text)
1526         {
1527                 text->gui = 0;
1528                 delete text;
1529         }
1532 void BC_ScrollTextBox::create_objects()
1534 // Must be created first
1535         parent_window->add_subwindow(text = new BC_ScrollTextBoxText(this));
1536         parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
1539 int BC_ScrollTextBox::handle_event()
1541         return 1;
1544 int BC_ScrollTextBox::get_x()
1546         return x;
1549 int BC_ScrollTextBox::get_y()
1551         return y;
1554 int BC_ScrollTextBox::get_w()
1556         return w;
1559 int BC_ScrollTextBox::get_rows()
1561         return rows;
1565 char* BC_ScrollTextBox::get_text()
1567         return text->get_text();
1570 void BC_ScrollTextBox::update(char *text)
1572         this->text->update(text);
1573         yscroll->update_length(this->text->get_text_rows(),
1574                 this->text->get_text_row(),
1575                 yscroll->get_handlelength());
1578 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
1580         this->x = x;
1581         this->y = y;
1582         this->w = w;
1583         this->rows = rows;
1584         text->reposition_window(x, 
1585                 y, 
1586                 w - yscroll->get_span(), 
1587                 rows);
1588         yscroll->reposition_window(x + w - yscroll->get_span(), 
1589                 y, 
1590                 BC_TextBox::calculate_row_h(rows, 
1591                         parent_window));
1592         yscroll->update_length(text->get_text_rows(),
1593                 text->get_text_row(),
1594                 rows);
1605 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui)
1606  : BC_TextBox(gui->x, 
1607         gui->y, 
1608         gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1609         gui->rows,
1610         gui->default_text)
1612         this->gui = gui;
1615 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
1617         if(gui)
1618         {
1619                 gui->text = 0;
1620                 delete gui;
1621         }
1624 int BC_ScrollTextBoxText::handle_event()
1626         gui->yscroll->update_length(get_text_rows(),
1627                 get_text_row(),
1628                 gui->yscroll->get_handlelength());
1629         return gui->handle_event();
1632 int BC_ScrollTextBoxText::motion_event()
1634         gui->yscroll->update_length(get_text_rows(),
1635                 get_text_row(),
1636                 gui->yscroll->get_handlelength());
1637         return 1;
1641 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
1642  : BC_ScrollBar(gui->x + 
1643                         gui->w - 
1644                         get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1645                 gui->y, 
1646                 SCROLL_VERT, 
1647                 BC_TextBox::calculate_row_h(gui->rows, 
1648                         gui->parent_window), 
1649                 gui->text->get_text_rows(), 
1650                 0, 
1651                 gui->rows)
1653         this->gui = gui;
1656 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
1660 int BC_ScrollTextBoxYScroll::handle_event()
1662         gui->text->set_text_row(get_position());
1663         return 1;
1675 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y)
1676  : BC_TextBox(x, y, popup->text_w, 1, popup->default_text)
1678         this->popup = popup;
1681 BC_PopupTextBoxText::~BC_PopupTextBoxText()
1683         if(popup)
1684         {
1685                 popup->textbox = 0;
1686                 delete popup;
1687                 popup = 0;
1688         }
1692 int BC_PopupTextBoxText::handle_event()
1694         popup->handle_event();
1695         return 1;
1698 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
1699  : BC_ListBox(x,
1700         y,
1701         popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
1702         popup->list_h,
1703         LISTBOX_TEXT,
1704         popup->list_items,
1705         0,
1706         0,
1707         1,
1708         0,
1709         1)
1711         this->popup = popup;
1713 int BC_PopupTextBoxList::handle_event()
1715         popup->textbox->update(get_selection(0, 0)->get_text());
1716         popup->handle_event();
1717         return 1;
1723 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window, 
1724                 ArrayList<BC_ListBoxItem*> *list_items,
1725                 char *default_text,
1726                 int x, 
1727                 int y, 
1728                 int text_w,
1729                 int list_h)
1731         this->x = x;
1732         this->y = y;
1733         this->list_h = list_h;
1734         this->default_text = default_text;
1735         this->text_w = text_w;
1736         this->parent_window = parent_window;
1737         this->list_items = list_items;
1740 BC_PopupTextBox::~BC_PopupTextBox()
1742         delete listbox;
1743         if(textbox) 
1744         {
1745                 textbox->popup = 0;
1746                 delete textbox;
1747         }
1750 int BC_PopupTextBox::create_objects()
1752         int x = this->x, y = this->y;
1753         parent_window->add_subwindow(textbox = new BC_PopupTextBoxText(this, x, y));
1754         x += textbox->get_w();
1755         parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
1756         return 0;
1759 void BC_PopupTextBox::update(char *text)
1761         textbox->update(text);
1764 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
1766         listbox->update(data, 
1767                 0, 
1768                 0,
1769                 1);
1773 char* BC_PopupTextBox::get_text()
1775         return textbox->get_text();
1778 int BC_PopupTextBox::get_number()
1780         return listbox->get_selection_number(0, 0);
1783 int BC_PopupTextBox::get_x()
1785         return x;
1788 int BC_PopupTextBox::get_y()
1790         return y;
1793 int BC_PopupTextBox::get_w()
1795         return textbox->get_w() + listbox->get_w();
1798 int BC_PopupTextBox::get_h()
1800         return textbox->get_h();
1803 int BC_PopupTextBox::handle_event()
1805         return 1;
1808 void BC_PopupTextBox::reposition_window(int x, int y)
1810         this->x = x;
1811         this->y = y;
1812         int x1 = x, y1 = y;
1813         textbox->reposition_window(x1, y1);
1814         x1 += textbox->get_w();
1815         listbox->reposition_window(x1, y1);
1831 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1832         int64_t default_value,
1833         int64_t min,
1834         int64_t max,
1835         int x, 
1836         int y)
1837  : BC_TextBox(x, 
1838         y, 
1839         popup->text_w, 
1840         1, 
1841         default_value)
1843         this->popup = popup;
1846 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1847         float default_value,
1848         float min,
1849         float max,
1850         int x, 
1851         int y)
1852  : BC_TextBox(x, 
1853         y, 
1854         popup->text_w, 
1855         1, 
1856         default_value)
1858         this->popup = popup;
1861 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
1863         if(popup)
1864         {
1865                 popup->textbox = 0;
1866                 delete popup;
1867                 popup = 0;
1868         }
1873 int BC_TumbleTextBoxText::handle_event()
1875         popup->handle_event();
1876         return 1;
1884 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1885                 int64_t default_value,
1886                 int64_t min,
1887                 int64_t max,
1888                 int x, 
1889                 int y, 
1890                 int text_w)
1892         reset();
1893         this->x = x;
1894         this->y = y;
1895         this->min = min;
1896         this->max = max;
1897         this->default_value = default_value;
1898         this->text_w = text_w;
1899         this->parent_window = parent_window;
1900         use_float = 0;
1901         precision = 4;
1902         increment = 1;
1905 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1906                 int default_value,
1907                 int min,
1908                 int max,
1909                 int x, 
1910                 int y, 
1911                 int text_w)
1913         reset();
1914         this->x = x;
1915         this->y = y;
1916         this->min = min;
1917         this->max = max;
1918         this->default_value = default_value;
1919         this->text_w = text_w;
1920         this->parent_window = parent_window;
1921         use_float = 0;
1922         precision = 4;
1923         increment = 1;
1926 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1927                 float default_value_f,
1928                 float min_f,
1929                 float max_f,
1930                 int x, 
1931                 int y, 
1932                 int text_w)
1934         reset();
1935         this->x = x;
1936         this->y = y;
1937         this->min_f = min_f;
1938         this->max_f = max_f;
1939         this->default_value_f = default_value_f;
1940         this->text_w = text_w;
1941         this->parent_window = parent_window;
1942         use_float = 1;
1943         precision = 4;
1944         increment = 1;
1947 BC_TumbleTextBox::~BC_TumbleTextBox()
1949 // Recursive delete.  Normally ~BC_TumbleTextBox is never called but textbox
1950 // is deleted anyway by the windowbase so textbox deletes this.
1951         if(tumbler) delete tumbler;
1952         tumbler = 0;
1953 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
1954         if(textbox)
1955         {
1956                 textbox->popup = 0;
1957                 delete textbox;
1958         }
1959         textbox = 0;
1962 void BC_TumbleTextBox::reset()
1964         textbox = 0;
1965         tumbler = 0;
1966         increment = 1.0;
1969 void BC_TumbleTextBox::set_precision(int precision)
1971         this->precision = precision;
1974 void BC_TumbleTextBox::set_increment(float value)
1976         this->increment = value;
1977         if(tumbler) tumbler->set_increment(value);
1980 int BC_TumbleTextBox::create_objects()
1982         int x = this->x, y = this->y;
1984         if(use_float)
1985         {
1986                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
1987                         default_value_f,
1988                         min_f, 
1989                         max_f, 
1990                         x, 
1991                         y));
1992                 textbox->set_precision(precision);
1993         }
1994         else
1995                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
1996                         default_value,
1997                         min, 
1998                         max, 
1999                         x, 
2000                         y));
2002         x += textbox->get_w();
2004         if(use_float)
2005                 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox, 
2006                         min_f,
2007                         max_f,
2008                         x, 
2009                         y));
2010         else
2011                 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox, 
2012                         min, 
2013                         max, 
2014                         x, 
2015                         y));
2017         tumbler->set_increment(increment);
2018         return 0;
2021 char* BC_TumbleTextBox::get_text()
2023         return textbox->get_text();
2026 int BC_TumbleTextBox::update(char *value)
2028         textbox->update(value);
2029         return 0;
2032 int BC_TumbleTextBox::update(int64_t value)
2034         textbox->update(value);
2035         return 0;
2038 int BC_TumbleTextBox::update(float value)
2040         textbox->update(value);
2041         return 0;
2045 int BC_TumbleTextBox::get_x()
2047         return x;
2050 int BC_TumbleTextBox::get_y()
2052         return y;
2055 int BC_TumbleTextBox::get_w()
2057         return textbox->get_w() + tumbler->get_w();
2060 int BC_TumbleTextBox::get_h()
2062         return textbox->get_h();
2065 int BC_TumbleTextBox::handle_event()
2067         return 1;
2070 void BC_TumbleTextBox::reposition_window(int x, int y)
2072         this->x = x;
2073         this->y = y;
2074         
2075         textbox->reposition_window(x, 
2076                 y, 
2077                 text_w, 
2078                 1);
2079         tumbler->reposition_window(x + textbox->get_w(),
2080                 y);
2084 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2086         tumbler->set_boundaries(min, max);
2089 void BC_TumbleTextBox::set_boundaries(float min, float max)
2091         tumbler->set_boundaries(min, max);