search fixes, preset fixes, ladspa icon logging, igor pref theme, drag btn rollover
[goodguy/history.git] / cinelerra-5.1 / guicast / bctextbox.C
index a661135240c61909a9f25b09e78973853157f904..506b578da030d88d710bd38ed32432f14bea0a59 100644 (file)
 #include "bcsignals.h"
 #include "bctextbox.h"
 #include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
 #include <ctype.h>
 #include "cursors.h"
 #include "filesystem.h"
 #include "keys.h"
+#include "language.h"
 #include <math.h>
 #include "bctimer.h"
 #include "vframe.h"
@@ -133,6 +134,7 @@ BC_TextBox::~BC_TextBox()
        delete suggestions_popup;
        suggestions->remove_all_objects();
        delete suggestions;
+       delete menu;
        delete [] wtext;
        if( size > 0 )
                delete [] text;
@@ -173,8 +175,11 @@ int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
        keypress_draw = 1;
        last_keypress = 0;
        separators = 0;
+       xscroll = 0;
        yscroll = 0;
+       menu = 0;
        dirty = 1;
+       selection_active = 0;
        return 0;
 }
 
@@ -186,8 +191,9 @@ int BC_TextBox::tstrlen()
 
 int BC_TextBox::tstrcmp(const char *cp)
 {
-       if( !tsize ) return strcmp(text, cp);
-       return strncmp(text, cp, tsize);
+       const char *tp = get_text();
+       if( !tsize ) return strcmp(tp, cp);
+       return strncmp(tp, cp, tsize);
 }
 
 char *BC_TextBox::tstrcpy(const char *cp)
@@ -245,6 +251,7 @@ int BC_TextBox::text_update(const wchar_t *wcp, int wsz, char *tcp, int tsz)
 
 int BC_TextBox::initialize()
 {
+
        if (!skip_cursor)
                skip_cursor = new Timer;
        skip_cursor->update();
@@ -286,6 +293,10 @@ int BC_TextBox::initialize()
        draw(0);
        set_cursor(IBEAM_CURSOR, 0, 0);
        show_window(0);
+
+       add_subwindow(menu = new BC_TextMenu(this));
+       menu->create_objects();
+
        return 0;
 }
 
@@ -503,10 +514,11 @@ void BC_TextBox::enable()
        }
 }
 
-int BC_TextBox::get_enabled()
-{
-       return enabled;
-}
+int BC_TextBox::get_enabled() { return enabled; }
+int BC_TextBox::get_text_x() { return text_x; }
+int BC_TextBox::get_text_y() { return text_y; }
+void BC_TextBox::set_text_x(int v) { text_x = v; }
+void BC_TextBox::set_text_y(int v) { text_y = v; }
 
 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
 {
@@ -671,6 +683,8 @@ void BC_TextBox::draw(int flush)
                            highlight_letter1 <= row_end ) {
                                int color = active && enabled && get_has_focus() ?
                                        resources->text_highlight :
+                                   selection_active ?
+                                       resources->text_selected_highlight :
                                        resources->text_inactive_highlight;
                                if( unicode_active >= 0 )
                                        color ^= LTBLUE;
@@ -695,7 +709,7 @@ void BC_TextBox::draw(int flush)
                        int len = row_end - row_begin;
                        if( len > 0 ) {
                                set_color(enabled ? resources->text_default : DMGREY);
-                               draw_wtext(text_x, k + text_ascent, wtext_row, len, 0);
+                               draw_single_text(1, font, text_x, k + text_ascent, wtext_row, len);
                        }
 
 // Get ibeam location
@@ -774,12 +788,10 @@ int BC_TextBox::button_press_event()
        const int debug = 0;
 
        if(!enabled) return 0;
-       if(get_buttonpress() != WHEEL_UP &&
-               get_buttonpress() != WHEEL_DOWN &&
-               get_buttonpress() != LEFT_BUTTON &&
-               get_buttonpress() != MIDDLE_BUTTON) return 0;
-
-
+//     if(get_buttonpress() != WHEEL_UP &&
+//             get_buttonpress() != WHEEL_DOWN &&
+//             get_buttonpress() != LEFT_BUTTON &&
+//             get_buttonpress() != MIDDLE_BUTTON) return 0;
 
        if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
 
@@ -817,6 +829,11 @@ int BC_TextBox::button_press_event()
                        update_scroll = 1;
                }
                else
