alt transport keys, snap editing, grab focus, inv hilight clr, subtitle fix
[goodguy/history.git] / cinelerra-5.1 / cinelerra / swindow.C
index 65799c4bba5ac82c55fc71ee4588c1535ed16dda..fd173764f8eab5d61e4d4218c986e0a3af099422 100644 (file)
@@ -5,6 +5,7 @@
 #include "cstrdup.h"
 #include "edl.h"
 #include "filesystem.h"
+#include "language.h"
 #include "localsession.h"
 #include "mainerror.h"
 #include "mainmenu.h"
@@ -75,27 +76,15 @@ SWindowLoadPath::SWindowLoadPath(SWindowGUI *gui, int x, int y, char *path)
  : BC_TextBox(x, y, 200, 1, path)
 {
        this->sw_gui = gui;
-
-       file_entries = new ArrayList<BC_ListBoxItem*>;
-       FileSystem fs;  char string[BCTEXTLEN];
-// Load current directory
-       fs.update(getcwd(string, BCTEXTLEN));
-       int total_files = fs.total_files();
-       for(int i = 0; i < total_files; i++) {
-               const char *name = fs.get_entry(i)->get_name();
-               file_entries->append(new BC_ListBoxItem(name));
-       }
 }
 
 SWindowLoadPath::~SWindowLoadPath()
 {
-       file_entries->remove_all_objects();
-       delete file_entries;
 }
 
 int SWindowLoadPath::handle_event()
 {
-       calculate_suggestions(file_entries);
+       calculate_suggestions();
        strcpy(sw_gui->script_path, get_text());
        return 1;
 }
@@ -113,9 +102,14 @@ SWindowLoadFile::~SWindowLoadFile()
 
 int SWindowLoadFile::handle_event()
 {
-       sw_gui->load_path->set_suggestions(0,0);
-       sw_gui->load_script();
-       sw_gui->set_script_pos(0);
+       if( sw_gui->script_path[0] ) {
+               sw_gui->load_path->set_suggestions(0,0);
+               sw_gui->load_script();
+               sw_gui->set_script_pos(0);
+       }
+       else {
+               eprintf(_("script text file path required"));
+       }
        return 1;
 }
 
@@ -131,7 +125,12 @@ SWindowSaveFile::~SWindowSaveFile()
 
 int SWindowSaveFile::handle_event()
 {
-       sw_gui->save_spumux_data();
+       if( sw_gui->script_path[0] ) {
+               sw_gui->save_spumux_data();
+       }
+       else {
+               eprintf(_("script microdvd file path required"));
+       }
        return 1;
 }
 
@@ -182,12 +181,17 @@ void SWindowGUI::create_objects()
        x1 = x + pad;
        blank_line = new char[2];
        blank_line[0] = ' ';  blank_line[1] = 0;
-       int rows = (ok_y - y - 4*pad) / text_rowsz - 3;
-       int w1 = get_w()-x1-pad;
+       add_subwindow(script_title = new BC_Title(x1, y, _("Script Text:")));
+       y += script_title->get_h() + pad;
+       int rows = (ok_y - y - BC_Title::calculate_h(this,_("Line Text:")) -
+               4*pad) / text_rowsz - 4;
+       int w1 = get_w() - x1 - pad;
        script_entry = new ScriptEntry(this, x1, y, w1, rows, blank_line);
        script_entry->create_objects();
        y += script_entry->get_h() + pad;
-       line_entry = new ScriptEntry(this, x1, y, w1, 3);
+       add_subwindow(line_title = new BC_Title(x1, y, _("Line Text:")));
+       y += line_title->get_h() + pad;
+       line_entry = new ScriptEntry(this, x1, y, w1, 4);
        line_entry->create_objects();
        ok = new SWindowOK(this, ok_x, ok_y);
        add_subwindow(ok);
