]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/FormBibtex.C
Introduce LFUN_PRINT.
[lyx.git] / src / frontends / xforms / FormBibtex.C
index 384f27e745ebb573809c6f2153125da3dd106e23..71416187e1356669392e783a7089bb184adb3c63 100644 (file)
@@ -5,7 +5,7 @@
  *
  * \author Angus Leeming
  * \author John Levon
- * \author Herbert Voss
+ * \author Herbert Voß
  * \author Rob Lahaye
  *
  * Full author contact details are available in file CREDITS.
 #include <config.h>
 
 #include "FormBibtex.h"
-#include "forms/form_bibtex.h"
 #include "ControlBibtex.h"
+#include "forms/form_bibtex.h"
 
-#include "xformsBC.h"
 #include "Tooltips.h"
 #include "xforms_helpers.h"
-#include "lyx_forms.h"
-#include "combox.h"
-
-#include "tex_helpers.h"
+#include "xformsBC.h"
 
-#include "gettext.h"
 #include "support/filetools.h"
+#include "support/globbing.h"
 #include "support/lstrings.h"
+#include "support/lyxalgo.h"
 
-namespace support = lyx::support;
-
-using std::vector;
-
-
-namespace {
-
-struct SameName {
-       SameName(string const & name) : name_(name) {}
-       bool operator()(string const & abs_name) {
-               return name_ == support::OnlyFilename(abs_name);
-       }
-private:
-       string name_;
-};
-
-
-string const get_absolute_filename(string const & file,
-                                  string const & buffer_path,
-                                  vector<string> const & bibfiles)
-{
-       if (support::AbsolutePath(file))
-               return file;
-
-       string const try1 = support::MakeAbsPath(file, buffer_path);
-       if (support::IsFileReadable(try1))
-               return try1;
-
-       string const name = support::OnlyFilename(file);
-
-       vector<string>::const_iterator it  = bibfiles.begin();
-       vector<string>::const_iterator end = bibfiles.end();
-       it = std::find_if(it, end, SameName(name));
-       if (it == end)
-               return try1;
-       return *it;
-}
-
-
-bool find_file_in_browser(FL_OBJECT * browser,
-                         string const & name,
-                         string const & buffer_path,
-                         vector<string> const & bibfiles)
-{
-       vector<string> browser_vec = getVector(browser);
-       vector<string>::iterator begin = browser_vec.begin();
-       vector<string>::iterator end   = browser_vec.end();
-       vector<string>::iterator it    = begin;
-       for (; it != end; ++it) {
-               *it = get_absolute_filename(*it, buffer_path, bibfiles);
-       }
-
-       string const abs_name = get_absolute_filename(name, buffer_path, bibfiles);
-       
-       it = std::find(begin, end, abs_name);
-       return it != end;
-}
-
+#include "lyx_forms.h"
 
-int find_style_in_combox(FL_OBJECT * combox, string const & name)
-{
-       int const size = fl_get_combox_maxitems(combox);
-       for (int i = 1; i <= size; ++i) {
-               char const * const tmp = fl_get_combox_line(combox, i);
-               string const str = tmp ? support::trim(tmp) : string();
-               if (str == name)
-                       return i;
-       }
-       return 0;
-}
+using lyx::support::ChangeExtension;
+using lyx::support::compare;
+using lyx::support::contains;
+using lyx::support::FileFilterList;
+using lyx::support::getStringFromVector;
+using lyx::support::getVectorFromString;
+using lyx::support::OnlyFilename;
+using lyx::support::prefixIs;
+using lyx::support::split;
 
-} // namespace anon
+using std::vector;
+using std::string;
 
 
 typedef FormController<ControlBibtex, FormView<FD_bibtex> > base_class;
