]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBibtex.C
fix crash with "save as"
[lyx.git] / src / frontends / xforms / FormBibtex.C
1 /**
2  * \file FormBibtex.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming 
7  * \author John Levon
8  * \author Herbert Voss
9  * \author Rob Lahaye
10  *
11  * Full author contact details are available in file CREDITS
12  */
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include <config.h>
19 #include "xformsBC.h"
20 #include "ControlBibtex.h"
21 #include "FormBibtex.h"
22 #include "forms/form_bibtex.h"
23 #include "Tooltips.h"
24 #include "xforms_helpers.h"
25 #include FORMS_H_LOCATION
26
27 #include "helper_funcs.h"
28 #include "gettext.h"
29 #include "support/lstrings.h"
30 #include "support/filetools.h"
31 #include "support/lyxalgo.h"
32
33
34 using std::vector;
35 using std::sort;
36
37
38 typedef FormCB<ControlBibtex, FormDB<FD_bibtex> > base_class;
39
40 FormBibtex::FormBibtex()
41         : base_class(_("BibTeX Database"))
42 {}
43
44
45 void FormBibtex::build()
46 {
47         dialog_.reset(build_bibtex(this));
48
49         // Manage the ok, apply, restore and cancel/close buttons
50         bc().setOK(dialog_->button_ok);
51         bc().setApply(dialog_->button_apply);
52         bc().setCancel(dialog_->button_close);
53         bc().setRestore(dialog_->button_restore);
54
55         // disable for read-only documents
56         bc().addReadOnly(dialog_->input_database);
57         bc().addReadOnly(dialog_->button_database_browse);
58         bc().addReadOnly(dialog_->button_style_browse);
59         bc().addReadOnly(dialog_->button_rescan);
60         bc().addReadOnly(dialog_->input_style);
61         bc().addReadOnly(dialog_->check_bibtotoc);
62
63         // trigger an input event for cut&paste with middle mouse button.
64         setPrehandler(dialog_->input_database);
65         setPrehandler(dialog_->input_style);
66
67         fl_set_input_return(dialog_->input_database, FL_RETURN_CHANGED);
68         fl_set_input_return(dialog_->input_style, FL_RETURN_CHANGED);
69
70         // set up the tooltips
71         string str = _("The database you want to cite from. Insert it "
72                        "without the default extension \".bib\". Use comma "
73                        "to separate databases.");
74         tooltips().init(dialog_->button_database_browse, str);
75
76         str = _("Browse directory for BibTeX stylefiles");
77         tooltips().init(dialog_->button_style_browse, str);
78
79         str = _("The BibTeX style to use (only one allowed). Insert it without "
80                 "the default extension \".bst\" and without path.");
81         tooltips().init(dialog_->input_style, str);
82
83         str = _("Select if the bibliography should appear in the Table "
84                 "of Contents");
85         tooltips().init(dialog_->check_bibtotoc, str);
86
87         str = _("Choose a BibTeX style from the list.");
88         tooltips().init(dialog_->browser_styles, str);
89         // Work-around xforms' bug; enable tooltips for browser widgets.
90         setPrehandler(dialog_->browser_styles);
91
92         str = _("Updates your TeX system for a new bibstyle list. Only "
93                 "the styles which are in directories where TeX finds them "
94                 "are listed!");
95         tooltips().init(dialog_->button_rescan, str);
96 }
97
98
99 ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long)
100 {
101         if (ob == dialog_->button_database_browse) {
102                 // When browsing, take the first file only
103                 string const in_name = getString(dialog_->input_database);
104                 string out_name =
105                         controller().Browse("",
106                                 _("Select Database"),
107                                 _("*.bib| BibTeX Databases (*.bib)"));
108                 if (!out_name.empty()) {
109                         // add the database to any existing ones
110                         if (!in_name.empty())
111                                 out_name = in_name + ',' + out_name;
112
113                         fl_set_input(dialog_->input_database, out_name.c_str());
114                 }
115
116         } else if (ob == dialog_->button_style_browse) {
117                 string const in_name = getString(dialog_->input_style);
118                 string const style = controller().Browse(in_name,
119                                         _("Select BibTeX-Style"),
120                                         _("*.bst| BibTeX Styles (*.bst)"));
121                 if (!style.empty()) {
122                         fl_set_input(dialog_->input_style, style.c_str());
123                 }
124
125         } else if (ob == dialog_->browser_styles) {
126                 string const style = getString(dialog_->browser_styles);
127                 if (style.empty()) {
128                         return ButtonPolicy::SMI_NOOP;
129                 } else {
130                         fl_set_input(dialog_->input_style,
131                                         ChangeExtension(style, "").c_str());
132                 }
133
134         } else if (ob == dialog_->button_rescan) {
135                 fl_clear_browser(dialog_->browser_styles);
136                 controller().rescanBibStyles();
137                 string const str =
138                         controller().getBibStyles();
139                 fl_add_browser_line(dialog_->browser_styles, str.c_str());
140         }
141
142         // with an empty database nothing makes sense ...
143         if (!compare(fl_get_input(dialog_->input_database), "")) {
144                 return ButtonPolicy::SMI_NOOP;
145         }
146
147         return ButtonPolicy::SMI_VALID;
148 }
149
150
151 void FormBibtex::update()
152 {
153         fl_set_input(dialog_->input_database,
154                      controller().params().getContents().c_str());
155
156         string bibtotoc = "bibtotoc";
157         string bibstyle = controller().params().getOptions();
158
159         bool const bibtotoc_exists = prefixIs(bibstyle, bibtotoc);
160         fl_set_button(dialog_->check_bibtotoc, bibtotoc_exists);
161         if (bibtotoc_exists) {
162                 if (contains(bibstyle, ',')) { // bibstyle exists?
163                         bibstyle = split(bibstyle, bibtotoc, ',');
164                 } else {
165                         bibstyle.erase();
166                 }
167         }
168         fl_set_input(dialog_->input_style, bibstyle.c_str());
169
170         fl_clear_browser(dialog_->browser_styles);
171         string const str = controller().getBibStyles();
172         fl_add_browser_line(dialog_->browser_styles, str.c_str());
173 }
174
175 namespace {
176
177 string const unique_and_no_extensions(string const & str_in)
178 {
179         vector<string> dbase = getVectorFromString(str_in);
180         for (vector<string>::iterator it = dbase.begin();
181              it != dbase.end(); ++it) {
182                 *it = ChangeExtension(*it, string());
183         }
184         lyx::eliminate_duplicates(dbase);
185         return getStringFromVector(dbase);
186 }
187
188 } // namespace anon
189
190
191 void FormBibtex::apply()
192 {
193         string const db = getString(dialog_->input_database);
194         if (db.empty()) {
195                 // no database -> no bibtex-command and no options!
196                 controller().params().setContents("");
197                 controller().params().setOptions("");
198                 return;
199         }
200
201         controller().params().setContents(unique_and_no_extensions(db));
202
203         // empty is valid!
204         string bibstyle = getString(dialog_->input_style);
205         if (!bibstyle.empty()) {
206                 // save the BibTeX style without any ".bst" extension
207                 bibstyle = ChangeExtension(OnlyFilename(bibstyle), "");
208         }
209
210         bool const addtotoc = fl_get_button(dialog_->check_bibtotoc);
211         string const bibtotoc = addtotoc ? "bibtotoc" : "";
212         if (addtotoc && !bibstyle.empty()) {
213                 // Both bibtotoc and style.
214                 controller().params().setOptions(bibtotoc + "," + bibstyle);
215
216         } else {
217                 // At least one of addtotoc and bibstyle is empty. No harm to output both!
218                 controller().params().setOptions(bibtotoc + bibstyle);
219         }
220 }