@@ -197,19 +201,36 @@ void SWindowGUI::create_objects()
 
 void SWindowGUI::load()
 {
+       const char *script_text =
+       _("Adding Subtitles: quick \"How To\" (= or * indicates comment)\n"
+       "*2345678901234567890123456789012345678901234567890123456789\n"
+       "For regular DVD subtitles, put script in a text file. "
+       "Lines can be any length but they will be broken up "
+       "to fit according to some criteria below.\n"
+       "Running text used as script lines will be broken into multilple lines.\n"
+       "The target line length is 60 characters.\n"
+       "Punctuation may be flagged to create an early line break.\n"
+       "Single carriage return ends an individual script line.\n"
+       "Double carriage return indicates the end of an entry.\n"
+       "Whitespace at beginning or end of line is removed.\n"
+       "You can edit the active line in the Line Text box.\n"
+       "\n"
+       "== A new entry is here for illustration purposes.\n"
+       "*  Entry 2\n"
+       "This is the second entry.\n");
+
        if( script_path[0] && !access(script_path,R_OK) ) {
                load_script();
-               int text_no = script_text_no;
-               script_text_no = -1;
-               load_selection(script_entry_no, text_no);
        }
        else {
-               script.remove_all_objects();
                script_path[0] = 0;
                load_path->update(script_path);
-               script_entry_no = 0;
-               script_text_no = 0;
+               FILE *fp = fmemopen((void *)script_text, strlen(script_text), "r");
+               load_script(fp);
        }
+       int text_no = script_text_no;
+       script_text_no = -1;
+       load_selection(script_entry_no, text_no);
 }
 
 SWindowGUI::SWindowGUI(SWindow *swindow, int x, int y, int w, int h)
@@ -297,11 +318,15 @@ int SWindowGUI::resize_event(int w, int h)
        int w1 = w - x1 - pad;
        script_scroll->reposition_window(x1, y, w1);
        y += hh + 2*pad;
+       script_title->reposition_window(x, y);
+       y += script_title->get_h() + pad;
        w1 = w - x - pad;
-       int rows = (ok_y - y - 4*pad) / text_rowsz - 3;
+       int rows = (ok_y - y - line_title->get_h() - 4*pad) / text_rowsz - 4;
        script_entry->reposition_window(x, y, w1, rows);
-       y += script_entry->get_h() + pad;
-       line_entry->reposition_window(x, y, w1, 3);
+       y += script_entry->get_h() + 2*pad;
+       line_title->reposition_window(x, y);
+       y += line_title->get_h() + pad;
+       line_entry->reposition_window(x, y, w1, 4);
        return 0;
 }
 
@@ -331,6 +356,7 @@ void SWindowGUI::set_script_pos(int64_t entry_no, int text_no)
 
 int SWindowGUI::load_selection(int pos, int row)
 {
+       if( pos < 0 || pos >= script.size() ) return 1;
        ScriptLines *texts = script[pos];
        char *rp = texts->get_text_row(row);
        if( !rp || *rp == '=' || *rp == '*' || *rp=='\n' ) return 1;
@@ -342,8 +368,9 @@ int SWindowGUI::load_selection(int pos, int row)
                script_entry->set_text_row(0);
        }
        script_text_no = row;
-       char line[BCTEXTLEN], *bp = line, *cp = rp;
-       while( *cp && *cp!='\n' ) *bp++ = *cp++;
+       char line[BCTEXTLEN], *bp = line;
+       char *ep = bp+sizeof(line)-1, *cp = rp;
+       while( bp < ep && *cp && *cp!='\n' ) *bp++ = *cp++;
        *bp = 0;  bp = texts->text;
        int char1 = rp-bp, char2 = cp-bp;
        script_entry->set_selection(char1, char2, char2);
@@ -602,15 +629,15 @@ int ScriptLines::break_lines()
                        memmove(cp,sp,dp+1-sp);
                        used -= n;  dp -= n;  ep -= n;
                }
-               // constrain line_limit
-               if( (n=(ep-cp)/2) < limit2 || n > line_limit )
+               // target about half remaining line, constrain line_limit
+               if( (n=(ep-1-cp)/2) < limit2 || n > line_limit )
                        n = line_limit;
-               // search for last punct, last space
+               // search for last punct, last space before line_limit
                for( bp=cp, pp=sp=0; --n>=0 && cp<ep; ++cp ) {
                        if( ispunct(*cp) && isspace(*(cp+1)) ) pp = cp;
                        else if( isspace(*cp) ) sp = cp;
                }
-               // long enough to break
+               // line not empty
                if( cp < ep ) {
                        // first, after punctuation
                        if( pp && pp-bp >= limit4 )
@@ -651,7 +678,7 @@ char *ScriptLines::get_text_row(int n)
 }
 
 ScriptScroll::ScriptScroll(SWindowGUI *gui, int x, int y, int w)