@@ -114,394 +53,192 @@ void FormBibtex::build()
 {
        dialog_.reset(build_bibtex(this));
 
-       // Manage the ok and cancel/close buttons
+       // Manage the ok, apply, restore and cancel/close buttons
        bcview().setOK(dialog_->button_ok);
+       bcview().setApply(dialog_->button_apply);
        bcview().setCancel(dialog_->button_close);
+       bcview().setRestore(dialog_->button_restore);
 
        // disable for read-only documents
-       bcview().addReadOnly(dialog_->browser_databases);
-       bcview().addReadOnly(dialog_->button_browse_db);
-       bcview().addReadOnly(dialog_->button_delete_db);
-       bcview().addReadOnly(dialog_->radio_absolute_path);
-       bcview().addReadOnly(dialog_->radio_relative_path);
-       bcview().addReadOnly(dialog_->radio_name_only);
        bcview().addReadOnly(dialog_->input_database);
-       bcview().addReadOnly(dialog_->button_add_db);
-       bcview().addReadOnly(dialog_->combox_style);
-       bcview().addReadOnly(dialog_->button_browse);
+       bcview().addReadOnly(dialog_->button_database_browse);
+       bcview().addReadOnly(dialog_->button_style_browse);
+       bcview().addReadOnly(dialog_->button_rescan);
+       bcview().addReadOnly(dialog_->input_style);
        bcview().addReadOnly(dialog_->check_bibtotoc);
 
-       // callback for double click in browser
-       fl_set_browser_dblclick_callback(dialog_->browser_databases,
-                                        C_FormDialogView_InputCB, 2);
+       // trigger an input event for cut&paste with middle mouse button.
+       setPrehandler(dialog_->input_database);
+       setPrehandler(dialog_->input_style);
 
-       fl_set_input_return(dialog_->input_database, FL_RETURN_ALWAYS);
+       fl_set_input_return(dialog_->input_database, FL_RETURN_CHANGED);
+       fl_set_input_return(dialog_->input_style, FL_RETURN_CHANGED);
 
-       storage_.init(dialog_->radio_absolute_path, ABSOLUTE_PATH);
-       storage_.init(dialog_->radio_relative_path, RELATIVE_PATH);
-       storage_.init(dialog_->radio_name_only,     NAME_ONLY);
+       // callback for double click in browser
+       fl_set_browser_dblclick_callback(dialog_->browser_styles,
+                                        C_FormDialogView_InputCB, 2);
 
        // set up the tooltips
-       string str = _("Selected BibTeX databases. Double click to edit");
-       tooltips().init(dialog_->browser_databases, str);
-
-#if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
-       // Work-around xforms' bug; enable tooltips for browser widgets.
-       setPrehandler(dialog_->browser_databases);
-#endif
-       str = _("Add a BibTeX database file");
-       tooltips().init(dialog_->button_browse_db, str);
+       string str = _("The database you want to cite from. Insert it "
+                      "without the default extension \".bib\". Use comma "
+                      "to separate databases.");
+       tooltips().init(dialog_->button_database_browse, str);
 
-       str = _("Remove the selected database");
-       tooltips().init(dialog_->button_delete_db, str);
+       str = _("Browse directory for BibTeX stylefiles");
+       tooltips().init(dialog_->button_style_browse, str);
 
-       str = _("Store the absolute path to the file");
-       tooltips().init(dialog_->radio_absolute_path, str);
+       str = _("The BibTeX style to use (only one allowed). Insert it without "
+               "the default extension \".bst\" and without path.");
+       tooltips().init(dialog_->input_style, str);
 
-       str = _("Store the relative path to the file");
-       tooltips().init(dialog_->radio_relative_path, str);
-
-       str = _("Store the file name only. Use TeX magic to find it");
-       tooltips().init(dialog_->radio_name_only, str);
-
-       str = _("Input BibTeX database file");
-       tooltips().init(dialog_->input_database, str);
-
-       str = _("Add the BibTeX database file in the input field");
-       tooltips().init(dialog_->button_add_db, str);
-
-       str = _("The BibTeX style");
-       tooltips().init(dialog_->combox_style, str);
-
-       str = _("Choose a style file");
-       tooltips().init(dialog_->button_browse, str);
-
-       str = _("Add bibliography to the table of contents");
+       str = _("Select if the bibliography should appear in the Table "
+               "of Contents");
        tooltips().init(dialog_->check_bibtotoc, str);
-}
-
-
-void FormBibtex::update()
-{
-       controller().getBibFiles(bib_files_namesonly_);
-       getTexFileList("bibFiles.lst", bib_files_);
-
-       browser_deactivated();
-
-       InsetBibtexParams const & params = controller().params();
-
-       fl_clear_browser(dialog_->browser_databases);
-       vector<support::FileName>::const_iterator fit  = params.databases.begin();
-       vector<support::FileName>::const_iterator fend = params.databases.end();
-       for (; fit != fend; ++fit) {
-               string const db = fit->outputFilename(kernel().bufferFilepath());
-               fl_add_browser_line(dialog_->browser_databases, db.c_str());
-       }
-
-       fl_set_button(dialog_->check_bibtotoc, params.bibtotoc);
-
-       fl_clear_combox(dialog_->combox_style);
-
-       int item_nr = 0;
-       vector<string> styles;
-       controller().getBibStyles(styles);
-       vector<string>::const_iterator sit  = styles.begin();
-       vector<string>::const_iterator send = styles.end();
-       for (; sit != send; ++sit) {
-               string const item = support::ChangeExtension(*sit, "");
-               fl_addto_combox(dialog_->combox_style, item.c_str());
-               if (item == params.style)
-                       item_nr = fl_get_combox_maxitems(dialog_->combox_style);
-       }
-
-       if (item_nr == 0) {
-               fl_addto_combox(dialog_->combox_style, params.style.c_str());
-               item_nr = fl_get_combox_maxitems(dialog_->combox_style);
-       }
-
-       fl_set_combox(dialog_->combox_style, item_nr);
-}
 
