olaf neophyte and de.po updates, valgrind tweaks, delete green lady, inkscape dpi=96
[goodguy/history.git] / cinelerra-5.1 / guicast / bctextbox.C
index 506b578da030d88d710bd38ed32432f14bea0a59..a7c8f5f7570ff1ce45d55bb65aaf1fded2da3007 100644 (file)
@@ -51,9 +51,9 @@ BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
        is_utf8 = 1;
        skip_cursor = 0;
        reset_parameters(rows, has_border, font, size);
-       if( size > 0 )
+       if( size >= 0 )
                tstrcpy(text);
-       else    // text referenced directly
+       else    // reference shared directly
                this->text = text;
 }
 
@@ -63,12 +63,9 @@ BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
 {
        is_utf8 = 1;
        skip_cursor = 0;
-       wsize = size > 0 ? size : wcslen(wtext);
-       if( size <= 0 ) size = 2*wsize;
        reset_parameters(rows, has_border, font, size);
-       this->wtext = new wchar_t[wsize+1];
+       wdemand(wcslen(wtext));
        wcsncpy(this->wtext, wtext, wsize);
-       this->wtext[wsize] = 0;
 }
 
 BC_TextBox::BC_TextBox(int x, int y, int w, int rows,
@@ -136,7 +133,7 @@ BC_TextBox::~BC_TextBox()
        delete suggestions;
        delete menu;
        delete [] wtext;
-       if( size > 0 )
+       if( size >= 0 )
                delete [] text;
 }
 
@@ -149,9 +146,11 @@ int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
        this->rows = rows;
        this->has_border = has_border;
        this->font = font;
+// size > 0: fixed buffer, size == 0: dynamic buffer
+// size < 0: fixed shared buffer via set_text
        this->size = size;
        this->tsize = size >= 0 ? size : -size;
-       this->text = size > 0 ? new char[size+1] : 0;
+       this->text = size > 0 ? new char[this->tsize+1] : 0;
        if( this->text ) this->text[0] = 0;
        text_start = 0;
        text_end = 0;
@@ -166,6 +165,8 @@ int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
        text_x = 0;
        enabled = 1;
        highlighted = 0;
+       back_color = -1;
+       high_color = -1;
        precision = 4;
        if (!skip_cursor)
                skip_cursor = new Timer;
@@ -185,14 +186,12 @@ int BC_TextBox::reset_parameters(int rows, int has_border, int font, int size)
 
 int BC_TextBox::tstrlen()
 {
-       if( !tsize ) return strlen(text);
-       return strnlen(text, tsize);
+       return !text ? 0 : strnlen(text, tsize);
 }
 
 int BC_TextBox::tstrcmp(const char *cp)
 {
        const char *tp = get_text();
-       if( !tsize ) return strcmp(tp, cp);
        return strncmp(tp, cp, tsize);
 }
 
@@ -200,12 +199,10 @@ char *BC_TextBox::tstrcpy(const char *cp)
 {
        dirty = 1;
        if( cp ) {
-               if( !tsize )
-                       return strcpy(text, cp);
+               if( !size ) tdemand(strlen(cp));
                strncpy(text, cp, tsize);
-               text[tsize-1] = 0;
        }
-       else
+       else if( text )
                text[0] = 0;
        return text;
 }
@@ -213,9 +210,8 @@ char *BC_TextBox::tstrcpy(const char *cp)
 char *BC_TextBox::tstrcat(const char *cp)
 {
        dirty = 1;
-       if( !tsize ) return strcat(text, cp);
+       if( !size ) tdemand(tstrlen() + strlen(cp));
        char *result = strncat(text, cp, tsize);
-       text[tsize-1] = 0;
        return result;
 }
 
