home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / bctextbox.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  19KB  |  1,017 lines

  1. #include "bcresources.h"
  2. #include "bctextbox.h"
  3. #include "colors.h"
  4. #include <ctype.h>
  5. #include "cursors.h"
  6. #include "keys.h"
  7.  
  8. #include <string.h>
  9.  
  10. BC_TextBox::BC_TextBox(int x, int y, int w, int rows, char *text, int has_border, int font)
  11.  : BC_SubWindow(x, y, w, 0, -1)
  12. {
  13.     reset_parameters(rows, has_border, font);
  14.     strcpy(this->text, text);
  15. }
  16.  
  17. BC_TextBox::BC_TextBox(int x, int y, int w, int rows, long text, int has_border, int font)
  18.  : BC_SubWindow(x, y, w, 0, -1)
  19. {
  20.     reset_parameters(rows, has_border, font);
  21.     sprintf(this->text, "%ld", text);
  22. }
  23.  
  24. BC_TextBox::BC_TextBox(int x, int y, int w, int rows, float text, int has_border, int font)
  25.  : BC_SubWindow(x, y, w, 0, -1)
  26. {
  27.     reset_parameters(rows, has_border, font);
  28.     sprintf(this->text, "%0.2f", text);
  29. }
  30.  
  31. BC_TextBox::BC_TextBox(int x, int y, int w, int rows, int text, int has_border, int font)
  32.  : BC_SubWindow(x, y, w, 0, -1)
  33. {
  34.     reset_parameters(rows, has_border, font);
  35.     sprintf(this->text, "%d", text);
  36. }
  37.  
  38. BC_TextBox::~BC_TextBox()
  39. {
  40. }
  41.  
  42. int BC_TextBox::reset_parameters(int rows, int has_border, int font)
  43. {
  44.     this->rows = rows;
  45.     this->has_border = has_border;
  46.     this->font = font;
  47.     text_start = 0;
  48.     text_end = 0;
  49.     highlight_letter1 = highlight_letter2 = 0;
  50.     highlight_letter3 = highlight_letter4 = 0;
  51.     ibeam_letter = 0;
  52.     active = 0;
  53.     text_selected = word_selected = 0;
  54.     text_x = 0;
  55.     return 0;
  56. }
  57.  
  58. int BC_TextBox::initialize()
  59. {
  60. // Get dimensions
  61.     text_ascent = get_text_ascent(font) + 1;
  62.     text_descent = get_text_descent(font) + 1;
  63.     text_height = text_ascent + text_descent;
  64.     ibeam_letter = strlen(text);
  65.     if(has_border)
  66.     { 
  67.         left_margin = right_margin = 4;
  68.         top_margin = bottom_margin = 2;
  69.     }
  70.     else 
  71.     { 
  72.         left_margin = right_margin = 2;
  73.         top_margin = bottom_margin = 0;
  74.     }
  75.     h = get_row_h(rows);
  76.     text_x = left_margin;
  77.     find_ibeam();
  78.  
  79. // Create the subwindow
  80.     BC_SubWindow::initialize();
  81.  
  82.     if(has_border)
  83.     {
  84.         back_color = WHITE;
  85.         high_color = LTYELLOW;
  86.     }
  87.     else 
  88.     {
  89.         high_color = LTGREY;
  90.         back_color = bg_color;
  91.     }
  92.  
  93.     draw();
  94.     set_cursor(IBEAM_CURSOR);
  95.     return 0;
  96. }
  97.  
  98. int BC_TextBox::update(char *text)
  99. {
  100.     int text_len = strlen(text);
  101.     strcpy(this->text, text);
  102.     if(highlight_letter1 > text_len) highlight_letter1 = text_len;
  103.     if(highlight_letter2 > text_len) highlight_letter2 = text_len;
  104.     ibeam_letter = text_len;
  105.     draw();
  106.     return 0;
  107. }
  108.  
  109. int BC_TextBox::update(long value)
  110. {
  111.     sprintf(this->text, "%ld", value);
  112.     int text_len = strlen(text);
  113.     if(highlight_letter1 > text_len) highlight_letter1 = text_len;
  114.     if(highlight_letter2 > text_len) highlight_letter2 = text_len;
  115.     ibeam_letter = text_len;
  116.     draw();
  117.     return 0;
  118. }
  119.  
  120. int BC_TextBox::update(float value)
  121. {
  122.     sprintf(this->text, "%0.2f", value);
  123.     int text_len = strlen(text);
  124.     if(highlight_letter1 > text_len) highlight_letter1 = text_len;
  125.     if(highlight_letter2 > text_len) highlight_letter2 = text_len;
  126.     ibeam_letter = text_len;
  127.     draw();
  128.     return 0;
  129. }
  130.  
  131. char* BC_TextBox::get_text()
  132. {
  133.     return text;
  134. }
  135.  
  136. int BC_TextBox::get_row_h(int rows)
  137. {
  138.     return rows * text_height + top_margin + bottom_margin;
  139. }
  140.  
  141. int BC_TextBox::reposition_window(int x, int y, int w, int rows)
  142. {
  143.     int new_h = get_h();
  144.     if(rows != -1)
  145.     {
  146.         new_h = get_row_h(rows);
  147.         this->rows = rows;
  148.     }
  149.     BC_WindowBase::reposition_window(x, y, w, new_h);
  150.     draw();
  151.     return 0;
  152. }
  153.  
  154. void BC_TextBox::draw_border()
  155. {
  156. // Clear margins
  157.     set_color(background_color);
  158.     draw_box(0, 0, left_margin, get_h());
  159.     draw_box(get_w() - right_margin, 0, right_margin, get_h());
  160.  
  161.     if(has_border)
  162.     {
  163.         if(highlighted)
  164.             draw_3d_border(0, 0, w, h,
  165.                 top_level->get_resources()->button_shadow, 
  166.                 RED, 
  167.                 LTPINK,
  168.                 top_level->get_resources()->button_light);
  169.         else
  170.             draw_3d_border(0, 0, w, h, 
  171.                 top_level->get_resources()->button_shadow, 
  172.                 BLACK, 
  173.                 top_level->get_resources()->button_up,
  174.                 top_level->get_resources()->button_light);
  175.     }
  176. }
  177.  
  178. void BC_TextBox::draw_cursor()
  179. {
  180.     set_color(background_color);
  181.     set_inverse();
  182.     draw_box(ibeam_x, ibeam_y, BCCURSORW, text_height);
  183.     set_opaque();
  184. }
  185.  
  186.  
  187. void BC_TextBox::draw()
  188. {
  189.     int i, j, k, text_len;
  190.     int row_begin, row_end;
  191.     int highlight_x1, highlight_x2;
  192.     int need_ibeam = 1;
  193.  
  194. // Background
  195.     if(has_border)
  196.     {
  197.         background_color = WHITE;
  198.     }
  199.     else
  200.     {
  201.         if(highlighted)
  202.         {
  203.             background_color = high_color;
  204.         }
  205.         else
  206.         {
  207.             background_color = back_color;
  208.         }
  209.     }
  210.  
  211.     set_color(background_color);
  212.     draw_box(0, 0, w, h);
  213.  
  214. // Draw text with selection
  215.     set_font(font);
  216.     text_len = strlen(text);
  217.     for(i = 0, k = text_y; i < text_len && k < get_h(); k += text_height)
  218.     {
  219. // Draw row of text
  220.         row_begin = i;
  221.         for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
  222.         {
  223.             text_row[j] = text[i];
  224.         }
  225.         row_end = i;
  226.  
  227.         text_row[j] = 0;
  228.  
  229.         if(k > -text_height + top_margin && k < get_h() - bottom_margin)
  230.         {
  231. // Draw highlighted region of row
  232.             if(highlight_letter2 > highlight_letter1 &&
  233.                 ((row_begin <= highlight_letter1 && row_end >= highlight_letter2) ||
  234.                  (row_begin < highlight_letter2 && row_end >= highlight_letter2) ||
  235.                  (row_begin <= highlight_letter1 && row_end > highlight_letter1)))
  236.             {
  237.                 if(active)
  238.                     set_color(top_level->get_resources()->text_highlight);
  239.                 else
  240.                     set_color(MEGREY);
  241.  
  242.                 if(highlight_letter1 >= row_begin && highlight_letter1 < row_end)
  243.                     highlight_x1 = get_text_width(font, text_row, highlight_letter1 - row_begin);
  244.                 else
  245.                     highlight_x1 = 0;
  246.  
  247.                 if(highlight_letter2 > row_begin && highlight_letter2 <= row_end)
  248.                     highlight_x2 = get_text_width(font, text_row, highlight_letter2 - row_begin);
  249.                 else
  250.                     highlight_x2 = get_w();
  251.  
  252.                 draw_box(highlight_x1 + text_x, 
  253.                     k, 
  254.                     highlight_x2 - highlight_x1, 
  255.                     text_height);
  256.             }
  257.  
  258. // Draw text over highlight
  259.             set_color(BLACK);
  260.             draw_text(text_x, k + text_ascent, text_row);
  261. // Get ibeam location
  262.             if(ibeam_letter >= row_begin || ibeam_letter <= row_end)
  263.             {
  264.                 need_ibeam = 0;
  265.                 ibeam_y = k;
  266.                 ibeam_x = text_x + get_text_width(font, text_row, ibeam_letter - row_begin);
  267.             }
  268.         }
  269.     }
  270.  
  271.     if(need_ibeam)
  272.     {
  273.         ibeam_x = text_x;
  274.         ibeam_y = text_y;
  275.     }
  276.  
  277. // Draw solid cursor
  278.     if(!active)
  279.     {
  280.         draw_cursor();
  281.     }
  282.  
  283. // Border
  284.     draw_border();
  285.  
  286.     flash();
  287. }
  288.  
  289. int BC_TextBox::cursor_enter_event()
  290. {
  291.     if(top_level->event_win == win)
  292.     {
  293.         if(!highlighted)
  294.         {
  295.             highlighted = 1;
  296.             draw_border();
  297.             flash();
  298.         }
  299.     }
  300.     return 0;
  301. }
  302.  
  303. int BC_TextBox::cursor_leave_event()
  304. {
  305.     if(highlighted)
  306.     {
  307.         highlighted = 0;
  308.         draw_border();
  309.         flash();
  310.     }
  311.     return 0;
  312. }
  313.  
  314. int BC_TextBox::button_press_event()
  315. {
  316.     int cursor_letter = 0;
  317.     int text_len = strlen(text);
  318.  
  319.     if(top_level->event_win == win)
  320.     {
  321.         if(!active)
  322.         {
  323.             top_level->deactivate();
  324.             activate();
  325.         }
  326.  
  327.         cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
  328.         if(get_double_click())
  329.         {
  330.             word_selected = 1;
  331.             select_word(highlight_letter1, highlight_letter2, cursor_letter);
  332.             highlight_letter3 = highlight_letter1;
  333.             highlight_letter4 = highlight_letter2;
  334.             ibeam_letter = highlight_letter2;
  335.         }
  336.         else
  337.         {
  338.             text_selected = 1;
  339.             highlight_letter3 = highlight_letter4 = 
  340.                 ibeam_letter = highlight_letter1 = 
  341.                 highlight_letter2 = cursor_letter;
  342.         }
  343.         
  344.         if(ibeam_letter < 0) ibeam_letter = 0;
  345.         if(ibeam_letter > text_len) ibeam_letter = text_len;
  346.         draw();
  347.         return 1;
  348.     }
  349.     else
  350.     if(active)
  351.     {
  352.         top_level->deactivate();
  353.     }
  354.  
  355.     return 0;
  356. }
  357.  
  358. int BC_TextBox::button_release_event()
  359. {
  360.     if(active)
  361.     {
  362.         if(text_selected || word_selected)
  363.         {
  364.             text_selected = 0;
  365.             word_selected = 0;
  366.         }
  367.     }
  368.     return 0;
  369. }
  370.  
  371. int BC_TextBox::cursor_motion_event()
  372. {
  373.     int cursor_letter, text_len = strlen(text), letter1, letter2;
  374.     if(active)
  375.     {
  376.         if(text_selected || word_selected)
  377.         {
  378.             cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
  379.             if(word_selected)
  380.             {
  381.                 select_word(letter1, letter2, cursor_letter);
  382.             }
  383.             else
  384.             if(text_selected)
  385.             {
  386.                 letter1 = letter2 = cursor_letter;
  387.             }
  388.  
  389.             if(letter1 <= highlight_letter3)
  390.             {
  391.                 highlight_letter1 = letter1;
  392.                 highlight_letter2 = highlight_letter4;
  393.                 ibeam_letter = letter1;
  394.             }
  395.             else
  396.             if(letter2 >= highlight_letter4)
  397.             {
  398.                 highlight_letter2 = letter2;
  399.                 highlight_letter1 = highlight_letter3;
  400.                 ibeam_letter = letter2;
  401.             }
  402.             
  403.             find_ibeam();
  404.             draw();
  405.             return 1;
  406.         }
  407.     }
  408.     return 0;
  409. }
  410.  
  411. int BC_TextBox::activate()
  412. {
  413.     top_level->active_subwindow = this;
  414.     active = 1;
  415.     draw();
  416.     top_level->set_repeat(top_level->get_resources()->blink_rate);
  417.     return 0;
  418. }
  419.  
  420. int BC_TextBox::deactivate()
  421. {
  422.     active = 0;
  423.     top_level->unset_repeat(top_level->get_resources()->blink_rate);
  424.     draw();
  425.     return 0;
  426. }
  427.  
  428. int BC_TextBox::repeat_event(long duration)
  429. {
  430.     if(duration == top_level->get_resources()->blink_rate && 
  431.         active)
  432.     {
  433.         draw_cursor();
  434.         flash();
  435.         return 1;
  436.     }
  437.     return 0;
  438. }
  439.  
  440. int BC_TextBox::keypress_event()
  441. {
  442. // Result == 2 contents changed
  443. // Result == 1 trapped keypress
  444. // Result == 0 nothing
  445.     int result = 0;
  446.     int text_len;
  447.     int dispatch_event = 0;
  448.  
  449.     if(!active) return 0;
  450.  
  451.     text_len = strlen(text);
  452.     switch(top_level->get_keypress())
  453.     {
  454.         case ESC:
  455.             top_level->deactivate();
  456.             result = 0;
  457.             break;
  458.  
  459.         case RETURN:
  460.             if(rows == 1)
  461.             {
  462.                 top_level->deactivate();
  463.                 dispatch_event = 1;
  464.                 result = 0;
  465.             }
  466.             break;
  467.  
  468.         case TAB:
  469.             top_level->cycle_textboxes(1);
  470.             result = 1;
  471.             break;
  472.  
  473.         case LEFTTAB:
  474.             top_level->cycle_textboxes(-1);
  475.             result = 1;
  476.             break;
  477.  
  478.         case LEFT:
  479.             if(ibeam_letter > 0)
  480.             {
  481. // Extend selection
  482.                 if(top_level->shift_down())
  483.                 {
  484. // Initialize highlighting
  485.                     if(highlight_letter1 == highlight_letter2)
  486.                     {
  487.                         highlight_letter1 = ibeam_letter - 1;
  488.                         highlight_letter2 = ibeam_letter;
  489.                     }
  490.                     else
  491. // Extend left highlight
  492.                     if(highlight_letter1 == ibeam_letter)
  493.                     {
  494.                         highlight_letter1--;
  495.                     }
  496.                     else
  497. // Shrink right highlight
  498.                     if(highlight_letter2 == ibeam_letter)
  499.                     {
  500.                         highlight_letter2--;
  501.                     }
  502.                 }
  503.                 else
  504.                     highlight_letter1 = highlight_letter2;
  505.  
  506.                 ibeam_letter--;
  507.  
  508.                 find_ibeam();
  509.                 draw();
  510.             }
  511.             result = 1;
  512.             break;
  513.  
  514.         case RIGHT:
  515.             if(ibeam_letter < text_len)
  516.             {
  517. // Extend selection
  518.                 if(top_level->shift_down())
  519.                 {
  520. // Initialize highlighting
  521.                     if(highlight_letter1 == highlight_letter2)
  522.                     {
  523.                         highlight_letter1 = ibeam_letter;
  524.                         highlight_letter2 = ibeam_letter + 1;
  525.                     }
  526.                     else
  527. // Shrink left highlight
  528.                     if(highlight_letter1 == ibeam_letter)
  529.                     {
  530.                         highlight_letter1++;
  531.                     }
  532.                     else
  533. // Expand right highlight
  534.                     if(highlight_letter2 == ibeam_letter)
  535.                     {
  536.                         highlight_letter2++;
  537.                     }
  538.                 }
  539.                 else
  540.                     highlight_letter1 = highlight_letter2;
  541.  
  542.                 ibeam_letter++;
  543.  
  544.                 find_ibeam();
  545.                 draw();
  546.             }
  547.             result = 1;
  548.             break;
  549.         
  550.         case END:
  551.             if(top_level->shift_down())
  552.             {
  553.                 if(highlight_letter1 == highlight_letter2)
  554.                 {
  555.                     highlight_letter2 = text_len;
  556.                     highlight_letter1 = ibeam_letter;
  557.                 }
  558.                 else
  559.                 if(highlight_letter1 == ibeam_letter)
  560.                 {
  561.                     highlight_letter1 = highlight_letter2;
  562.                     highlight_letter2 = text_len;
  563.                 }
  564.                 else
  565.                 if(highlight_letter2 == ibeam_letter)
  566.                 {
  567.                     highlight_letter2 = text_len;
  568.                 }
  569.             }
  570.             else
  571.                 highlight_letter1 = highlight_letter2;
  572.  
  573.             ibeam_letter = text_len;
  574.             find_ibeam();
  575.             draw();
  576.             result = 1;
  577.             break;
  578.         
  579.         case HOME:
  580.             if(top_level->shift_down())
  581.             {
  582.                 if(highlight_letter1 == highlight_letter2)
  583.                 {
  584.                     highlight_letter2 = ibeam_letter;
  585.                     highlight_letter1 = 0;
  586.                 }
  587.                 else
  588.                 if(highlight_letter1 == ibeam_letter)
  589.                 {
  590.                     highlight_letter1 = 0;
  591.                 }
  592.                 else
  593.                 if(highlight_letter2 == ibeam_letter)
  594.                 {
  595.                     highlight_letter2 = highlight_letter1;
  596.                     highlight_letter1 = 0;
  597.                 }
  598.             }
  599.             else
  600.                 highlight_letter1 = highlight_letter2;
  601.  
  602.             ibeam_letter = 0;
  603.             find_ibeam();
  604.             draw();
  605.             result = 1;
  606.             break;
  607.  
  608.         case BACKSPACE:
  609.             if(highlight_letter1 == highlight_letter2)
  610.             {
  611.                 if(ibeam_letter > 0)
  612.                 {
  613.                     delete_selection(ibeam_letter - 1, ibeam_letter, text_len);
  614.                     ibeam_letter--;
  615.                 }
  616.             }
  617.             else
  618.             {
  619.                 delete_selection(highlight_letter1, highlight_letter2, text_len);
  620.                 highlight_letter2 = ibeam_letter = highlight_letter1;
  621.             }
  622.  
  623.             find_ibeam();
  624.             draw();
  625.             dispatch_event = 1;
  626.             result = 1;
  627.             break;
  628.  
  629.         case DELETE:
  630.             if(highlight_letter1 == highlight_letter2)
  631.             {
  632.                 if(ibeam_letter < text_len)
  633.                 {
  634.                     delete_selection(ibeam_letter, ibeam_letter + 1, text_len);
  635.                 }
  636.             }
  637.             else
  638.             {
  639.                 delete_selection(highlight_letter1, highlight_letter2, text_len);
  640.                 highlight_letter2 = ibeam_letter = highlight_letter1;
  641.             }
  642.             
  643.             find_ibeam();
  644.             draw();
  645.             dispatch_event = 1;
  646.             result = 1;
  647.             break;
  648.  
  649.         default:
  650.             if((top_level->get_keypress() == NEWLINE) ||
  651.                 (top_level->get_keypress() > 30 && top_level->get_keypress() < 127))
  652.             {
  653.                 temp_string[0] = top_level->get_keypress();
  654.                 temp_string[1] = 0;
  655.                 insert_text(temp_string);
  656.                 find_ibeam();
  657.                 draw();
  658.                 dispatch_event = 1;
  659.                 result = 1;
  660.             }
  661.             break;
  662.     }
  663.  
  664.     if(dispatch_event) handle_event();
  665.     return result;
  666. }
  667.  
  668. int BC_TextBox::uses_text()
  669. {
  670.     return 1;
  671. }
  672.  
  673. void BC_TextBox::delete_selection(int letter1, int letter2, int text_len)
  674. {
  675.     int i, j;
  676.     
  677.     for(i = letter1, j = letter2; j < text_len; i++, j++)
  678.     {
  679.         text[i] = text[j];
  680.     }
  681.     text[i] = 0;
  682. }
  683.  
  684. void BC_TextBox::insert_text(char *string)
  685. {
  686.     int i, j, text_len, string_len;
  687.  
  688.     string_len = strlen(string);
  689.     text_len = strlen(text);
  690.     if(highlight_letter1 < highlight_letter2)
  691.     {
  692.         delete_selection(highlight_letter1, highlight_letter2, text_len);
  693.         highlight_letter2 = ibeam_letter = highlight_letter1;
  694.     }
  695.  
  696.     text_len = strlen(text);
  697.  
  698.     for(i = text_len, j = text_len + string_len; i >= ibeam_letter; i--, j--)
  699.         text[j] = text[i];
  700.  
  701.     for(i = ibeam_letter, j = 0; j < string_len; j++, i++)
  702.         text[i] = string[j];
  703.  
  704.     ibeam_letter += string_len;
  705. }
  706.  
  707. void BC_TextBox::get_ibeam_position(int &x, int &y)
  708. {
  709.     int i, j, k, row_begin, row_end, text_len;
  710.  
  711.     text_len = strlen(text);
  712.     for(i = 0, k = 0; i < text_len; k += text_height)
  713.     {
  714.         row_begin = i;
  715.         for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
  716.         {
  717.             text_row[j] = text[i];
  718.         }
  719.  
  720.         row_end = i;
  721.         text_row[j] = 0;
  722.  
  723.         if(ibeam_letter >= row_begin && ibeam_letter <= row_end)
  724.         {
  725.             x = get_text_width(font, text_row, ibeam_letter - row_begin);
  726.             y = k;
  727.             return;
  728.         }
  729.         if(text[i] == '\n') i++;
  730.     }
  731.  
  732.     x = 0;
  733.     y = 0;
  734.     return;
  735. }
  736.  
  737. void BC_TextBox::find_ibeam()
  738. {
  739.     int x, y;
  740.  
  741.     get_ibeam_position(x, y);
  742.     if(left_margin + text_x + x >= get_w() - right_margin - BCCURSORW)
  743.     {
  744.         text_x = -(x - (get_w() - get_w() / 4)) + left_margin;
  745.         if(text_x > left_margin) text_x = left_margin;
  746.     }
  747.     else
  748.     if(left_margin + text_x + x < left_margin)
  749.     {
  750.         text_x = -(x - (get_w() / 4)) + left_margin;
  751.         if(text_x > left_margin) text_x = left_margin;
  752.     }
  753.  
  754.     if((y >= get_h() - text_height - bottom_margin) || 
  755.         (y < top_margin))
  756.     {
  757.         text_y = -(y - (get_h() / 2)) + top_margin;
  758.         if(text_y > top_margin) text_y = top_margin;
  759.     }
  760. }
  761.  
  762. int BC_TextBox::get_cursor_letter(int cursor_x, int cursor_y)
  763. {
  764.     int i, j, k, l, row_begin, row_end, text_len, result = 0, done = 0;
  765.     text_len = strlen(text);
  766.  
  767.     if(cursor_y >= get_h() - bottom_margin) result = text_len;
  768.  
  769.     for(i = 0, k = text_y; i < text_len && !done; k += text_height)
  770.     {
  771.         row_begin = i;
  772.         for(j = 0; text[i] != '\n' && i < text_len; j++, i++)
  773.         {
  774.             text_row[j] = text[i];
  775.         }
  776.         row_end = i;
  777.         text_row[j] = 0;
  778.  
  779.         if(cursor_y >= k && cursor_y < k + text_height)
  780.         {
  781.             for(j = 0; j <= row_end - row_begin && !done; j++)
  782.             {
  783.                 l = get_text_width(font, text_row, j) + text_x;
  784.                 if(l > cursor_x)
  785.                 {
  786.                     done = 1;
  787.                     result = row_begin + j - 1;
  788.                 }
  789.             }
  790.             if(!done) result = row_end;
  791.         }
  792.         if(text[i] == '\n') i++;
  793.     }
  794.     if(result < 0) result = 0;
  795.     if(result > text_len) result = text_len;
  796.     return result;
  797. }
  798.  
  799. void BC_TextBox::select_word(int &letter1, int &letter2, int ibeam_letter)
  800. {
  801.     int text_len = strlen(text);
  802.     letter1 = letter2 = ibeam_letter;
  803.     do
  804.     {
  805.         if(isalnum(text[letter1])) letter1--;
  806.     }while(letter1 > 0 && isalnum(text[letter1]));
  807.     if(!isalnum(text[letter1])) letter1++;
  808.  
  809.     do
  810.     {
  811.         if(isalnum(text[letter2])) letter2++;
  812.     }while(letter2 < text_len && isalnum(text[letter2]));
  813.     if(letter2 < text_len && text[letter2] == ' ') letter2++;
  814.  
  815.     if(letter1 < 0) letter1 = 0;
  816.     if(letter2 < 0) letter2 = 0;
  817.     if(letter1 > text_len) letter1 = text_len;
  818.     if(letter2 > text_len) letter2 = text_len;
  819. }
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836. BC_PopupTextBoxText::BC_PopupTextBoxText(BC_PopupTextBox *popup, int x, int y)
  837.  : BC_TextBox(x, y, popup->text_w, 1, popup->default_text)
  838. {
  839.     this->popup = popup;
  840. }
  841.  
  842. int BC_PopupTextBoxText::handle_event()
  843. {
  844.     return 1;
  845. }
  846.  
  847. BC_PopupTextBoxList::BC_PopupTextBoxList(BC_PopupTextBox *popup, int x, int y)
  848.  : BC_ListBox(x,
  849.      y,
  850.     popup->text_w,
  851.     popup->list_h,
  852.     LISTBOX_TEXT,
  853.     popup->list_items,
  854.     0,
  855.     0,
  856.     1,
  857.     0,
  858.     1)
  859. {
  860.     this->popup = popup;
  861. }
  862. int BC_PopupTextBoxList::handle_event()
  863. {
  864.     popup->textbox->update(get_selection(0, 0)->get_text());
  865.     popup->handle_event();
  866.     return 1;
  867. }
  868.  
  869.  
  870.  
  871.  
  872. BC_PopupTextBox::BC_PopupTextBox(BC_WindowBase *parent_window, 
  873.         ArrayList<BC_ListBoxItem*> *list_items,
  874.         char *default_text,
  875.         int x, 
  876.         int y, 
  877.         int text_w,
  878.         int list_h)
  879. {
  880.     this->x = x;
  881.     this->y = y;
  882.     this->list_h = list_h;
  883.     this->default_text = default_text;
  884.     this->text_w = text_w;
  885.     this->parent_window = parent_window;
  886.     this->list_items = list_items;
  887. }
  888.  
  889. BC_PopupTextBox::~BC_PopupTextBox()
  890. {
  891.     delete textbox;
  892.     delete listbox;
  893. }
  894.  
  895. int BC_PopupTextBox::create_objects()
  896. {
  897.     int x = this->x, y = this->y;
  898.     parent_window->add_subwindow(textbox = new BC_PopupTextBoxText(this, x, y));
  899.     x += textbox->get_w();
  900.     parent_window->add_subwindow(listbox = new BC_PopupTextBoxList(this, x, y));
  901.     return 0;
  902. }
  903.  
  904. void BC_PopupTextBox::update(char *text)
  905. {
  906.     textbox->update(text);
  907. }
  908.  
  909. char* BC_PopupTextBox::get_text()
  910. {
  911.     return textbox->get_text();
  912. }
  913.  
  914. int BC_PopupTextBox::get_number()
  915. {
  916.     return listbox->get_selection_number(0, 0);
  917. }
  918.  
  919. int BC_PopupTextBox::get_w()
  920. {
  921.     return textbox->get_w() + listbox->get_w();
  922. }
  923.  
  924. int BC_PopupTextBox::get_h()
  925. {
  926.     return textbox->get_h();
  927. }
  928.  
  929. int BC_PopupTextBox::handle_event()
  930. {
  931.     return 1;
  932. }
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939. BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, int x, int y)
  940.  : BC_TextBox(x, y, popup->text_w, 1, popup->default_value)
  941. {
  942.     this->popup = popup;
  943. }
  944.  
  945. int BC_TumbleTextBoxText::handle_event()
  946. {
  947.     return 1;
  948. }
  949.  
  950. BC_TumbleTextBoxTumble::BC_TumbleTextBoxTumble(BC_TumbleTextBox *popup, 
  951.         long min,
  952.         long max,
  953.         int x, 
  954.         int y)
  955.  : BC_ITumbler(popup->textbox, min, max, x, y)
  956. {
  957.     this->popup = popup;
  958. }
  959.  
  960. BC_TumbleTextBox::BC_TumbleTextBox(BC_WindowBase *parent_window, 
  961.         long default_value,
  962.         long min,
  963.         long max,
  964.         int x, 
  965.         int y, 
  966.         int text_w)
  967. {
  968.     this->x = x;
  969.     this->y = y;
  970.     this->min = min;
  971.     this->max = max;
  972.     this->default_value = default_value;
  973.     this->text_w = text_w;
  974.     this->parent_window = parent_window;
  975. }
  976.  
  977. BC_TumbleTextBox::~BC_TumbleTextBox()
  978. {
  979.     delete textbox;
  980.     delete tumbler;
  981. }
  982.  
  983. int BC_TumbleTextBox::create_objects()
  984. {
  985.     int x = this->x, y = this->y;
  986.     parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, x, y));
  987.     x += textbox->get_w();
  988.     parent_window->add_subwindow(tumbler = new BC_TumbleTextBoxTumble(this, min, max, x, y));
  989.     return 0;
  990. }
  991.  
  992. char* BC_TumbleTextBox::get_text()
  993. {
  994.     return textbox->get_text();
  995. }
  996.  
  997. int BC_TumbleTextBox::get_w()
  998. {
  999.     return textbox->get_w() + tumbler->get_w();
  1000. }
  1001.  
  1002. int BC_TumbleTextBox::get_h()
  1003. {
  1004.     return textbox->get_h();
  1005. }
  1006.  
  1007. int BC_TumbleTextBox::handle_event()
  1008. {
  1009.     return 1;
  1010. }
  1011.  
  1012. void BC_TumbleTextBox::set_boundaries(long min, long max)
  1013. {
  1014.     tumbler->set_boundaries(min, max);
  1015. }
  1016.  
  1017.