+       str = _("Double click to choose a BibTeX style from the list.");
+       tooltips().init(dialog_->browser_styles, str);
 
-void FormBibtex::apply()
-{
-       InsetBibtexParams params;
-
-       FL_OBJECT * browser = dialog_->browser_databases;
-       int const size = fl_get_browser_maxline(browser);
-       for (int i = 0; i < size; ++i) {
-               string const text = fl_get_browser_line(browser, i+1);
-               support::FileName file;
-               file.set(text, kernel().bufferFilepath());
-                params.databases.push_back(file);
-        }
-
-       params.style = support::trim(fl_get_combox_text(dialog_->combox_style));
-       params.bibtotoc = fl_get_button(dialog_->check_bibtotoc);
+#if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
+       // Work-around xforms' bug; enable tooltips for browser widgets.
+       setPrehandler(dialog_->browser_styles);
+#endif
 
-       controller().params() = params;
+       str = _("Updates your TeX system for a new bibstyle list. Only "
+               "the styles which are in directories where TeX finds them "
+               "are listed!");
+       tooltips().init(dialog_->button_rescan, str);
 }
 
 
 ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value)
 {
-       ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
-
-       if (ob == dialog_->browser_databases && ob_value == 2) {
-               activate = browser_double_click();
-
-       } else if (ob == dialog_->browser_databases) {
-               activate = browser_selected();
-
-       } else if (ob == dialog_->button_browse_db) {
-               activate = database_browse();
-
-       } else if (ob == dialog_->button_delete_db) {
-               activate = browser_delete();
-
-       } else if (ob == dialog_->radio_absolute_path) {
-               activate = set_path(ABSOLUTE_PATH);
-
-       } else if (ob == dialog_->radio_relative_path) {
-               activate = set_path(RELATIVE_PATH);
-
-       } else if (ob == dialog_->radio_name_only) {
-               activate = set_path(NAME_ONLY);
-
-       } else if (ob == dialog_->input_database) {
-               input_database();
-
-       } else if (ob == dialog_->button_add_db) {
-               activate = add_database();
-
-       } else if (ob == dialog_->button_browse) {
-               activate = style_browse();
+       if (ob == dialog_->button_database_browse) {
+               // When browsing, take the first file only
+               string const in_name = getString(dialog_->input_database);
+               FileFilterList const
+                       filter(_("*.bib| BibTeX Databases (*.bib)"));
+               string out_name =
+                       controller().browse("", _("Select Database"),
+                                           filter);
+               if (!out_name.empty()) {
+                       // add the database to any existing ones
+                       if (!in_name.empty())
+                               out_name = in_name + ',' + out_name;
+
+                       fl_set_input(dialog_->input_database, out_name.c_str());
+               }
+
+       } else if (ob == dialog_->button_style_browse) {
+               string const in_name = getString(dialog_->input_style);
+               FileFilterList const
+                       filter(_("*.bst| BibTeX Styles (*.bst)"));
+               string const style = controller()
+                       .browse(in_name, _("Select BibTeX-Style"), filter);
+               if (!style.empty()) {
+                       fl_set_input(dialog_->input_style, style.c_str());
+               }
+
+       } else if (ob == dialog_->browser_styles && ob_value == 2) {
+               // double clicked in styles browser
+               string const style = getString(dialog_->browser_styles);
+               if (style.empty()) {
+                       return ButtonPolicy::SMI_NOOP;
+               } else {
+                       fl_set_input(dialog_->input_style,
+                                       ChangeExtension(style, "").c_str());
+               }
+               // reset the browser so that the following
+               // single-click callback doesn't do anything
+               fl_deselect_browser(dialog_->browser_styles);
+
+       } else if (ob == dialog_->button_rescan) {
+               fl_clear_browser(dialog_->browser_styles);
+               controller().rescanBibStyles();
+               vector<string> styles;
+               controller().getBibStyles(styles);
+               fl_add_browser_line(dialog_->browser_styles,
+                                   getStringFromVector(styles, "\n").c_str());
+       }
 
-       } else if (ob == dialog_->combox_style || ob == dialog_->check_bibtotoc) {
-               activate = ButtonPolicy::SMI_VALID;
+       // with an empty database nothing makes sense ...
+       if (!compare(fl_get_input(dialog_->input_database), "")) {
+               return ButtonPolicy::SMI_NOOP;
        }
 
-       return activate;
+       return ButtonPolicy::SMI_VALID;
 }
 
 
-ButtonPolicy::SMInput FormBibtex::add_database()
+void FormBibtex::update()
 {
-       FL_OBJECT * input   = dialog_->input_database;
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       string const db = getString(input);
+       fl_set_input(dialog_->input_database,
+                    controller().params().getContents().c_str());
 
-       bool const activate =
-               !db.empty() &&
-               !find_file_in_browser(browser, db, kernel().bufferFilepath(),
-                                     bib_files_);
+       string bibtotoc = "bibtotoc";
+       string bibstyle = controller().params().getOptions();
 
-       if (activate)
-               fl_add_browser_line(browser, db.c_str());
+       bool const bibtotoc_exists = prefixIs(bibstyle, bibtotoc);
+       fl_set_button(dialog_->check_bibtotoc, bibtotoc_exists);
+       if (bibtotoc_exists) {
+               if (contains(bibstyle, ',')) { // bibstyle exists?
+                       bibstyle = split(bibstyle, bibtotoc, ',');
+               } else {
+                       bibstyle.erase();
+               }
+       }
+       fl_set_input(dialog_->input_style, bibstyle.c_str());
 
-       fl_set_input(input, "");
-       setEnabled(dialog_->button_add_db, false);
+       vector<string> styles;
+       controller().getBibStyles(styles);
 
-       return activate ? ButtonPolicy::SMI_VALID : ButtonPolicy::SMI_NOOP;
+       fl_clear_browser(dialog_->browser_styles);
+       fl_add_browser_line(dialog_->browser_styles,
+                           getStringFromVector(styles, "\n").c_str());
 }
 
-
 namespace {
 
-bool inTeXSearchPath(string const & db, vector<string> const & tex_bib_files)
-{
-       vector<string>::const_iterator it  = tex_bib_files.begin();
-       vector<string>::const_iterator end = tex_bib_files.end();
-       return std::find(it, end, db) != end;
-}
-
-
-FormBibtex::PathStyle storageStyle(string const & db,
-                                  vector<string> const & tex_bib_files)
+string const unique_and_no_extensions(string const & str_in)
 {
-       if (support::AbsolutePath(db))
-               return FormBibtex::ABSOLUTE_PATH;
-
-       string const name = support::OnlyFilename(db);
-       if (db == name && inTeXSearchPath(name, tex_bib_files))
-               return FormBibtex::NAME_ONLY;
-
-       return FormBibtex::RELATIVE_PATH;
+       vector<string> dbase = getVectorFromString(str_in);
+       for (vector<string>::iterator it = dbase.begin();
+            it != dbase.end(); ++it) {
+               *it = ChangeExtension(*it, string());
+       }
+       lyx::eliminate_duplicates(dbase);
+       return getStringFromVector(dbase);
 }
 
 } // namespace anon
 
 
-ButtonPolicy::SMInput FormBibtex::browser_selected()
-{
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       int const sel = fl_get_browser(browser);
-       if (sel < 1 || sel > fl_get_browser_maxline(browser))
-               return ButtonPolicy::SMI_NOOP;
-
-       setEnabled(dialog_->button_delete_db, true);
-       storage_.setEnabled(true);
-       fl_set_input(dialog_->input_database, "");
-
-       string const db = fl_get_browser_line(browser, sel);
-       storage_.set(storageStyle(db, bib_files_namesonly_));
-
-       return ButtonPolicy::SMI_NOOP;
-}
-
-
-ButtonPolicy::SMInput FormBibtex::browser_double_click()
-{
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       int const sel = fl_get_browser(browser);
-       if (sel < 1 || sel > fl_get_browser_maxline(browser))
-               return ButtonPolicy::SMI_NOOP;
-
-       string const db = fl_get_browser_line(browser, sel);
-       fl_set_input(dialog_->input_database, db.c_str());
-       setEnabled(dialog_->button_add_db, true);
-
-       // Reset the browser so that the following single-click
-       // callback doesn't do anything
-       fl_deselect_browser(browser);
-
-       return ButtonPolicy::SMI_NOOP;
-}
-
-
-ButtonPolicy::SMInput FormBibtex::browser_add_db(string const & name)
-{
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       if (find_file_in_browser(browser, name, kernel().bufferFilepath(),
-                                bib_files_))
-               return ButtonPolicy::SMI_NOOP;
-
-       input_clear();
-
-       fl_add_browser_line(browser, name.c_str());
-       int const line = fl_get_browser_maxline(browser);
-       fl_select_browser_line(browser, line);
-
-       browser_selected();
-       return ButtonPolicy::SMI_VALID;
-}
-
-
-ButtonPolicy::SMInput FormBibtex::browser_delete()
-{
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       int const sel = fl_get_browser(browser);
-       if (sel < 1 || sel > fl_get_browser_maxline(browser))
-               return ButtonPolicy::SMI_NOOP;
-
-       fl_delete_browser_line(browser, sel);
-       browser_deactivated();
-       return ButtonPolicy::SMI_VALID;
-}
-
-
-ButtonPolicy::SMInput FormBibtex::set_path(PathStyle style)
+void FormBibtex::apply()
 {
-       FL_OBJECT * browser = dialog_->browser_databases;
-
-       int const sel = fl_get_browser(browser);
-       if (sel < 1 || sel > fl_get_browser_maxline(browser))
-               return ButtonPolicy::SMI_NOOP;
-
-       string const db = fl_get_browser_line(browser, sel);
-       string const abs_name =
-               get_absolute_filename(db, kernel().bufferFilepath(), bib_files_);
-
-       switch (style) {
-       case ABSOLUTE_PATH:
-               fl_replace_browser_line(browser, sel, abs_name.c_str());
-               break;
-       case RELATIVE_PATH: 
-       {
-               string const rel_name =
-                       support::MakeRelPath(abs_name, kernel().bufferFilepath());
-               fl_replace_browser_line(browser, sel, rel_name.c_str());
-               break;
-       }
-       case NAME_ONLY:
-       {
-               string const name = support::OnlyFilename(abs_name);
-               fl_replace_browser_line(browser, sel, name.c_str());
-               break;
-       }
+       string const db = getString(dialog_->input_database);
+       if (db.empty()) {
+               // no database -> no bibtex-command and no options!
+               controller().params().setContents("");
+               controller().params().setOptions("");
+               return;
        }
-       
-       return ButtonPolicy::SMI_VALID;
-}
-
-
-ButtonPolicy::SMInput FormBibtex::database_browse()
-{
-       ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
-               
-       FL_OBJECT * browser = dialog_->browser_databases;
-       // When browsing, take the first file only
-       string const in_name = fl_get_browser_maxline(browser) > 0 ?
-               fl_get_browser_line(browser, 1) : string();
-
-       string const out_name =
-               controller().Browse("", _("Select Database"),
-                                   _("*.bib| BibTeX Databases (*.bib)"));
-
-       if (!out_name.empty() &&
-           out_name != in_name &&
-           !find_file_in_browser(browser, out_name,
-                                 kernel().bufferFilepath(),
-                                 bib_files_))
-               activate = browser_add_db(out_name);
-       return activate;
-}
 
+       controller().params().setContents(unique_and_no_extensions(db));
 
-ButtonPolicy::SMInput FormBibtex::style_browse()
-{
-       FL_OBJECT * combox = dialog_->combox_style;
-
-       string const in_name = fl_get_combox_text(combox);
-       string const style =
-               controller().Browse(in_name, _("Select BibTeX-Style"),
-                                   _("*.bst| BibTeX Styles (*.bst)"));
-
-       int const sel = find_style_in_combox(combox, style);
-       if (sel)
-               fl_set_combox(combox, sel);
-       else {
-               fl_addto_combox(combox, style.c_str());
-               fl_set_combox(combox, fl_get_combox_maxitems(combox));
+       // empty is valid!
+       string bibstyle = getString(dialog_->input_style);
+       if (!bibstyle.empty()) {
+               // save the BibTeX style without any ".bst" extension
+               bibstyle = ChangeExtension(OnlyFilename(bibstyle), "");
        }
 
-       return ButtonPolicy::SMI_VALID;
-}
-
+       bool const addtotoc = fl_get_button(dialog_->check_bibtotoc);
+       string const bibtotoc = addtotoc ? "bibtotoc" : "";
+       if (addtotoc && !bibstyle.empty()) {
+               // Both bibtotoc and style.
+               controller().params().setOptions(bibtotoc + ',' + bibstyle);
 
-void FormBibtex::browser_deactivated()
-{
-       setEnabled(dialog_->button_delete_db, false);
-       input_clear();
-       storage_.unset();
-       storage_.setEnabled(false);
-}
-
-
-void FormBibtex::input_clear()
-{
-       fl_set_input(dialog_->input_database, "");
-       setEnabled(dialog_->button_add_db, false);
-}
-
-
-void FormBibtex::input_database()
-{
-       FL_OBJECT * input = dialog_->input_database;
-       setEnabled(dialog_->button_add_db, !getString(input).empty());
+       } else {
+               // At least one of addtotoc and bibstyle is empty. No harm to output both!
+               controller().params().setOptions(bibtotoc + bibstyle);
+       }
 }