3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
11 * Full author contact details are available in file CREDITS.
16 #include "FormBibtex.h"
17 #include "forms/form_bibtex.h"
18 #include "ControlBibtex.h"
22 #include "xforms_helpers.h"
23 #include "lyx_forms.h"
26 #include "tex_helpers.h"
29 #include "support/filetools.h"
30 #include "support/lstrings.h"
32 namespace support = lyx::support;
40 SameName(string const & name) : name_(name) {}
41 bool operator()(string const & abs_name) {
42 return name_ == support::OnlyFilename(abs_name);
49 string const get_absolute_filename(string const & file,
50 string const & buffer_path,
51 vector<string> const & bibfiles)
53 if (support::AbsolutePath(file))
56 string const try1 = support::MakeAbsPath(file, buffer_path);
57 if (support::IsFileReadable(try1))
60 string const name = support::OnlyFilename(file);
62 vector<string>::const_iterator it = bibfiles.begin();
63 vector<string>::const_iterator end = bibfiles.end();
64 it = std::find_if(it, end, SameName(name));
71 bool find_file_in_browser(FL_OBJECT * browser,
73 string const & buffer_path,
74 vector<string> const & bibfiles)
76 vector<string> browser_vec = getVector(browser);
77 vector<string>::iterator begin = browser_vec.begin();
78 vector<string>::iterator end = browser_vec.end();
79 vector<string>::iterator it = begin;
80 for (; it != end; ++it) {
81 *it = get_absolute_filename(*it, buffer_path, bibfiles);
84 string const abs_name = get_absolute_filename(name, buffer_path, bibfiles);
86 it = std::find(begin, end, abs_name);
91 int find_style_in_combox(FL_OBJECT * combox, string const & name)
93 int const size = fl_get_combox_maxitems(combox);
94 for (int i = 1; i <= size; ++i) {
95 char const * const tmp = fl_get_combox_line(combox, i);
96 string const str = tmp ? support::trim(tmp) : string();
106 typedef FormController<ControlBibtex, FormView<FD_bibtex> > base_class;
108 FormBibtex::FormBibtex(Dialog & parent)
109 : base_class(parent, _("BibTeX Database"))
113 void FormBibtex::build()
115 dialog_.reset(build_bibtex(this));
117 // Manage the ok and cancel/close buttons
118 bcview().setOK(dialog_->button_ok);
119 bcview().setCancel(dialog_->button_close);
121 // disable for read-only documents
122 bcview().addReadOnly(dialog_->browser_databases);
123 bcview().addReadOnly(dialog_->button_browse_db);
124 bcview().addReadOnly(dialog_->button_delete_db);
125 bcview().addReadOnly(dialog_->radio_absolute_path);
126 bcview().addReadOnly(dialog_->radio_relative_path);
127 bcview().addReadOnly(dialog_->radio_name_only);
128 bcview().addReadOnly(dialog_->input_database);
129 bcview().addReadOnly(dialog_->button_add_db);
130 bcview().addReadOnly(dialog_->combox_style);
131 bcview().addReadOnly(dialog_->button_browse);
132 bcview().addReadOnly(dialog_->check_bibtotoc);
134 // callback for double click in browser
135 fl_set_browser_dblclick_callback(dialog_->browser_databases,
136 C_FormDialogView_InputCB, 2);
138 fl_set_input_return(dialog_->input_database, FL_RETURN_ALWAYS);
140 storage_.init(dialog_->radio_absolute_path, ABSOLUTE_PATH);
141 storage_.init(dialog_->radio_relative_path, RELATIVE_PATH);
142 storage_.init(dialog_->radio_name_only, NAME_ONLY);
144 // set up the tooltips
145 string str = _("Selected BibTeX databases. Double click to edit");
146 tooltips().init(dialog_->browser_databases, str);
148 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
149 // Work-around xforms' bug; enable tooltips for browser widgets.
150 setPrehandler(dialog_->browser_databases);
152 str = _("Add a BibTeX database file");
153 tooltips().init(dialog_->button_browse_db, str);
155 str = _("Remove the selected database");
156 tooltips().init(dialog_->button_delete_db, str);
158 str = _("Store the absolute path to the file");
159 tooltips().init(dialog_->radio_absolute_path, str);
161 str = _("Store the relative path to the file");
162 tooltips().init(dialog_->radio_relative_path, str);
164 str = _("Store the file name only. Use TeX magic to find it");
165 tooltips().init(dialog_->radio_name_only, str);
167 str = _("Input BibTeX database file");
168 tooltips().init(dialog_->input_database, str);
170 str = _("Add the BibTeX database file in the input field");
171 tooltips().init(dialog_->button_add_db, str);
173 str = _("The BibTeX style");
174 tooltips().init(dialog_->combox_style, str);
176 str = _("Choose a style file");
177 tooltips().init(dialog_->button_browse, str);
179 str = _("Add bibliography to the table of contents");
180 tooltips().init(dialog_->check_bibtotoc, str);
184 void FormBibtex::update()
186 controller().getBibFiles(bib_files_namesonly_);
187 getTexFileList("bibFiles.lst", bib_files_);
189 browser_deactivated();
191 InsetBibtexParams const & params = controller().params();
193 fl_clear_browser(dialog_->browser_databases);
194 vector<support::FileName>::const_iterator fit = params.databases.begin();
195 vector<support::FileName>::const_iterator fend = params.databases.end();
196 for (; fit != fend; ++fit) {
197 string const db = fit->outputFilename(kernel().bufferFilepath());
198 fl_add_browser_line(dialog_->browser_databases, db.c_str());
201 fl_set_button(dialog_->check_bibtotoc, params.bibtotoc);
203 fl_clear_combox(dialog_->combox_style);
206 vector<string> styles;
207 controller().getBibStyles(styles);
208 vector<string>::const_iterator sit = styles.begin();
209 vector<string>::const_iterator send = styles.end();
210 for (; sit != send; ++sit) {
211 string const item = support::ChangeExtension(*sit, "");
212 fl_addto_combox(dialog_->combox_style, item.c_str());
213 if (item == params.style)
214 item_nr = fl_get_combox_maxitems(dialog_->combox_style);
218 fl_addto_combox(dialog_->combox_style, params.style.c_str());
219 item_nr = fl_get_combox_maxitems(dialog_->combox_style);
222 fl_set_combox(dialog_->combox_style, item_nr);
226 void FormBibtex::apply()
228 InsetBibtexParams params;
230 FL_OBJECT * browser = dialog_->browser_databases;
231 int const size = fl_get_browser_maxline(browser);
232 for (int i = 0; i < size; ++i) {
233 string const text = fl_get_browser_line(browser, i+1);
234 support::FileName file;
235 file.set(text, kernel().bufferFilepath());
236 params.databases.push_back(file);
239 params.style = support::trim(fl_get_combox_text(dialog_->combox_style));
240 params.bibtotoc = fl_get_button(dialog_->check_bibtotoc);
242 controller().params() = params;
246 ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value)
248 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
250 if (ob == dialog_->browser_databases && ob_value == 2) {
251 activate = browser_double_click();
253 } else if (ob == dialog_->browser_databases) {
254 activate = browser_selected();
256 } else if (ob == dialog_->button_browse_db) {
257 activate = database_browse();
259 } else if (ob == dialog_->button_delete_db) {
260 activate = browser_delete();
262 } else if (ob == dialog_->radio_absolute_path) {
263 activate = set_path(ABSOLUTE_PATH);
265 } else if (ob == dialog_->radio_relative_path) {
266 activate = set_path(RELATIVE_PATH);
268 } else if (ob == dialog_->radio_name_only) {
269 activate = set_path(NAME_ONLY);
271 } else if (ob == dialog_->input_database) {
274 } else if (ob == dialog_->button_add_db) {
275 activate = add_database();
277 } else if (ob == dialog_->button_browse) {
278 activate = style_browse();
280 } else if (ob == dialog_->combox_style || ob == dialog_->check_bibtotoc) {
281 activate = ButtonPolicy::SMI_VALID;
288 ButtonPolicy::SMInput FormBibtex::add_database()
290 FL_OBJECT * input = dialog_->input_database;
291 FL_OBJECT * browser = dialog_->browser_databases;
293 string const db = getString(input);
295 bool const activate =
297 !find_file_in_browser(browser, db, kernel().bufferFilepath(),
301 fl_add_browser_line(browser, db.c_str());
303 fl_set_input(input, "");
304 setEnabled(dialog_->button_add_db, false);
306 return activate ? ButtonPolicy::SMI_VALID : ButtonPolicy::SMI_NOOP;
312 bool inTeXSearchPath(string const & db, vector<string> const & tex_bib_files)
314 vector<string>::const_iterator it = tex_bib_files.begin();
315 vector<string>::const_iterator end = tex_bib_files.end();
316 return std::find(it, end, db) != end;
320 FormBibtex::PathStyle storageStyle(string const & db,
321 vector<string> const & tex_bib_files)
323 if (support::AbsolutePath(db))
324 return FormBibtex::ABSOLUTE_PATH;
326 string const name = support::OnlyFilename(db);
327 if (db == name && inTeXSearchPath(name, tex_bib_files))
328 return FormBibtex::NAME_ONLY;
330 return FormBibtex::RELATIVE_PATH;
336 ButtonPolicy::SMInput FormBibtex::browser_selected()
338 FL_OBJECT * browser = dialog_->browser_databases;
340 int const sel = fl_get_browser(browser);
341 if (sel < 1 || sel > fl_get_browser_maxline(browser))
342 return ButtonPolicy::SMI_NOOP;
344 setEnabled(dialog_->button_delete_db, true);
345 storage_.setEnabled(true);
346 fl_set_input(dialog_->input_database, "");
348 string const db = fl_get_browser_line(browser, sel);
349 storage_.set(storageStyle(db, bib_files_namesonly_));
351 return ButtonPolicy::SMI_NOOP;
355 ButtonPolicy::SMInput FormBibtex::browser_double_click()
357 FL_OBJECT * browser = dialog_->browser_databases;
359 int const sel = fl_get_browser(browser);
360 if (sel < 1 || sel > fl_get_browser_maxline(browser))
361 return ButtonPolicy::SMI_NOOP;
363 string const db = fl_get_browser_line(browser, sel);
364 fl_set_input(dialog_->input_database, db.c_str());
365 setEnabled(dialog_->button_add_db, true);
367 // Reset the browser so that the following single-click
368 // callback doesn't do anything
369 fl_deselect_browser(browser);
371 return ButtonPolicy::SMI_NOOP;
375 ButtonPolicy::SMInput FormBibtex::browser_add_db(string const & name)
377 FL_OBJECT * browser = dialog_->browser_databases;
379 if (find_file_in_browser(browser, name, kernel().bufferFilepath(),
381 return ButtonPolicy::SMI_NOOP;
385 fl_add_browser_line(browser, name.c_str());
386 int const line = fl_get_browser_maxline(browser);
387 fl_select_browser_line(browser, line);
390 return ButtonPolicy::SMI_VALID;
394 ButtonPolicy::SMInput FormBibtex::browser_delete()
396 FL_OBJECT * browser = dialog_->browser_databases;
398 int const sel = fl_get_browser(browser);
399 if (sel < 1 || sel > fl_get_browser_maxline(browser))
400 return ButtonPolicy::SMI_NOOP;
402 fl_delete_browser_line(browser, sel);
403 browser_deactivated();
404 return ButtonPolicy::SMI_VALID;
408 ButtonPolicy::SMInput FormBibtex::set_path(PathStyle style)
410 FL_OBJECT * browser = dialog_->browser_databases;
412 int const sel = fl_get_browser(browser);
413 if (sel < 1 || sel > fl_get_browser_maxline(browser))
414 return ButtonPolicy::SMI_NOOP;
416 string const db = fl_get_browser_line(browser, sel);
417 string const abs_name =
418 get_absolute_filename(db, kernel().bufferFilepath(), bib_files_);
422 fl_replace_browser_line(browser, sel, abs_name.c_str());
426 string const rel_name =
427 support::MakeRelPath(abs_name, kernel().bufferFilepath());
428 fl_replace_browser_line(browser, sel, rel_name.c_str());
433 string const name = support::OnlyFilename(abs_name);
434 fl_replace_browser_line(browser, sel, name.c_str());
439 return ButtonPolicy::SMI_VALID;
443 ButtonPolicy::SMInput FormBibtex::database_browse()
445 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
447 FL_OBJECT * browser = dialog_->browser_databases;
448 // When browsing, take the first file only
449 string const in_name = fl_get_browser_maxline(browser) > 0 ?
450 fl_get_browser_line(browser, 1) : string();
452 string const out_name =
453 controller().Browse("", _("Select Database"),
454 _("*.bib| BibTeX Databases (*.bib)"));
456 if (!out_name.empty() &&
457 out_name != in_name &&
458 !find_file_in_browser(browser, out_name,
459 kernel().bufferFilepath(),
461 activate = browser_add_db(out_name);
466 ButtonPolicy::SMInput FormBibtex::style_browse()
468 FL_OBJECT * combox = dialog_->combox_style;
470 string const in_name = fl_get_combox_text(combox);
472 controller().Browse(in_name, _("Select BibTeX-Style"),
473 _("*.bst| BibTeX Styles (*.bst)"));
475 int const sel = find_style_in_combox(combox, style);
477 fl_set_combox(combox, sel);
479 fl_addto_combox(combox, style.c_str());
480 fl_set_combox(combox, fl_get_combox_maxitems(combox));
483 return ButtonPolicy::SMI_VALID;
487 void FormBibtex::browser_deactivated()
489 setEnabled(dialog_->button_delete_db, false);
492 storage_.setEnabled(false);
496 void FormBibtex::input_clear()
498 fl_set_input(dialog_->input_database, "");
499 setEnabled(dialog_->button_add_db, false);
503 void FormBibtex::input_database()
505 FL_OBJECT * input = dialog_->input_database;
506 setEnabled(dialog_->button_add_db, !getString(input).empty());