r1053: Add Russian translation.
[cinelerra_cv.git] / guicast / bctextbox.C
blobd7fb0f05782117b52fb4cc31464889e74223c421
1 #include "bcclipboard.h"
2 #include "bclistboxitem.h"
3 #include "bcresources.h"
4 #include "bcsignals.h"
5 #include "bctextbox.h"
6 #include "clip.h"
7 #include "colors.h"
8 #include <ctype.h>
9 #include "cursors.h"
10 #include "keys.h"
11 #include <math.h>
12 #include "bctimer.h"
13 #include "vframe.h"
15 #include <string.h>
17 #define VERTICAL_MARGIN 2
18 #define VERTICAL_MARGIN_NOBORDER 0
19 #define HORIZONTAL_MARGIN 4
20 #define HORIZONTAL_MARGIN_NOBORDER 2
22 BC_TextBox::BC_TextBox(int x, 
23         int y, 
24         int w, 
25         int rows, 
26         char *text, 
27         int has_border, 
28         int font)
29  : BC_SubWindow(x, y, w, 0, -1)
31         skip_cursor = 0;
32         reset_parameters(rows, has_border, font);
33         strcpy(this->text, text);
36 BC_TextBox::BC_TextBox(int x, 
37         int y, 
38         int w, 
39         int rows, 
40         int64_t text, 
41         int has_border, 
42         int font)
43  : BC_SubWindow(x, y, w, 0, -1)
45         skip_cursor = 0;
46         reset_parameters(rows, has_border, font);
47         sprintf(this->text, "%lld", text);
50 BC_TextBox::BC_TextBox(int x, 
51         int y, 
52         int w, 
53         int rows, 
54         float text, 
55         int has_border, 
56         int font,
57         int precision)
58  : BC_SubWindow(x, y, w, 0, -1)
60         skip_cursor = 0;
61         this->precision = precision;
62         reset_parameters(rows, has_border, font);
63         sprintf(this->text, "%0.*f", precision, text);
66 BC_TextBox::BC_TextBox(int x, 
67         int y, 
68         int w, 
69         int rows, 
70         int text, 
71         int has_border, 
72         int font)
73  : BC_SubWindow(x, y, w, 0, -1)
75         skip_cursor = 0;
76         reset_parameters(rows, has_border, font);
77         sprintf(this->text, "%d", text);
80 BC_TextBox::~BC_TextBox()
82         if(skip_cursor) delete skip_cursor;
85 int BC_TextBox::reset_parameters(int rows, int has_border, int font)
87         this->rows = rows;
88         this->has_border = has_border;
89         this->font = font;
90         text_start = 0;
91         text_end = 0;
92         highlight_letter1 = highlight_letter2 = 0;
93         highlight_letter3 = highlight_letter4 = 0;
94         ibeam_letter = 0;
95         active = 0;
96         text_selected = word_selected = 0;
97         text_x = 0;
98         enabled = 1;
99         highlighted = 0;
100         precision = 4;
101         if (!skip_cursor)
102                 skip_cursor = new Timer;
103         keypress_draw = 1;
104         last_keypress = 0;
105         separators = 0;
106         return 0;
109 int BC_TextBox::initialize()
111         if (!skip_cursor)
112                 skip_cursor = new Timer;
113         skip_cursor->update();
114 // Get dimensions
115         text_ascent = get_text_ascent(font) + 1;
116         text_descent = get_text_descent(font) + 1;
117         text_height = text_ascent + text_descent;
118         ibeam_letter = strlen(text);
119         if(has_border)
120         {
121                 left_margin = right_margin = HORIZONTAL_MARGIN;
122                 top_margin = bottom_margin = VERTICAL_MARGIN;
123         }
124         else
125         {
126                 left_margin = right_margin = HORIZONTAL_MARGIN_NOBORDER;
127                 top_margin = bottom_margin = VERTICAL_MARGIN_NOBORDER;
128         }
129         h = get_row_h(rows);
130         text_x = left_margin;
131         text_y = top_margin;
132         find_ibeam(0);
134 // Create the subwindow
135         BC_SubWindow::initialize();
137         BC_Resources *resources = get_resources();
138         if(has_border)
139         {
140                 back_color = resources->text_background;
141                 high_color = resources->text_background_hi;
142         }
143         else 
144         {
145                 high_color = resources->text_background_noborder_hi;
146                 back_color = bg_color;
147         }
149         draw();
150         set_cursor(IBEAM_CURSOR);
151         return 0;
154 int BC_TextBox::calculate_h(BC_WindowBase *gui, 
155         int font, 
156         int has_border,
157         int rows)
159         return rows * (gui->get_text_ascent(font) + 1 + 
160                 gui->get_text_descent(font) + 1) +
161                 2 * (has_border ? VERTICAL_MARGIN : VERTICAL_MARGIN_NOBORDER);
164 void BC_TextBox::set_precision(int precision)
166         this->precision = precision;
169 void BC_TextBox::set_selection(int char1, int char2, int ibeam)
171         highlight_letter1 = char1;
172         highlight_letter2 = char2;
173         ibeam_letter = ibeam;
174         draw();
177 int BC_TextBox::update(char *text)
179 //printf("BC_TextBox::update 1 %d %s %s\n", strcmp(text, this->text), text, this->text);
180         int text_len = strlen(text);
181 // Don't update if contents are the same
182         if(!strcmp(text, this->text)) return 0;
185         strcpy(this->text, text);
186         if(highlight_letter1 > text_len) highlight_letter1 = text_len;
187         if(highlight_letter2 > text_len) highlight_letter2 = text_len;
188         if(ibeam_letter > text_len) ibeam_letter = text_len;
189         draw();
190         return 0;
193 int BC_TextBox::update(int64_t value)
195         char string[BCTEXTLEN];
196         sprintf(string, "%lld", value);
199         update(string);
200         return 0;
203 int BC_TextBox::update(float value)
205         char string[BCTEXTLEN];
206         sprintf(string, "%0.*f", precision, value);
208         update(string);
209         return 0;
212 void BC_TextBox::disable()
214         if(enabled)
215         {
216                 enabled = 0;
217                 if(top_level)
218                 {
219                         if(active) top_level->deactivate();
220                         draw();
221                 }
222         }
225 void BC_TextBox::enable()
227         if(!enabled)
228         {
229                 enabled = 1;
230                 if(top_level)
231                 {
232                         draw();
233                 }
234         }
237 int BC_TextBox::get_enabled()
239         return enabled;
242 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
244         return (pixels - 4) / 
245                 (window->get_text_ascent(font) + 1 + 
246                         window->get_text_descent(font) + 1);
249 int BC_TextBox::calculate_row_h(int rows, 
250         BC_WindowBase *parent_window, 
251         int has_border, 
252         int font)
254         return rows * 
255                 (parent_window->get_text_ascent(font) + 1 + 
256                 parent_window->get_text_descent(font) + 1) +
257                 (has_border ? 4 : 0);
260 char* BC_TextBox::get_text()
262         return text;
265 int BC_TextBox::get_text_rows()
267         int text_len = strlen(text);
268         int result = 1;
269         for(int i = 0; i < text_len; i++)
270         {
271                 if(text[i] == 0xa) result++;
272         }
273         return result;
277 int BC_TextBox::get_row_h(int rows)
279         return rows * text_height + top_margin + bottom_margin;
282 int BC_TextBox::reposition_window(int x, int y, int w, int rows)
284         int new_h = get_h();
285         if(w < 0) w = get_w();
286         if(rows != -1)
287         {
288                 new_h = get_row_h(rows);
289                 this->rows = rows;
290         }
292         if(x != get_x() || 
293                 y != get_y() || 
294                 w != get_w() || 
295                 new_h != get_h())
296         {
297 // printf("BC_TextBox::reposition_window 1 %d %d %d %d %d %d %d %d\n",
298 // x, get_x(), y, get_y(), w, get_w(), new_h, get_h());
299                 BC_WindowBase::reposition_window(x, y, w, new_h);
300                 draw();
301         }
302         return 0;
305 void BC_TextBox::draw_border()
307         BC_Resources *resources = get_resources();
308 // Clear margins
309         set_color(background_color);
310         draw_box(0, 0, left_margin, get_h());
311         draw_box(get_w() - right_margin, 0, right_margin, get_h());
313         if(has_border)
314         {
315                 if(highlighted)
316                         draw_3d_border(0, 0, w, h,
317                                 resources->button_shadow, 
318                                 resources->button_uphighlighted,
319                                 resources->button_highlighted,
320                                 resources->button_light);
321                 else
322                         draw_3d_border(0, 0, w, h, 
323                                 resources->text_border1, 
324                                 resources->text_border2,
325                                 resources->text_border3,
326                                 resources->text_border4);
327         }
330 void BC_TextBox::draw_cursor()
332 //      set_color(background_color);
333         set_color(WHITE);
334         set_inverse();
336         draw_box(ibeam_x + text_x, 
337                 ibeam_y + text_y, 
338                 BCCURSORW, 
339                 text_height);
340         set_opaque();
344 void BC_TextBox::draw()
346         int i, j, k, text_len;
347         int row_begin, row_end;
348         int highlight_x1, highlight_x2;
349         int need_ibeam = 1;
350         BC_Resources *resources = get_resources();
352 //printf("BC_TextBox::draw 1 %s\n", text);
353 // Background
354         if(has_border)
355         {
356                 background_color = resources->text_background;
357         }
358         else
359         {
360                 if(highlighted)
361                 {
362                         background_color = high_color;
363                 }
364                 else
365                 {
366                         background_color = back_color;
367                 }
368         }
370         set_color(background_color);
371         draw_box(0, 0, w, h);
373 // Draw text with selection
374         set_font(font);
375         text_len = strlen(text);
376 //printf("BC_TextBox::draw 0 %s %d %d %d %d\n", text, text_y, text_len, get_w(), text_height);
378         for(i = 0, k = text_y; i < text_len && k < get_h(); k += text_height)
379         {
380 // Draw row of text
381                 if(text[i] == '\n') i++;
382                 row_begin = i;
383                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
384                 {
385                         text_row[j] = text[i];
386                 }
387                 row_end = i;
388                 text_row[j] = 0;
390 //printf("BC_TextBox::draw 1 %d %d %c\n", row_begin, row_end, text_row[j - 1]);
392                 if(k > -text_height + top_margin && k < get_h() - bottom_margin)
393                 {
394 // Draw highlighted region of row
395                         if(highlight_letter2 > highlight_letter1 &&
396                                 highlight_letter2 > row_begin && highlight_letter1 < row_end)
397                         {
398                                 if(active && enabled && get_has_focus())
399                                         set_color(resources->text_highlight);
400                                 else
401                                         set_color(resources->text_inactive_highlight);
403                                 if(highlight_letter1 >= row_begin && highlight_letter1 < row_end)
404                                         highlight_x1 = get_text_width(font, text_row, highlight_letter1 - row_begin);
405                                 else
406                                         highlight_x1 = 0;
408                                 if(highlight_letter2 > row_begin && highlight_letter2 <= row_end)
409                                         highlight_x2 = get_text_width(font, text_row, highlight_letter2 - row_begin);
410                                 else
411                                         highlight_x2 = get_w();
413                                 draw_box(highlight_x1 + text_x, 
414                                         k, 
415                                         highlight_x2 - highlight_x1, 
416                                         text_height);
417                         }
419 // Draw text over highlight
420                         if(enabled)
421                                 set_color(resources->text_default);
422                         else
423                                 set_color(MEGREY);
425                         draw_text(text_x, k + text_ascent, text_row);
427 // Get ibeam location
428                         if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
429                         {
430                                 need_ibeam = 0;
431                                 ibeam_y = k - text_y;
432                                 ibeam_x = get_text_width(font, text_row, ibeam_letter - row_begin);
433                         }
434                 }
435         }
437 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
438         if(need_ibeam)
439         {
440                 ibeam_x = 0;
441                 ibeam_y = 0;
442         }
444 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
445 // Draw solid cursor
446         if (active) 
447                 draw_cursor();
449 // Border
450         draw_border();
451         flash();
452         flush();   
455 int BC_TextBox::focus_in_event()
457         draw();
458         return 1;
461 int BC_TextBox::focus_out_event()
463         draw();
464         return 1;
467 int BC_TextBox::cursor_enter_event()
469         if(top_level->event_win == win && enabled)
470         {
471                 tooltip_done = 0;
473                 if(!highlighted)
474                 {
475                         highlighted = 1;
476                         draw_border();
477                         flash();
478                         flush();   
479                 }
480         }
481         return 0;
484 int BC_TextBox::cursor_leave_event()
486         if(highlighted)
487         {
488                 highlighted = 0;
489                 draw_border();
490                 hide_tooltip();
491                 flash();
492                 flush();   
493         }
494         return 0;
497 int BC_TextBox::button_press_event()
499         if(get_buttonpress() > 2) return 0;
501         int cursor_letter = 0;
502         int text_len = strlen(text);
504         if(!enabled) return 0;
506         if(top_level->event_win == win)
507         {
508                 if(!active)
509                 {
510                         hide_tooltip();
511                         top_level->deactivate();
512                         activate();
513                 }
515                 cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
516                 if(get_double_click())
517                 {
518                         word_selected = 1;
519                         select_word(highlight_letter1, highlight_letter2, cursor_letter);
520                         highlight_letter3 = highlight_letter1;
521                         highlight_letter4 = highlight_letter2;
522                         ibeam_letter = highlight_letter2;
523                         copy_selection(PRIMARY_SELECTION);
524                 }
525                 else
526                 if(get_buttonpress() == 2)
527                 {
528                         highlight_letter3 = highlight_letter4 = 
529                                 ibeam_letter = highlight_letter1 = 
530                                 highlight_letter2 = cursor_letter;
531                         paste_selection(PRIMARY_SELECTION);
532                 }
533                 else
534                 {
535                         text_selected = 1;
536                         highlight_letter3 = highlight_letter4 = 
537                                 ibeam_letter = highlight_letter1 = 
538                                 highlight_letter2 = cursor_letter;
539                 }
540                 
541                 if(ibeam_letter < 0) ibeam_letter = 0;
542                 if(ibeam_letter > text_len) ibeam_letter = text_len;
543                 draw();
544                 return 1;
545         }
546         else
547         if(active)
548         {
549                 top_level->deactivate();
550         }
552         return 0;
555 int BC_TextBox::button_release_event()
557         if(active)
558         {
559                 hide_tooltip();
560                 if(text_selected || word_selected)
561                 {
562                         text_selected = 0;
563                         word_selected = 0;
564                 }
565         }
566         return 0;
569 int BC_TextBox::cursor_motion_event()
571         int cursor_letter, text_len = strlen(text), letter1, letter2;
572         if(active)
573         {
574                 if(text_selected || word_selected)
575                 {
576                         cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
577                         if(word_selected)
578                         {
579                                 select_word(letter1, letter2, cursor_letter);
580                         }
581                         else
582                         if(text_selected)
583                         {
584                                 letter1 = letter2 = cursor_letter;
585                         }
587                         if(letter1 <= highlight_letter3)
588                         {
589                                 highlight_letter1 = letter1;
590                                 highlight_letter2 = highlight_letter4;
591                                 ibeam_letter = letter1;
592                         }
593                         else
594                         if(letter2 >= highlight_letter4)
595                         {
596                                 highlight_letter2 = letter2;
597                                 highlight_letter1 = highlight_letter3;
598                                 ibeam_letter = letter2;
599                         }
600                         
601                         copy_selection(PRIMARY_SELECTION);
602                         find_ibeam(1);
603                         draw();
604                         return 1;
605                 }
606         }
607         return 0;
610 int BC_TextBox::activate()
612         top_level->active_subwindow = this;
613         active = 1;
614         draw();
615         top_level->set_repeat(top_level->get_resources()->blink_rate);
616         return 0;
619 int BC_TextBox::deactivate()
621         active = 0;
622         top_level->unset_repeat(top_level->get_resources()->blink_rate);
623         draw();
624         return 0;
627 int BC_TextBox::repeat_event(int64_t duration)
629         int result = 0;
631         if(duration == top_level->get_resources()->tooltip_delay &&
632                 tooltip_text[0] != 0 &&
633                 highlighted)
634         {
635                 show_tooltip();
636                 tooltip_done = 1;
637                 result = 1;
638         }
639                 
640         if(duration == top_level->get_resources()->blink_rate && 
641                 active &&
642                 get_has_focus())
643         {
644                 if(skip_cursor->get_difference() < duration)
645                 {
646 // printf("BC_TextBox::repeat_event 1 %lld %lld\n", 
647 // skip_cursor->get_difference(), 
648 // duration);
649                         return 1;
650                 }
651                 draw_cursor();
652                 flash();
653                 flush();   
654                 result = 1;
655         }
656         return result;
659 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
661     if((top_level->get_keypress() == RETURN) ||
662 //              (top_level->get_keypress() > 30 && top_level->get_keypress() < 127))
663                 (top_level->get_keypress() > 30 && top_level->get_keypress() <= 255))
664         {
665 // Substitute UNIX linefeed
666                 if(top_level->get_keypress() == RETURN) 
667                         temp_string[0] = 0xa;
668                 else
669                         temp_string[0] = top_level->get_keypress();
670                 temp_string[1] = 0;
671                 insert_text(temp_string);
672                 find_ibeam(1);
673                 draw();
674                 dispatch_event = 1;
675                 result = 1;
676         }
679 int BC_TextBox::select_whole_text(int select)
681         if (select == 1) 
682         {
683                 highlight_letter1 = 0;
684                 highlight_letter2 = strlen(text);
685                 text_selected = word_selected = 0;      
686                 ibeam_letter = highlight_letter1;
687                 find_ibeam(1);
688                 if(keypress_draw) draw();
689         } else
690         if (select == -1)
691         {
692                 ibeam_letter = strlen(text);
693                 highlight_letter1 = ibeam_letter;
694                 highlight_letter2 = ibeam_letter;
695                 text_selected = word_selected = 0;
696                 find_ibeam(1);
697                 if(keypress_draw) draw();
698         }
699         return highlight_letter2 - highlight_letter1;
702 void BC_TextBox::cycle_textboxes(int amout)
704         top_level->cycle_textboxes(amout);
707 int BC_TextBox::keypress_event()
709 // Result == 2 contents changed
710 // Result == 1 trapped keypress
711 // Result == 0 nothing
712         int result = 0;
713         int text_len;
714         int dispatch_event = 0;
716         if(!active || !enabled) return 0;
718         text_len = strlen(text);
719         last_keypress = get_keypress();
720         switch(get_keypress())
721         {
722                 case ESC:
723                         top_level->deactivate();
724                         result = 0;
725                         break;
727                 case RETURN:
728                         if(rows == 1)
729                         {
730                                 top_level->deactivate();
731                                 dispatch_event = 1;
732                                 result = 0;
733                         }
734                         else
735                         {
736                                 default_keypress(dispatch_event, result);
737                         }
738                         break;
739 // Handle like a default keypress
741                 case TAB:
742                         cycle_textboxes(1);
743                         result = 1;
744                         break;
746                 case LEFTTAB:
747                         cycle_textboxes(-1);
748                         result = 1;
749                         break;
751                 case LEFT:
752                         if(ibeam_letter > 0)
753                         {
754                                 int old_ibeam_letter = ibeam_letter;
755 // Single character
756                                 if(!ctrl_down())
757                                 {
758                                         ibeam_letter--;
759                                 }
760                                 else
761 // Word
762                                 {
763                                         ibeam_letter--;
764                                         while(ibeam_letter > 0 && isalnum(text[ibeam_letter - 1]))
765                                                 ibeam_letter--;
766                                 }
769 // Extend selection
770                                 if(top_level->shift_down())
771                                 {
772 // Initialize highlighting
773                                         if(highlight_letter1 == highlight_letter2)
774                                         {
775                                                 highlight_letter1 = ibeam_letter;
776                                                 highlight_letter2 = old_ibeam_letter;
777                                         }
778                                         else
779 // Extend left highlight
780                                         if(highlight_letter1 == old_ibeam_letter)
781                                         {
782                                                 highlight_letter1 = ibeam_letter;
783                                         }
784                                         else
785 // Shrink right highlight
786                                         if(highlight_letter2 == old_ibeam_letter)
787                                         {
788                                                 highlight_letter2 = ibeam_letter;
789                                         }
790                                 }
791                                 else
792                                 {
793                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
794                                 }
797                                 find_ibeam(1);
798                                 if(keypress_draw) draw();
799                         }
800                         result = 1;
801                         break;
803                 case RIGHT:
804                         if(ibeam_letter < text_len)
805                         {
806                                 int old_ibeam_letter = ibeam_letter;
807 // Single character
808                                 if(!ctrl_down())
809                                 {
810                                         ibeam_letter++;
811                                 }
812                                 else
813 // Word
814                                 {
815                                         while(ibeam_letter < text_len && isalnum(text[ibeam_letter++]))
816                                                 ;
817                                 }
821 // Extend selection
822                                 if(top_level->shift_down())
823                                 {
824 // Initialize highlighting
825                                         if(highlight_letter1 == highlight_letter2)
826                                         {
827                                                 highlight_letter1 = old_ibeam_letter;
828                                                 highlight_letter2 = ibeam_letter;
829                                         }
830                                         else
831 // Shrink left highlight
832                                         if(highlight_letter1 == old_ibeam_letter)
833                                         {
834                                                 highlight_letter1 = ibeam_letter;
835                                         }
836                                         else
837 // Expand right highlight
838                                         if(highlight_letter2 == old_ibeam_letter)
839                                         {
840                                                 highlight_letter2 = ibeam_letter;
841                                         }
842                                 }
843                                 else
844                                 {
845                                         highlight_letter1 = highlight_letter2 = ibeam_letter;
846                                 }
848                                 find_ibeam(1);
849                                 if(keypress_draw) draw();
850                         }
851                         result = 1;
852                         break;
854                 case UP:
855                         if(ibeam_letter > 0)
856                         {
857 //printf("BC_TextBox::keypress_event 1 %d %d %d\n", ibeam_x, ibeam_y, ibeam_letter);
858                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
859                                         ibeam_y + text_y - text_height);
860 //printf("BC_TextBox::keypress_event 2 %d %d %d\n", ibeam_x, ibeam_y, new_letter);
862 // Extend selection
863                                 if(top_level->shift_down())
864                                 {
865 // Initialize highlighting
866                                         if(highlight_letter1 == highlight_letter2)
867                                         {
868                                                 highlight_letter1 = new_letter;
869                                                 highlight_letter2 = ibeam_letter;
870                                         }
871                                         else
872 // Expand left highlight
873                                         if(highlight_letter1 == ibeam_letter)
874                                         {
875                                                 highlight_letter1 = new_letter;
876                                         }
877                                         else
878 // Shrink right highlight
879                                         if(highlight_letter2 == ibeam_letter)
880                                         {
881                                                 highlight_letter2 = new_letter;
882                                         }
883                                 }
884                                 else
885                                         highlight_letter1 = highlight_letter2 = new_letter;
887                                 if(highlight_letter1 > highlight_letter2)
888                                 {
889                                         int temp = highlight_letter1;
890                                         highlight_letter1 = highlight_letter2;
891                                         highlight_letter2 = temp;
892                                 }
893                                 ibeam_letter = new_letter;
895                                 find_ibeam(1);
896                                 if(keypress_draw) draw();
897                         }
898                         result = 1;
899                         break;
901                 case PGUP:
902                         if(ibeam_letter > 0)
903                         {
904                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
905                                         ibeam_y + text_y - get_h());
907 // Extend selection
908                                 if(top_level->shift_down())
909                                 {
910 // Initialize highlighting
911                                         if(highlight_letter1 == highlight_letter2)
912                                         {
913                                                 highlight_letter1 = new_letter;
914                                                 highlight_letter2 = ibeam_letter;
915                                         }
916                                         else
917 // Expand left highlight
918                                         if(highlight_letter1 == ibeam_letter)
919                                         {
920                                                 highlight_letter1 = new_letter;
921                                         }
922                                         else
923 // Shrink right highlight
924                                         if(highlight_letter2 == ibeam_letter)
925                                         {
926                                                 highlight_letter2 = new_letter;
927                                         }
928                                 }
929                                 else
930                                         highlight_letter1 = highlight_letter2 = new_letter;
932                                 if(highlight_letter1 > highlight_letter2)
933                                 {
934                                         int temp = highlight_letter1;
935                                         highlight_letter1 = highlight_letter2;
936                                         highlight_letter2 = temp;
937                                 }
938                                 ibeam_letter = new_letter;
940                                 find_ibeam(1);
941                                 if(keypress_draw) draw();
942                         }
943                         result = 1;
944                         break;
946                 case DOWN:
947 //                      if(ibeam_letter > 0)
948                         {
949 // Extend selection
950                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
951                                         ibeam_y + text_y + text_height);
952 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
954                                 if(top_level->shift_down())
955                                 {
956 // Initialize highlighting
957                                         if(highlight_letter1 == highlight_letter2)
958                                         {
959                                                 highlight_letter1 = new_letter;
960                                                 highlight_letter2 = ibeam_letter;
961                                         }
962                                         else
963 // Shrink left highlight
964                                         if(highlight_letter1 == ibeam_letter)
965                                         {
966                                                 highlight_letter1 = new_letter;
967                                         }
968                                         else
969 // Expand right highlight
970                                         if(highlight_letter2 == ibeam_letter)
971                                         {
972                                                 highlight_letter2 = new_letter;
973                                         }
974                                 }
975                                 else
976                                         highlight_letter1 = highlight_letter2 = new_letter;
978                                 if(highlight_letter1 > highlight_letter2)
979                                 {
980                                         int temp = highlight_letter1;
981                                         highlight_letter1 = highlight_letter2;
982                                         highlight_letter2 = temp;
983                                 }
984                                 ibeam_letter = new_letter;
986                                 find_ibeam(1);
987                                 if(keypress_draw) draw();
989 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
990                         }
991                         result = 1;
992                         break;
994                 case PGDN:
995                         {
996 // Extend selection
997                                 int new_letter = get_cursor_letter(ibeam_x + text_x, 
998                                         ibeam_y + text_y + get_h());
999 //printf("BC_TextBox::keypress_event 10 %d\n", new_letter);
1001                                 if(top_level->shift_down())
1002                                 {
1003 // Initialize highlighting
1004                                         if(highlight_letter1 == highlight_letter2)
1005                                         {
1006                                                 highlight_letter1 = new_letter;
1007                                                 highlight_letter2 = ibeam_letter;
1008                                         }
1009                                         else
1010 // Shrink left highlight
1011                                         if(highlight_letter1 == ibeam_letter)
1012                                         {
1013                                                 highlight_letter1 = new_letter;
1014                                         }
1015                                         else
1016 // Expand right highlight
1017                                         if(highlight_letter2 == ibeam_letter)
1018                                         {
1019                                                 highlight_letter2 = new_letter;
1020                                         }
1021                                 }
1022                                 else
1023                                         highlight_letter1 = highlight_letter2 = new_letter;
1025                                 if(highlight_letter1 > highlight_letter2)
1026                                 {
1027                                         int temp = highlight_letter1;
1028                                         highlight_letter1 = highlight_letter2;
1029                                         highlight_letter2 = temp;
1030                                 }
1031                                 ibeam_letter = new_letter;
1033                                 find_ibeam(1);
1034                                 if(keypress_draw) draw();
1036 //printf("BC_TextBox::keypress_event 20 %d\n", ibeam_letter);
1037                         }
1038                         result = 1;
1039                         break;
1040                 
1041                 case END:
1042                 {
1043                         int old_ibeam_letter = ibeam_letter;
1045                         while(ibeam_letter < text_len && text[ibeam_letter] != '\n')
1046                                 ibeam_letter++;
1048                         if(top_level->shift_down())
1049                         {
1050 // Begin selection
1051                                 if(highlight_letter1 == highlight_letter2)
1052                                 {
1053                                         highlight_letter2 = ibeam_letter;
1054                                         highlight_letter1 = old_ibeam_letter;
1055                                 }
1056                                 else
1057 // Shrink selection
1058                                 if(highlight_letter1 == old_ibeam_letter)
1059                                 {
1060                                         highlight_letter1 = highlight_letter2;
1061                                         highlight_letter2 = ibeam_letter;
1062                                 }
1063                                 else
1064 // Extend selection
1065                                 if(highlight_letter2 == old_ibeam_letter)
1066                                 {
1067                                         highlight_letter2 = ibeam_letter;
1068                                 }
1069                         }
1070                         else
1071                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1073                         find_ibeam(1);
1074                         if(keypress_draw) draw();
1075                         result = 1;
1076                         break;
1077                 }
1079                 case HOME:
1080                 {
1081                         int old_ibeam_letter = ibeam_letter;
1083                         while(ibeam_letter > 0 && text[ibeam_letter - 1] != '\n')
1084                                 ibeam_letter--;
1086                         if(top_level->shift_down())
1087                         {
1088 // Begin selection
1089                                 if(highlight_letter1 == highlight_letter2)
1090                                 {
1091                                         highlight_letter2 = old_ibeam_letter;
1092                                         highlight_letter1 = ibeam_letter;
1093                                 }
1094                                 else
1095 // Extend selection
1096                                 if(highlight_letter1 == old_ibeam_letter)
1097                                 {
1098                                         highlight_letter1 = ibeam_letter;
1099                                 }
1100                                 else
1101 // Shrink selection
1102                                 if(highlight_letter2 == old_ibeam_letter)
1103                                 {
1104                                         highlight_letter2 = highlight_letter1;
1105                                         highlight_letter1 = ibeam_letter;
1106                                 }
1107                         }
1108                         else
1109                                 highlight_letter1 = highlight_letter2 = ibeam_letter;
1111                         find_ibeam(1);
1112                         if(keypress_draw) draw();
1113                         result = 1;
1114                         break;
1115                 }
1117         case BACKSPACE:
1118                         if(highlight_letter1 == highlight_letter2)
1119                         {
1120                                 if(ibeam_letter > 0)
1121                                 {
1122                                         delete_selection(ibeam_letter - 1, ibeam_letter, text_len);
1123                                         ibeam_letter--;
1124                                 }
1125                         }
1126                         else
1127                         {
1128                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1129                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1130                         }
1132                         find_ibeam(1);
1133                         if(keypress_draw) draw();
1134                         dispatch_event = 1;
1135                         result = 1;
1136                 break;
1138                 case DELETE:
1139                         if(highlight_letter1 == highlight_letter2)
1140                         {
1141                                 if(ibeam_letter < text_len)
1142                                 {
1143                                         delete_selection(ibeam_letter, ibeam_letter + 1, text_len);
1144                                 }
1145                         }
1146                         else
1147                         {
1148                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1149                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1150                         }
1151                         
1152                         find_ibeam(1);
1153                         if(keypress_draw) draw();
1154                         dispatch_event = 1;
1155                         result = 1;
1156                         break;
1160                 default:
1161                         if(ctrl_down())
1162                         {
1163                                 if(get_keypress() == 'c' || get_keypress() == 'C')
1164                                 {
1165                                         if(highlight_letter1 != highlight_letter2)
1166                                         {
1167                                                 copy_selection(SECONDARY_SELECTION);
1168                                                 result = 1;
1169                                         }
1170                                 }
1171                                 else
1172                                 if(get_keypress() == 'v' || get_keypress() == 'V')
1173                                 {
1174                                         paste_selection(SECONDARY_SELECTION);
1175                                         find_ibeam(1);
1176                                         if(keypress_draw) draw();
1177                                         dispatch_event = 1;
1178                                         result = 1;
1179                                 }
1180                                 else
1181                                 if(get_keypress() == 'x' || get_keypress() == 'X')
1182                                 {
1183                                         if(highlight_letter1 != highlight_letter2)
1184                                         {
1185                                                 copy_selection(SECONDARY_SELECTION);
1186                                                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1187                                                 highlight_letter2 = ibeam_letter = highlight_letter1;
1188                                         }
1190                                         find_ibeam(1);
1191                                         if(keypress_draw) draw();
1192                                         dispatch_event = 1;
1193                                         result = 1;
1194                                 }
1195                                 
1196                                 break;
1197                         }
1199                         default_keypress(dispatch_event, result);
1200                         break;
1201         }
1203         if(dispatch_event) skip_cursor->update();
1204         if(dispatch_event) handle_event();
1205 //printf("BC_TextBox::keypress_event 100 %d\n", ibeam_letter);
1206         return result;
1211 int BC_TextBox::uses_text()
1213         return 1;
1216 void BC_TextBox::delete_selection(int letter1, int letter2, int text_len)
1218         int i, j;
1219         
1220         for(i = letter1, j = letter2; j < text_len; i++, j++)
1221         {
1222                 text[i] = text[j];
1223         }
1224         text[i] = 0;
1226         do_separators(1);
1229 void BC_TextBox::insert_text(char *string)
1231         int i, j, text_len, string_len;
1233         string_len = strlen(string);
1234         text_len = strlen(text);
1235         if(highlight_letter1 < highlight_letter2)
1236         {
1237                 delete_selection(highlight_letter1, highlight_letter2, text_len);
1238                 highlight_letter2 = ibeam_letter = highlight_letter1;
1239         }
1241         text_len = strlen(text);
1243         for(i = text_len, j = text_len + string_len; i >= ibeam_letter; i--, j--)
1244                 text[j] = text[i];
1246         for(i = ibeam_letter, j = 0; j < string_len; j++, i++)
1247                 text[i] = string[j];
1249         ibeam_letter += string_len;
1251         do_separators(0);
1254 void BC_TextBox::do_separators(int ibeam_left)
1256         if(separators)
1257         {
1258 // Remove separators from text
1259                 int text_len = strlen(text);
1260                 int separator_len = strlen(separators);
1261                 for(int i = 0; i < text_len; i++)
1262                 {
1263                         if(!isalnum(text[i]))
1264                         {
1265                                 for(int j = i; j < text_len - 1; j++)
1266                                         text[j] = text[j + 1];
1267                                 if(!ibeam_left && i < ibeam_letter) ibeam_letter--;
1268                                 text_len--;
1269                                 i--;
1270                         }
1271                 }
1272                 text[text_len] = 0;
1279 // Insert separators into text
1280                 for(int i = 0; i < separator_len; i++)
1281                 {
1282                         if(i < text_len)
1283                         {
1284 // Insert a separator
1285                                 if(!isalnum(separators[i]))
1286                                 {
1287                                         for(int j = text_len; j >= i; j--)
1288                                         {
1289                                                 text[j + 1] = text[j];
1290                                         }
1291                                         if(!ibeam_left && i < ibeam_letter) ibeam_letter++;
1292                                         text_len++;
1293                                         text[i] = separators[i];
1294                                 }
1295                         }
1296                         else
1297                         if(i >= text_len)
1298                         {
1299                                 text[i] = separators[i];
1300                         }
1301                 }
1303 // Truncate text
1304                 text[separator_len] = 0;
1305         }
1309 void BC_TextBox::get_ibeam_position(int &x, int &y)
1311         int i, j, k, row_begin, row_end, text_len;
1313         text_len = strlen(text);
1314         y = 0;
1315         x = 0;
1316         for(i = 0; i < text_len; )
1317         {
1318                 row_begin = i;
1319                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1320                 {
1321                         text_row[j] = text[i];
1322                 }
1324                 row_end = i;
1325                 text_row[j] = 0;
1327                 if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
1328                 {
1329                         x = get_text_width(font, text_row, ibeam_letter - row_begin);
1330 //printf("BC_TextBox::get_ibeam_position 9 %d %d\n", x, y);
1331                         return;
1332                 }
1334                 if(text[i] == '\n')
1335                 {
1336                         i++;
1337                         y += text_height;
1338                 }
1339         }
1340 //printf("BC_TextBox::get_ibeam_position 10 %d %d\n", x, y);
1342         x = 0;
1343         return;
1346 void BC_TextBox::set_text_row(int row)
1348         text_y = -(row * text_height) + top_margin;
1349         draw();
1352 int BC_TextBox::get_text_row()
1354         return -(text_y - top_margin) / text_height;
1357 void BC_TextBox::find_ibeam(int dispatch_event)
1359         int x, y;
1360         int old_x = text_x, old_y = text_y;
1362         get_ibeam_position(x, y);
1364         if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
1365         {
1366                 text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
1367                 if(text_x > left_margin) text_x = left_margin;
1368         }
1369         else
1370         if(left_margin + text_x + x < left_margin)
1371         {
1372                 text_x = -(x - (get_w() / 4)) + left_margin;
1373                 if(text_x > left_margin) text_x = left_margin;
1374         }
1376         while(y + text_y >= get_h() - text_height - bottom_margin)
1377         {
1378                 text_y -= text_height;
1379 //              text_y = -(y - (get_h() / 2)) + top_margin;
1380 //              if(text_y > top_margin) text_y = top_margin;
1381         }
1383         while(y + text_y < top_margin)
1384         {
1385                 text_y += text_height;
1386                 if(text_y > top_margin) 
1387                 {
1388                         text_y = top_margin;
1389                         break;
1390                 }
1391         }
1393         if(dispatch_event && (old_x != text_x || old_y != text_y)) motion_event();
1396 int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
1398         int i, j, k, l, row_begin, row_end, text_len, result = 0, done = 0;
1399         text_len = strlen(text);
1401         if(cursor_y < text_y)
1402         {
1403                 result = 0;
1404                 done = 1;
1405         }
1407         for(i = 0, k = text_y; i < text_len && !done; k += text_height)
1408         {
1409                 row_begin = i;
1410                 for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
1411                 {
1412                         text_row[j] = text[i];
1413                 }
1414                 row_end = i;
1415                 text_row[j] = 0;
1417                 if(cursor_y >= k && cursor_y < k + text_height)
1418                 {
1419                         for(j = 0; j <= row_end - row_begin && !done; j++)
1420                         {
1421                                 l = get_text_width(font, text_row, j) + text_x;
1422                                 if(l > cursor_x)
1423                                 {
1424                                         result = row_begin + j - 1;
1425                                         done = 1;
1426                                 }
1427                         }
1428                         if(!done)
1429                         {
1430                                 result = row_end;
1431                                 done = 1;
1432                         }
1433                 }
1434                 if(text[i] == '\n') i++;
1435                 
1436                 if(i >= text_len && !done)
1437                 {
1438                         result = text_len;
1439                 }
1440         }
1441         if(result < 0) result = 0;
1442         if(result > text_len) result = text_len;
1443         return result;
1446 void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
1448         int text_len = strlen(text);
1449         letter1 = letter2 = ibeam_letter;
1450         do
1451         {
1452                 if(isalnum(text[letter1])) letter1--;
1453         }while(letter1 > 0 && isalnum(text[letter1]));
1454         if(!isalnum(text[letter1])) letter1++;
1456         do
1457         {
1458                 if(isalnum(text[letter2])) letter2++;
1459         }while(letter2 < text_len && isalnum(text[letter2]));
1460         if(letter2 < text_len && text[letter2] == ' ') letter2++;
1462         if(letter1 < 0) letter1 = 0;
1463         if(letter2 < 0) letter2 = 0;
1464         if(letter1 > text_len) letter1 = text_len;
1465         if(letter2 > text_len) letter2 = text_len;
1468 void BC_TextBox::copy_selection(int clipboard_num)
1470         int text_len = strlen(text);
1472         if(highlight_letter1 >= text_len ||
1473                 highlight_letter2 > text_len ||
1474                 highlight_letter1 < 0 ||
1475                 highlight_letter2 < 0 ||
1476                 highlight_letter2 - highlight_letter1 <= 0) return;
1478         get_clipboard()->to_clipboard(&text[highlight_letter1], 
1479                 highlight_letter2 - highlight_letter1, 
1480                 clipboard_num);
1483 void BC_TextBox::paste_selection(int clipboard_num)
1485         int len = get_clipboard()->clipboard_len(clipboard_num);
1486         if(len)
1487         {
1488                 char *string = new char[len + 1];
1489                 get_clipboard()->from_clipboard(string, len, clipboard_num);
1490                 insert_text(string);
1491         }
1494 void BC_TextBox::set_keypress_draw(int value)
1496         keypress_draw = value;
1499 int BC_TextBox::get_last_keypress()
1501         return last_keypress;
1504 int BC_TextBox::get_ibeam_letter()
1506         return ibeam_letter;
1509 void BC_TextBox::set_ibeam_letter(int number, int redraw)
1511         this->ibeam_letter = number;
1512         if(redraw)
1513         {
1514                 draw();
1515         }
1518 void BC_TextBox::set_separators(char *separators)
1520         this->separators = separators;
1538 BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window, 
1539         int x, 
1540         int y, 
1541         int w,
1542         int rows,
1543         char *default_text)
1545         this->parent_window = parent_window;
1546         this->x = x;
1547         this->y = y;
1548         this->w = w;
1549         this->rows = rows;
1550         this->default_text = default_text;
1553 BC_ScrollTextBox::~BC_ScrollTextBox()
1555         delete yscroll;
1556         if(text)
1557         {
1558                 text->gui = 0;
1559                 delete text;
1560         }
1563 void BC_ScrollTextBox::create_objects()
1565 // Must be created first
1566         parent_window->add_subwindow(text = new BC_ScrollTextBoxText(this));
1567         parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
1570 int BC_ScrollTextBox::handle_event()
1572         return 1;
1575 int BC_ScrollTextBox::get_x()
1577         return x;
1580 int BC_ScrollTextBox::get_y()
1582         return y;
1585 int BC_ScrollTextBox::get_w()
1587         return w;
1590 int BC_ScrollTextBox::get_rows()
1592         return rows;
1596 char* BC_ScrollTextBox::get_text()
1598         return text->get_text();
1601 void BC_ScrollTextBox::update(char *text)
1603         this->text->update(text);
1604         yscroll->update_length(this->text->get_text_rows(),
1605                 this->text->get_text_row(),
1606                 yscroll->get_handlelength());
1609 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
1611         this->x = x;
1612         this->y = y;
1613         this->w = w;
1614         this->rows = rows;
1615         text->reposition_window(x, 
1616                 y, 
1617                 w - yscroll->get_span(), 
1618                 rows);
1619         yscroll->reposition_window(x + w - yscroll->get_span(), 
1620                 y, 
1621                 BC_TextBox::calculate_row_h(rows, 
1622                         parent_window));
1623         yscroll->update_length(text->get_text_rows(),
1624                 text->get_text_row(),
1625                 rows);
1636 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui)
1637  : BC_TextBox(gui->x, 
1638         gui->y, 
1639         gui->w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1640         gui->rows,
1641         gui->default_text)
1643         this->gui = gui;
1646 BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
1648         if(gui)
1649         {
1650                 gui->text = 0;
1651                 delete gui;
1652         }
1655 int BC_ScrollTextBoxText::handle_event()
1657         gui->yscroll->update_length(get_text_rows(),
1658                 get_text_row(),
1659                 gui->yscroll->get_handlelength());
1660         return gui->handle_event();
1663 int BC_ScrollTextBoxText::motion_event()
1665         gui->yscroll->update_length(get_text_rows(),
1666                 get_text_row(),
1667                 gui->yscroll->get_handlelength());
1668         return 1;
1672 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
1673  : BC_ScrollBar(gui->x + 
1674                         gui->w - 
1675                         get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(), 
1676                 gui->y, 
1677                 SCROLL_VERT, 
1678                 BC_TextBox::calculate_row_h(gui->rows, 
1679                         gui->parent_window), 
1680                 gui->text->get_text_rows(), 
1681                 0, 
1682                 gui->rows)
1684         this->gui = gui;
1687 BC_ScrollTextBoxYScroll::~BC_ScrollTextBoxYScroll()
1691 int BC_ScrollTextBoxYScroll::handle_event()
1693         gui->text->set_text_row(get_position());
1694         return 1;
1706 BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y)
1707  : BC_TextBox(x, y, popup->text_w, 1, popup->default_text)
1709         this->popup = popup;
1712 BC_PopupTextBoxText::~BC_PopupTextBoxText()
1714         if(popup)
1715         {
1716                 popup->textbox = 0;
1717                 delete popup;
1718                 popup = 0;
1719         }
1723 int BC_PopupTextBoxText::handle_event()
1725         popup->handle_event();
1726         return 1;
1729 BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
1730  : BC_ListBox(x,
1731         y,
1732         popup->text_w + BC_WindowBase::get_resources()->listbox_button[0]->get_w(),
1733         popup->list_h,
1734         LISTBOX_TEXT,
1735         popup->list_items,
1736         0,
1737         0,
1738         1,
1739         0,
1740         1)
1742         this->popup = popup;
1744 int BC_PopupTextBoxList::handle_event()
1746         BC_ListBoxItem *item = get_selection(0, 0);
1747         if(item)
1748         {
1749                 popup->textbox->update(item->get_text());
1750                 popup->handle_event();
1751         }
1752         return 1;
1758 BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window, 
1759                 ArrayList<BC_ListBoxItem*> *list_items,
1760                 char *default_text,
1761                 int x, 
1762                 int y, 
1763                 int text_w,
1764                 int list_h)
1766         this->x = x;
1767         this->y = y;
1768         this->list_h = list_h;
1769         this->default_text = default_text;
1770         this->text_w = text_w;
1771         this->parent_window = parent_window;
1772         this->list_items = list_items;
1775 BC_PopupTextBox::~BC_PopupTextBox()
1777         delete listbox;
1778         if(textbox) 
1779         {
1780                 textbox->popup = 0;
1781                 delete textbox;
1782         }
1785 int BC_PopupTextBox::create_objects()
1787         int x = this->x, y = this->y;
1788         parent_window->add_subwindow(textbox = new BC_PopupTextBoxText(this, x, y));
1789         x += textbox->get_w();
1790         parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
1791         return 0;
1794 void BC_PopupTextBox::update(char *text)
1796         textbox->update(text);
1799 void BC_PopupTextBox::update_list(ArrayList<BC_ListBoxItem*> *data)
1801         listbox->update(data, 
1802                 0, 
1803                 0,
1804                 1);
1808 char* BC_PopupTextBox::get_text()
1810         return textbox->get_text();
1813 int BC_PopupTextBox::get_number()
1815         return listbox->get_selection_number(0, 0);
1818 int BC_PopupTextBox::get_x()
1820         return x;
1823 int BC_PopupTextBox::get_y()
1825         return y;
1828 int BC_PopupTextBox::get_w()
1830         return textbox->get_w() + listbox->get_w();
1833 int BC_PopupTextBox::get_h()
1835         return textbox->get_h();
1838 int BC_PopupTextBox::handle_event()
1840         return 1;
1843 int BC_PopupTextBox::reposition_widget(int x, int y, int w, int h) {
1844         reposition_window(x, y);
1845         return(0);
1848 void BC_PopupTextBox::reposition_window(int x, int y)
1850         this->x = x;
1851         this->y = y;
1852         int x1 = x, y1 = y;
1853         textbox->reposition_window(x1, y1);
1854         x1 += textbox->get_w();
1855         listbox->reposition_window(x1, y1);
1871 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1872         int64_t default_value,
1873         int64_t min,
1874         int64_t max,
1875         int x, 
1876         int y)
1877  : BC_TextBox(x, 
1878         y, 
1879         popup->text_w, 
1880         1, 
1881         default_value)
1883         this->popup = popup;
1886 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, 
1887         float default_value,
1888         float min,
1889         float max,
1890         int x, 
1891         int y)
1892  : BC_TextBox(x, 
1893         y, 
1894         popup->text_w, 
1895         1, 
1896         default_value)
1898         this->popup = popup;
1901 BC_TumbleTextBoxText::~BC_TumbleTextBoxText()
1903         if(popup)
1904         {
1905                 popup->textbox = 0;
1906                 delete popup;
1907                 popup = 0;
1908         }
1913 int BC_TumbleTextBoxText::handle_event()
1915         popup->handle_event();
1916         return 1;
1919 int BC_TumbleTextBoxText::button_press_event()
1921         if(is_event_win())
1922         {
1923                 if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
1924                 if(get_buttonpress() == 4)
1925                 {
1926                         popup->tumbler->handle_up_event();
1927                 }
1928                 else
1929                 if(get_buttonpress() == 5)
1930                 {
1931                         popup->tumbler->handle_down_event();
1932                 }
1933                 return 1;
1934         }
1935         return 0;
1941 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1942                 int64_t default_value,
1943                 int64_t min,
1944                 int64_t max,
1945                 int x, 
1946                 int y, 
1947                 int text_w)
1949         reset();
1950         this->x = x;
1951         this->y = y;
1952         this->min = min;
1953         this->max = max;
1954         this->default_value = default_value;
1955         this->text_w = text_w;
1956         this->parent_window = parent_window;
1957         use_float = 0;
1958         precision = 4;
1959         increment = 1;
1960         log_floatincrement = 0;
1963 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1964                 int default_value,
1965                 int min,
1966                 int max,
1967                 int x, 
1968                 int y, 
1969                 int text_w)
1971         reset();
1972         this->x = x;
1973         this->y = y;
1974         this->min = min;
1975         this->max = max;
1976         this->default_value = default_value;
1977         this->text_w = text_w;
1978         this->parent_window = parent_window;
1979         use_float = 0;
1980         precision = 4;
1981         increment = 1;
1982         log_floatincrement = 0;
1985 BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
1986                 float default_value_f,
1987                 float min_f,
1988                 float max_f,
1989                 int x, 
1990                 int y, 
1991                 int text_w)
1993         reset();
1994         this->x = x;
1995         this->y = y;
1996         this->min_f = min_f;
1997         this->max_f = max_f;
1998         this->default_value_f = default_value_f;
1999         this->text_w = text_w;
2000         this->parent_window = parent_window;
2001         use_float = 1;
2002         precision = 4;
2003         increment = 1;
2004         log_floatincrement = 0;
2007 BC_TumbleTextBox::~BC_TumbleTextBox()
2009 // Recursive delete.  Normally ~BC_TumbleTextBox is never called but textbox
2010 // is deleted anyway by the windowbase so textbox deletes this.
2011         if(tumbler) delete tumbler;
2012         tumbler = 0;
2013 // Don't delete text here if we were called by ~BC_TumbleTextBoxText
2014         if(textbox)
2015         {
2016                 textbox->popup = 0;
2017                 delete textbox;
2018         }
2019         textbox = 0;
2022 void BC_TumbleTextBox::reset()
2024         textbox = 0;
2025         tumbler = 0;
2026         increment = 1.0;
2027         log_floatincrement = 0;
2030 void BC_TumbleTextBox::set_precision(int precision)
2032         this->precision = precision;
2035 void BC_TumbleTextBox::set_increment(float value)
2037         this->increment = value;
2038         if(tumbler) tumbler->set_increment(value);
2041 void BC_TumbleTextBox::set_log_floatincrement(int value)
2043         this->log_floatincrement = value;
2044         if(tumbler) tumbler->set_log_floatincrement(value);
2047 int BC_TumbleTextBox::create_objects()
2049         int x = this->x, y = this->y;
2051         if(use_float)
2052         {
2053                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
2054                         default_value_f,
2055                         min_f, 
2056                         max_f, 
2057                         x, 
2058                         y));
2059                 textbox->set_precision(precision);
2060         }
2061         else
2062                 parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, 
2063                         default_value,
2064                         min, 
2065                         max, 
2066                         x, 
2067                         y));
2069         x += textbox->get_w();
2071         if(use_float)
2072                 parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox, 
2073                         min_f,
2074                         max_f,
2075                         x, 
2076                         y));
2077         else
2078                 parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox, 
2079                         min, 
2080                         max, 
2081                         x, 
2082                         y));
2084         tumbler->set_increment(increment);
2085         tumbler->set_log_floatincrement(log_floatincrement);
2086         return 0;
2089 char* BC_TumbleTextBox::get_text()
2091         return textbox->get_text();
2094 int BC_TumbleTextBox::update(char *value)
2096         textbox->update(value);
2097         return 0;
2100 int BC_TumbleTextBox::update(int64_t value)
2102         textbox->update(value);
2103         return 0;
2106 int BC_TumbleTextBox::update(float value)
2108         textbox->update(value);
2109         return 0;
2113 int BC_TumbleTextBox::get_x()
2115         return x;
2118 int BC_TumbleTextBox::get_y()
2120         return y;
2123 int BC_TumbleTextBox::get_w()
2125         return textbox->get_w() + tumbler->get_w();
2128 int BC_TumbleTextBox::get_h()
2130         return textbox->get_h();
2133 int BC_TumbleTextBox::handle_event()
2135         return 1;
2138 int BC_TumbleTextBox::reposition_widget(int x, int y, int w, int h) {
2139         reposition_window(x, y);
2140         return(0);
2143 void BC_TumbleTextBox::reposition_window(int x, int y)
2145         this->x = x;
2146         this->y = y;
2147         
2148         textbox->reposition_window(x, 
2149                 y, 
2150                 text_w, 
2151                 1);
2152         tumbler->reposition_window(x + textbox->get_w(),
2153                 y);
2157 void BC_TumbleTextBox::set_boundaries(int64_t min, int64_t max)
2159         tumbler->set_boundaries(min, max);
2162 void BC_TumbleTextBox::set_boundaries(float min, float max)
2164         tumbler->set_boundaries(min, max);