+               if(get_buttonpress() == RIGHT_BUTTON)
+               {
+                       menu->activate_menu();
+               }
+               else
                {
 
                cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
@@ -1603,29 +1620,15 @@ int BC_TextBox::keypress_event()
                        if( ctrl_down() ) {
                                switch( get_keypress() ) {
                                case 'c': case 'C': {
-                                       if(highlight_letter1 != highlight_letter2) {
-                                               copy_selection(SECONDARY_SELECTION);
-                                               result = 1;
-                                       }
+                                       result = copy(0);
                                        break; }
                                case 'v': case 'V': {
-                                       paste_selection(SECONDARY_SELECTION);
-                                       find_ibeam(1);
-                                       if(keypress_draw) draw(1);
+                                       result = paste(0);
                                        dispatch_event = 1;
-                                       result = 1;
                                        break; }
                                case 'x': case 'X': {
-                                       if(highlight_letter1 != highlight_letter2) {
-                                               copy_selection(SECONDARY_SELECTION);
-                                               delete_selection(highlight_letter1, highlight_letter2, wtext_len);
-                                               highlight_letter2 = ibeam_letter = highlight_letter1;
-                                       }
-
-                                       find_ibeam(1);
-                                       if(keypress_draw) draw(1);
+                                       result = cut(0);
                                        dispatch_event = 1;
-                                       result = 1;
                                        break; }
                                case 'u': case 'U': {
                                        if( shift_down() ) {
@@ -1656,6 +1659,53 @@ int BC_TextBox::keypress_event()
 }
 
 
+int BC_TextBox::cut(int do_update)
+{
+       if( highlight_letter1 != highlight_letter2 ) {
+               int wtext_len = wtext_update();
+               copy_selection(SECONDARY_SELECTION);
+               delete_selection(highlight_letter1, highlight_letter2, wtext_len);
+               highlight_letter2 = ibeam_letter = highlight_letter1;
+       }
+
+       find_ibeam(1);
+       if( keypress_draw )
+               draw(1);
+       
+       if( do_update ) {
+               skip_cursor->update();
+               handle_event();
+       }
+       return 1;
+}
+
+int BC_TextBox::copy(int do_update)
+{
+       int result = 0;
+       if( highlight_letter1 != highlight_letter2 ) {
+               copy_selection(SECONDARY_SELECTION);
+               result = 1;
+               if( do_update ) {
+                       skip_cursor->update();
+               }
+       }
+       return result;
+}
+
+int BC_TextBox::paste(int do_update)
+{
+       paste_selection(SECONDARY_SELECTION);
+       find_ibeam(1);
+       if( keypress_draw )
+               draw(1);
+       if( do_update ) {
+               skip_cursor->update();
+               handle_event();
+       }
+       return 1;
+}
+
+
 int BC_TextBox::uses_text()
 {
        return 1;
@@ -2005,17 +2055,25 @@ void BC_TextBox::copy_selection(int clipboard_num)
 //printf(" BC_TextBox::copy_selection %d %d %d\n",highlight_letter1, highlight_letter2, clip_len);
        char ctext[4*clip_len+4];
        clip_len = text_update(&wtext[highlight_letter1],clip_len, ctext,4*clip_len+4);
-       get_clipboard()->to_clipboard(ctext, clip_len, clipboard_num);
+       to_clipboard(ctext, clip_len, clipboard_num);
+       selection_active = 1;
 }
 
+int BC_TextBox::selection_clear_event()
+{
+       if( !is_event_win() ) return 0;
+       selection_active = 0;
+       draw(1);
+       return 1;
+}
 
 void BC_TextBox::paste_selection(int clipboard_num)
 {
-       int len = get_clipboard()->clipboard_len(clipboard_num);
+       int len = clipboard_len(clipboard_num);
        if( len > 0 )
        {
                char cstring[len];  wchar_t wstring[len];
-               get_clipboard()->from_clipboard(cstring, len, clipboard_num);  --len;
+               from_clipboard(cstring, len, clipboard_num);  --len;
 //printf("BC_TextBox::paste_selection %d '%*.*s'\n",len,len,len,cstring);
                len = BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
                        cstring,len, (char *)wstring,(len+1)*sizeof(wchar_t)) / sizeof(wchar_t);
@@ -2116,6 +2174,7 @@ BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
        this->y = y;
        this->w = w;
        this->rows = rows;
+       xscroll = 0;  yscroll = 0;
        this->default_text = default_text;
        this->default_wtext = 0;
        this->default_size = default_size;
@@ -2130,6 +2189,7 @@ BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
        this->y = y;
        this->w = w;
        this->rows = rows;
+       xscroll = 0;  yscroll = 0;
        this->default_text = 0;
        this->default_wtext = default_wtext;
        this->default_size = default_size;
@@ -2137,6 +2197,7 @@ BC_ScrollTextBox::BC_ScrollTextBox(BC_WindowBase *parent_window,
 
 BC_ScrollTextBox::~BC_ScrollTextBox()
 {
+       delete xscroll;
        delete yscroll;
        if(text) {
                text->gui = 0;
@@ -2150,44 +2211,32 @@ void BC_ScrollTextBox::create_objects()
        parent_window->add_subwindow(text = default_wtext ?
                new BC_ScrollTextBoxText(this, default_wtext) :
                new BC_ScrollTextBoxText(this, default_text));
-       parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
-       text->yscroll = yscroll;
-       yscroll->bound_to = text;
        set_text_row(0);
 }
 
 void BC_ScrollTextBox::set_text(char *text, int isz)
 {
        this->text->set_text(text, isz);
-       yscroll->update_length(this->text->get_text_rows(),
-               this->text->get_text_row(),
-               yscroll->get_handlelength(),
-               1);
+       update_scrollbars();
 }
 
 int BC_ScrollTextBox::set_text_row(int n)
 {
        text->set_text_row(n);
-       yscroll->update_value(n);
+       update_scrollbars();
        return 1;
 }
 
 void BC_ScrollTextBox::update(const char *text)
 {
        this->text->update(text);
-       yscroll->update_length(this->text->get_text_rows(),
-               this->text->get_text_row(),
-               yscroll->get_handlelength(),
-               1);
+       update_scrollbars();
 }
 
 void BC_ScrollTextBox::update(const wchar_t *wtext)
 {
        this->text->update(wtext);
-       yscroll->update_length(this->text->get_text_rows(),
-               this->text->get_text_row(),
-               yscroll->get_handlelength(),
-               1);
+       update_scrollbars();
 }
 
 void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
@@ -2196,19 +2245,7 @@ void BC_ScrollTextBox::reposition_window(int x, int y, int w, int rows)
        this->y = y;
        this->w = w;
        this->rows = rows;
-
-       text->reposition_window(x,
-               y,
-               w - yscroll->get_span(),
-               rows);
-       yscroll->reposition_window(x + w - yscroll->get_span(),
-               y,
-               BC_TextBox::calculate_row_h(rows,
-                       parent_window));
-       yscroll->update_length(text->get_text_rows(),
-               text->get_text_row(),
-               rows,
-               0);
+       update_scrollbars();
 }
 
 int BC_ScrollTextBox::button_press_event()
@@ -2240,6 +2277,15 @@ int BC_ScrollTextBox::get_ibeam_letter()
 {
        return text->get_ibeam_letter();
 }
+int BC_ScrollTextBox::get_x_pos()
+{
+       return text->left_margin - text->get_text_x();
+}
+void BC_ScrollTextBox::set_x_pos(int x)
+{
+       text->set_text_x(text->left_margin - x);
+       text->draw(1);
+}
 
 BC_ScrollTextBoxText::BC_ScrollTextBoxText(BC_ScrollTextBox *gui, const char *text)
  : BC_TextBox(gui->x, gui->y,
@@ -2266,35 +2312,111 @@ BC_ScrollTextBoxText::~BC_ScrollTextBoxText()
        }
 }
 
+void BC_ScrollTextBox::update_scrollbars()
+{
+       int view_w = w, view_rows = rows;
+       int view_h = BC_TextBox::calculate_row_h(view_rows, parent_window);
+       int text_rows = text->get_text_rows();
+       int text_width = parent_window->get_text_width(text->font, text->get_wtext());
+       BC_Resources *resources = parent_window->get_resources();
+       int need_xscroll = 0, need_yscroll = 0;
+
+// Create scrollbars as needed
+       int resize = 1;
+       while( resize ) {
+               resize = 0;
+               if( !need_xscroll && (text->get_text_x() != text->left_margin ||
+                     text_width >= view_w - text->left_margin - text->right_margin) ) {
+                       resize = need_xscroll = 1;
+                       view_h -= resources->hscroll_data[SCROLL_HANDLE_UP]->get_h();
+                       view_rows = BC_TextBox::pixels_to_rows(parent_window, text->font, view_h);
+               }
+               if( !need_yscroll && (text->get_text_y() != text->top_margin ||
+                     text_rows > view_rows) ) {
+                       resize = need_yscroll = 1;
+                       view_w -= resources->vscroll_data[SCROLL_HANDLE_UP]->get_w();
+               }
+       }
+
+       if( !need_xscroll && xscroll ) {
+               text->yscroll = 0;
+               delete xscroll;  xscroll = 0;
+       }
+       if( !need_yscroll && yscroll ) {
+               text->yscroll = 0;
+               delete yscroll;  yscroll = 0;
+       }
+
+       if( view_rows != text->get_rows() || view_w != text->get_w() ) {
+               text->reposition_window(x, y, view_w, view_rows);
+       }
+       if( need_xscroll && !xscroll ) {
+               xscroll = new BC_ScrollTextBoxXScroll(this);
+               parent_window->add_subwindow(xscroll);
+               text->xscroll = xscroll;
+               xscroll->bound_to = text;
+               xscroll->show_window();
+       }
+       if( need_yscroll && !yscroll ) {
+               yscroll = new BC_ScrollTextBoxYScroll(this);
+               parent_window->add_subwindow(yscroll);
+               text->yscroll = yscroll;
+               yscroll->bound_to = text;
+               yscroll->show_window();
+       }
+       if( xscroll ) {
+               xscroll->reposition_window(x, y + text->get_h(), view_w);
+               int xpos = get_x_pos();
+               if( xpos != xscroll->get_value() )
+                       xscroll->update_value(xpos);
+               if( text_width != xscroll->get_length() ||
+                   view_w != xscroll->get_handlelength() )
+                       xscroll->update_length(text_width, xpos, view_w, 0);
+       }
+       if( yscroll ) {
+               yscroll->reposition_window(x + w - yscroll->get_span(), y, text->get_h());
+               int text_row = text->get_text_row();
+               if( text_row != yscroll->get_value() )
+                       yscroll->update_value(text_row);
+               if( text_rows != yscroll->get_length() ||
+                   view_rows != yscroll->get_handlelength() )
+                       yscroll->update_length(text_rows, text_row, view_rows, 0);
+       }
+}
+
 int BC_ScrollTextBoxText::handle_event()
 {
-       gui->yscroll->update_length(get_text_rows(),
-               get_text_row(),
-               gui->yscroll->get_handlelength(),
-               1);
+       gui->update_scrollbars();
        return gui->handle_event();
 }
 
 int BC_ScrollTextBoxText::motion_event()
 {
-       gui->yscroll->update_length(get_text_rows(),
-               get_text_row(),
-               gui->yscroll->get_handlelength(),
-               1);
+       gui->update_scrollbars();
+       return 1;
+}
+
+BC_ScrollTextBoxXScroll::BC_ScrollTextBoxXScroll(BC_ScrollTextBox *gui)
+ : BC_ScrollBar(gui->x, gui->y + gui->text->get_h(), SCROLL_HORIZ + SCROLL_STRETCH,
+       gui->text->get_w(), gui->text->get_text_width(MEDIUMFONT, gui->get_wtext()),
+       0, gui->w)
+{
+       this->gui = gui;
+}
+
+BC_ScrollTextBoxXScroll::~BC_ScrollTextBoxXScroll()
+{
+}
+
+int BC_ScrollTextBoxXScroll::handle_event()
+{
+       gui->set_x_pos(get_position());
        return 1;
 }
 
 BC_ScrollTextBoxYScroll::BC_ScrollTextBoxYScroll(BC_ScrollTextBox *gui)
- : BC_ScrollBar(gui->x +
-                       gui->w -
-                       get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
-               gui->y,
-               SCROLL_VERT,
-               BC_TextBox::calculate_row_h(gui->rows,
-                       gui->parent_window),
-               gui->text->get_text_rows(),
-               0,
-               gui->rows)
+ : BC_ScrollBar(gui->x + gui->text->get_w(), gui->y, SCROLL_VERT,
+       gui->text->get_h(), gui->text->get_text_rows(), 0, gui->rows)
 {
        this->gui = gui;
 }
@@ -2495,8 +2617,8 @@ BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
 }
 
 BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup,
-       float default_value, int x, int y)
- : BC_TextBox(x, y, popup->text_w, 1, default_value)
+       float default_value, int x, int y, int precision)
+ : BC_TextBox(x, y, popup->text_w, 1, default_value, 1, MEDIUMFONT, precision)
 {
        this->popup = popup;
 }
@@ -2521,19 +2643,10 @@ int BC_TumbleTextBoxText::handle_event()
 
 int BC_TumbleTextBoxText::button_press_event()
 {
-       if(is_event_win())
-       {
-               if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
-
-               if(get_buttonpress() == 4)
-               {
-                       popup->tumbler->handle_up_event();
-               }
-               else
-               if(get_buttonpress() == 5)
-               {
-                       popup->tumbler->handle_down_event();
-               }
+       if( get_enabled() && is_event_win() ) {
+               if( get_buttonpress() < 4 ) return BC_TextBox::button_press_event();
+               if( get_buttonpress() == 4 )      popup->tumbler->handle_up_event();
+               else if( get_buttonpress() == 5 ) popup->tumbler->handle_down_event();
                return 1;
        }
        return 0;
@@ -2648,31 +2761,17 @@ int BC_TumbleTextBox::create_objects()
 {
        int x = this->x, y = this->y;
 
-       if(use_float)
-       {
-               parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
-                       default_value_f, x, y));
-               textbox->set_precision(precision);
-       }
-       else
-               parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this,
-                       default_value, x, y));
+       textbox = use_float ?
+               new BC_TumbleTextBoxText(this, default_value_f, x, y, precision) :
+               new BC_TumbleTextBoxText(this, default_value, x, y);
 
+       parent_window->add_subwindow(textbox);
        x += textbox->get_w();
 
-       if(use_float)
-               parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox,
-                       min_f,
-                       max_f,
-                       x,
-                       y));
-       else
-               parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox,
-                       min,
-                       max,
-                       x,
-                       y));
-
+       tumbler = use_float ?
+               (BC_Tumbler *)new BC_FTumbler(textbox, min_f, max_f, x, y) :
+               (BC_Tumbler *)new BC_ITumbler(textbox, min, max, x, y);
+       parent_window->add_subwindow(tumbler);
        tumbler->set_increment(increment);
        return 0;
 }