@@ -224,13 +220,10 @@ int BC_TextBox::wtext_update()
        if( dirty ) {
                const char *src_enc = is_utf8 ? "UTF8" : BC_Resources::encoding;
                const char *dst_enc = BC_Resources::wide_encoding;
-               int nsize = tsize > 0 ? tsize : strlen(text) + BCTEXTLEN;
-               if( nsize > wsize || !wtext ) {
-                       wchar_t *ntext = new wchar_t[nsize+1];
-                       memcpy(ntext, wtext, wsize*sizeof(wtext[0]));
-                       delete [] wtext;  wtext = ntext;  wsize = nsize;
-               }
-               wlen = BC_Resources::encode(src_enc, dst_enc, text, strlen(text),
+               int tlen = tstrlen();
+               int nsize = tsize > 0 ? tsize : tlen + BCTEXTLEN;
+               wdemand(nsize);
+               wlen = BC_Resources::encode(src_enc, dst_enc, text, tlen,
                        (char*)wtext, wsize*sizeof(wchar_t)) / sizeof(wchar_t);
                dirty = 0;
        }
@@ -281,13 +274,13 @@ int BC_TextBox::initialize()
        BC_Resources *resources = get_resources();
        if(has_border)
        {
-               back_color = resources->text_background;
-               high_color = resources->text_background_hi;
+               if( back_color < 0 ) back_color = resources->text_background;
+               if( high_color < 0 ) high_color = resources->text_background_hi;
        }
        else
        {
-               high_color = resources->text_background_noborder_hi;
-               back_color = bg_color;
+               if( back_color < 0 ) back_color = bg_color;
+               if( high_color < 0 ) high_color = resources->text_background_noborder_hi;
        }
 
        draw(0);
@@ -402,9 +395,9 @@ void BC_TextBox::set_suggestions(ArrayList<char*> *suggestions, int column)
 // Show the highlighted text
                if( suggestions->size() == 1 ) {
                        highlight_letter1 = wtext_update();
-                       text_update(wtext,wlen, text,tsize);
+                       int len = text_update(wtext,wlen, text,tsize);
                        char *current_suggestion = suggestions->get(0);
-                       int col = highlight_letter1 - suggestion_column;
+                       int col = len - suggestion_column;
                        if( col < 0 ) col = 0;
                        char *cur = current_suggestion + col;
                        tstrcat(cur);
@@ -456,7 +449,8 @@ int BC_TextBox::update(const char *text)
 {
 //printf("BC_TextBox::update 1 %d %s %s\n", tstrcmp(text), text, this->text);
 // Don't update if contents are the same
-       if(!tstrcmp(text)) return 0;
+       int bg_color = has_border || !highlighted ? back_color : high_color;
+       if( bg_color == background_color && !tstrcmp(text)) return 0;
        tstrcpy(text);
        int wtext_len = wtext_update();
        if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
@@ -469,9 +463,9 @@ int BC_TextBox::update(const char *text)
 int BC_TextBox::update(const wchar_t *wtext)
 {
        int wtext_len = wcslen(wtext);
-       if( wtext_len >= wsize ) wtext_len = wsize;
-       wcsncpy(this->wtext, wtext, wtext_len);
-       wlen = wtext_len;
+       wdemand(wtext_len);
+       wcsncpy(this->wtext, wtext, wsize);
+       this->wlen = wtext_len;
        if(highlight_letter1 > wtext_len) highlight_letter1 = wtext_len;
        if(highlight_letter2 > wtext_len) highlight_letter2 = wtext_len;
        if(ibeam_letter > wtext_len) ibeam_letter = wtext_len;
@@ -519,6 +513,8 @@ 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::get_back_color() { return back_color; }
+void BC_TextBox::set_back_color(int v) { back_color = v; }
 
 int BC_TextBox::pixels_to_rows(BC_WindowBase *window, int font, int pixels)
 {
@@ -553,13 +549,14 @@ const wchar_t* BC_TextBox::get_wtext()
 
 void BC_TextBox::set_text(char *text, int isz)
 {
-       if( size > 0 || isz < 0 ) return;
-       this->text = text;
-       tsize = isz;
-       size = -isz;
-       dirty = 1;
-       wtext_update();
-       draw(1);
+       if( size < 0 && isz > 0 ) {
+               this->text = text;
+               tsize = isz;
+               size = -isz;
+               dirty = 1;
+               wtext_update();
+               draw(1);
+       }
 }
 
 int BC_TextBox::get_text_rows()
@@ -647,7 +644,7 @@ void BC_TextBox::draw_cursor()
 
 void BC_TextBox::draw(int flush)
 {
-       int i, j, k;
+       int i, k;
        int row_begin, row_end;
        int highlight_x1, highlight_x2;
        int need_ibeam = 1;
@@ -655,12 +652,7 @@ void BC_TextBox::draw(int flush)
 
 //printf("BC_TextBox::draw %d %s\n", __LINE__, text);
 // Background
-       if(has_border)
-               background_color = resources->text_background;
-       else if(highlighted)
-               background_color = high_color;
-       else
-               background_color = back_color;
+       background_color = has_border || !highlighted ? back_color : high_color;
        set_color(background_color);
        draw_box(0, 0, w, h);
 
@@ -669,11 +661,11 @@ void BC_TextBox::draw(int flush)
 // Draw text with selection
        set_font(font);
 
-       for(i=0, j=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
+       for(i=0, k=text_y; i < wtext_len && k < get_h(); k += text_height) {
 // Draw row of text
                row_begin = i;
                wchar_t *wtext_row = &wtext[i];
-               for(j=0; j<BCTEXTLEN-1 && i<wtext_len && wtext[i]!='\n'; ++i, ++j);
+               for( ; i<wtext_len && wtext[i]!='\n'; ++i );
                if( (row_end=i) < wtext_len ) ++i;
 
                if(k > top_margin-text_height && k < get_h()-bottom_margin) {
@@ -1128,15 +1120,28 @@ int BC_TextBox::repeat_event(int64_t duration)
 void BC_TextBox::default_keypress(int &dispatch_event, int &result)
 {
        int key = top_level->get_keypress(), len;
-       if( (key == RETURN) || ( key >= 32 && key <= 255 ) ) {
-               wchar_t *wkeys = top_level->get_wkeystring(&len);
-               if( key == RETURN ) { wkeys[0] = '\n';  wkeys[1] = 0;  len = 1; }
-               insert_text(wkeys, len);
-               find_ibeam(1);
-               draw(1);
-               dispatch_event = 1;
-               result = 1;
-       }
+       wchar_t *wkeys = top_level->get_wkeystring(&len);
+       switch( key ) {
+       case KPENTER:   key = '\n';     goto kpchr;
+       case KPMINUS:   key = '-';      goto kpchr;
+       case KPPLUS:    key = '+';      goto kpchr;
+       case KPDEL:     key = '.';      goto kpchr;
+       case RETURN:    key = '\n';     goto kpchr;
+       case KPINS:     key = '0';      goto kpchr;
+       case KP1: case KP2: case KP3: case KP4: case KP5:
+       case KP6: case KP7: case KP8: case KP9:
+               key = key - KP1 + '1';
+       kpchr: {
+               wkeys[0] = key;  wkeys[1] = 0;  len = 1;
+               break; }
+       default:
+               if( key < 32 || key > 255 ) return;
+       }
+       insert_text(wkeys, len);
+       find_ibeam(1);
+       draw(1);
+       dispatch_event = 1;
+       result = 1;
 }
 
 int BC_TextBox::keypress_event()
@@ -1185,6 +1190,10 @@ int BC_TextBox::keypress_event()
                        result = 1;
                        wlen = 0;
                        break; }
+               case KPINS: last_keypress = KP1-'1'+'0'; // fall thru
+               case KP1: case KP2: case KP3: case KP4: case KP5:
+               case KP6: case KP7: case KP8: case KP9:
+                       last_keypress = last_keypress-KP1 + '1';
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
@@ -1618,7 +1627,7 @@ int BC_TextBox::keypress_event()
 
                default: {
                        if( ctrl_down() ) {
-                               switch( get_keypress() ) {
+                               switch( last_keypress ) {
                                case 'c': case 'C': {
                                        result = copy(0);
                                        break; }
@@ -1724,10 +1733,34 @@ void BC_TextBox::delete_selection(int letter1, int letter2, int wtext_len)
        do_separators(1);
 }
 
+int BC_TextBox::wdemand(int len)
+{
+       if( wtext && wsize >= len ) return 0;
+       int nsize = len + wlen/2 + BCTEXTLEN;
+       wchar_t *ntext = new wchar_t[nsize+1];
+       ntext[nsize] = 0;
+       memcpy(ntext, wtext, wsize*sizeof(wtext[0]));
+       delete [] wtext;  wtext = ntext;  wsize = nsize;
+       return 1;
+}
+
+int BC_TextBox::tdemand(int len)
+{
+       if( text && tsize >= len ) return 0;
+       int tlen = !text ? 0 : strlen(text);
+       int nsize = len + tlen/2 + BCTEXTLEN;
+       char *ntext = new char[nsize+1];
+       ntext[nsize] = 0;
+       memcpy(ntext, text, tsize*sizeof(text[0]));
+       delete [] text;  text = ntext;  tsize = nsize;
+       return 1;
+}
+
 void BC_TextBox::insert_text(const wchar_t *wcp, int len)
 {
        if( len < 0 ) len = wcslen(wcp);
        int wtext_len = wtext_update();
+       wdemand(wtext_len + len + 1);
        if( unicode_active < 0 && highlight_letter1 < highlight_letter2 ) {
                delete_selection(highlight_letter1, highlight_letter2, wtext_len);
                highlight_letter2 = ibeam_letter = highlight_letter1;
@@ -1735,15 +1768,11 @@ void BC_TextBox::insert_text(const wchar_t *wcp, int len)
        }
 
        int i, j;
-       for(i=wtext_len-1, j=wtext_len+len-1; i>=ibeam_letter; i--, j--) {
-               if( j >= wsize ) continue;
-               wtext[j] = wtext[i];
-       }
+       for( i=wtext_len, j=wtext_len+len; --i>=ibeam_letter; )
+               if( --j < wsize ) wtext[j] = wtext[i];
+       for( i=ibeam_letter,j=0; j<len; ++i, ++j )
+               if( i < wsize ) wtext[i] = wcp[j];
 
-       for(i = ibeam_letter, j = 0; j < len; j++, i++) {
-               if( i >= wsize ) break;
-               wtext[i] = wcp[j];
-       }
        if( (wlen+=len) > wsize ) wlen = wsize;
        if( (ibeam_letter+=len) > wsize ) ibeam_letter = wsize;
        wtext[wlen] = 0;  // wtext allocated wsize+1
@@ -2078,6 +2107,7 @@ void BC_TextBox::paste_selection(int clipboard_num)
                len = BC_Resources::encode(BC_Resources::encoding, BC_Resources::wide_encoding,
                        cstring,len, (char *)wstring,(len+1)*sizeof(wchar_t)) / sizeof(wchar_t);
                insert_text(wstring, len);
+               last_keypress = 0;
        }
 }