- : BC_ScrollBar(x, y, SCROLL_HORIZ, w, 0, 0, 0)
+ : BC_ScrollBar(x, y, SCROLL_HORIZ + SCROLL_STRETCH, w, 0, 0, 0)
 {
        this->sw_gui = gui;
 }
@@ -709,11 +736,26 @@ ScriptEntry::~ScriptEntry()
 void ScriptEntry::set_text(char *text, int isz)
 {
        if( !text || !*text ) return;
-       if( isz < 0 ) isz = strlen(text);
+       if( isz < 0 ) isz = strlen(text)+1;
        BC_ScrollTextBox::set_text(text, isz);
        ttext = text;
 }
 
+int ScriptEntry::handle_event()
+{
+       if( sw_gui->get_button_down() &&
+           sw_gui->get_buttonpress() == 1 &&
+           sw_gui->get_triple_click() ) {
+               int ibeam = get_ibeam_letter(), row = 0;
+               const char *tp = ttext;
+               while( *tp && tp-ttext < ibeam ) {
+                       if( *tp++ == '\n' ) ++row;
+               }
+               int pos = sw_gui->script_entry_no;
+               sw_gui->load_selection(pos, row);
+       }
+       return 1;
+}
 
 int SWindowGUI::load_script_line(FILE *fp)
 {
@@ -731,10 +773,10 @@ int SWindowGUI::load_script_line(FILE *fp)
 
        for(;;) { // load non-blank lines
                //int len = strlen(line);
-               //if( cp[len-1] == '\n' ) cp[len-1] = 0;
+               //if( line[len-1] == '\n' ) line[len-1] = ' ';
                entry->append(line);
                char *cp = fgets(line,sizeof(line),fp);
-               if( !cp ) return 1;
+               if( !cp ) break;
                ++script_line_no;
                while( *cp && isspace(*cp) ) ++cp;
                if( !*cp ) break;
@@ -752,7 +794,11 @@ void SWindowGUI::load_script()
                MainError::show_error(string);
                return;
        }
+       load_script(fp);
+}
 
+void SWindowGUI::load_script(FILE *fp)
+{
        script.remove_all_objects();
        script_line_no = 0;
        script_text_lines = 0;
@@ -760,13 +806,13 @@ void SWindowGUI::load_script()
        char value[64];
        sprintf(value,"%ld",ftell(fp));
        script_filesz->update(value);
-       sprintf(value,"%ld",script_line_no);
+       sprintf(value,"%jd",script_line_no);
        script_lines->update(value);
        sprintf(value,"%d",script.size());
        script_entries->update(value);
-       sprintf(value,"%ld",script_text_lines);
+       sprintf(value,"%jd",script_text_lines);
        script_texts->update(value);
-       int hw = 2*script_scroll->get_h();
+       int hw = script_scroll->get_h();
        script_scroll->update_length(script.size(), script_entry_no, hw, 0);
        script_position->update(script_entry_no);
        script_position->set_boundaries((int64_t)0, (int64_t)script.size()-1);
@@ -795,6 +841,10 @@ void SWindowGUI::save_spumux_data()
                *cp = 0;
                snprintf(ext,len,"-%s.udvd",track_title);
                FILE *fp = fopen(filename, "w");
+               if( !fp ) {
+                       eprintf(_("Unable to open %s:\n%m"), filename);
+                       continue;
+               }
                int64_t start = 0;
                for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
                        SEdit *sedit = (SEdit *)edit;
@@ -802,7 +852,7 @@ void SWindowGUI::save_spumux_data()
                                int64_t end = start + sedit->length;
                                char *text = sedit->get_text();
                                if( *text ) {
-                                       fprintf(fp, "{%ld}{%ld}%s\n", start, end-1, text);
+                                       fprintf(fp, "{%jd}{%jd}%s\n", start, end-1, text);
                                }
                                start = end;
                        }
@@ -852,8 +902,8 @@ void SWindow::stop()
                if( gui ) gui->stop(1);
                window_lock->unlock();
                Thread::cancel();
-               Thread::join();
        }
+       Thread::join();
 }
 
 void SWindow::run()