@@ -2789,6 +2888,66 @@ void BC_TumbleTextBox::set_boundaries(float min, float max)
        tumbler->set_boundaries(min, max);
 }
 
+
+
+BC_TextMenu::BC_TextMenu(BC_TextBox *textbox)
+ : BC_PopupMenu(0, 0, 0, "", 0)
+{
+       this->textbox = textbox;
+}
+
+BC_TextMenu::~BC_TextMenu()
+{
+}
+
+void BC_TextMenu::create_objects()
+{
+       add_item(new BC_TextMenuCut(this));
+       add_item(new BC_TextMenuCopy(this));
+       add_item(new BC_TextMenuPaste(this));
+}
+
+
+BC_TextMenuCut::BC_TextMenuCut(BC_TextMenu *menu) 
+ : BC_MenuItem(_("Cut"))
+{
+       this->menu = menu;
+}
+
+int BC_TextMenuCut::handle_event()
+{
+       menu->textbox->cut(1);
+       
+       return 0;
+}
+
+
+BC_TextMenuCopy::BC_TextMenuCopy(BC_TextMenu *menu) 
+ : BC_MenuItem(_("Copy"))
+{
+       this->menu = menu;
+}
+
+int BC_TextMenuCopy::handle_event()
+{
+       menu->textbox->copy(1);
+       return 0;
+}
+
+
+BC_TextMenuPaste::BC_TextMenuPaste(BC_TextMenu *menu) 
+ : BC_MenuItem(_("Paste"))
+{
+       this->menu = menu;
+}
+
+int BC_TextMenuPaste::handle_event()
+{
+       menu->textbox->paste(1);
+       return 0;
+}
+
+
 void BC_TumbleTextBox::set_tooltip(const char *text)
 {
        textbox->set_tooltip(text);