]> git.lyx.org Git - lyx.git/blob - src/insets/InsetCommandParams.cpp
header cleanup
[lyx.git] / src / insets / InsetCommandParams.cpp
1 /**
2  * \file InsetCommandParams.cpp
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 Georg Baum
8  * \author Richard Heck
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "InsetCommandParams.h"
16
17 #include "InsetBibitem.h"
18 #include "InsetBibtex.h"
19 #include "InsetCitation.h"
20 #include "InsetFloatList.h"
21 #include "InsetHFill.h"
22 #include "InsetHyperlink.h"
23 #include "InsetInclude.h"
24 #include "InsetIndex.h"
25 #include "InsetLabel.h"
26 #include "InsetNomencl.h"
27 #include "InsetRef.h"
28 #include "InsetTOC.h"
29
30 #include "Lexer.h"
31
32 #include "support/debug.h"
33 #include "support/ExceptionMessage.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
36 #include "support/docstream.h"
37
38 #include <boost/assert.hpp>
39
40 using namespace std;
41 using namespace lyx::support;
42
43 namespace lyx {
44
45
46 InsetCommandParams::InsetCommandParams(InsetCode code)
47         : insetCode_(code), preview_(false)
48 {
49         cmdName_ = getDefaultCmd(code);
50         info_ = findInfo(code, cmdName_);
51         BOOST_ASSERT(info_);
52         params_.resize(info_->n);
53 }
54
55
56 InsetCommandParams::InsetCommandParams(InsetCode code,
57         string const & cmdName)
58         : insetCode_(code), cmdName_(cmdName), preview_(false)
59 {
60         info_ = findInfo(code, cmdName);
61         BOOST_ASSERT(info_);
62         params_.resize(info_->n);
63 }
64
65
66 CommandInfo const * InsetCommandParams::findInfo(
67         InsetCode code, string const & cmdName)
68 {
69         switch (code) {
70         case BIBITEM_CODE:
71                 return InsetBibitem::findInfo(cmdName);
72         case BIBTEX_CODE:
73                 return InsetBibtex::findInfo(cmdName);
74         case CITE_CODE:
75                 return InsetCitation::findInfo(cmdName);        
76         case FLOAT_LIST_CODE:
77                 return InsetFloatList::findInfo(cmdName);
78         case HFILL_CODE:
79                 return InsetHFill::findInfo(cmdName);
80         case HYPERLINK_CODE:
81                 return InsetHyperlink::findInfo(cmdName);
82         case INCLUDE_CODE:
83                 return InsetInclude::findInfo(cmdName);
84         case INDEX_PRINT_CODE:
85                 return InsetPrintIndex::findInfo(cmdName);
86         case LABEL_CODE:
87                 return InsetLabel::findInfo(cmdName);   
88         case NOMENCL_CODE:
89                 return InsetNomencl::findInfo(cmdName);
90         case NOMENCL_PRINT_CODE:
91                 return InsetPrintNomencl::findInfo(cmdName);
92         case REF_CODE:
93                 return InsetRef::findInfo(cmdName);
94         case TOC_CODE:
95                 return InsetTOC::findInfo(cmdName);
96         default:
97                 BOOST_ASSERT(false);
98         }
99         return 0;
100 }
101
102
103 string InsetCommandParams::getDefaultCmd(InsetCode code) {
104         switch (code) {
105                 case BIBITEM_CODE: 
106                         return InsetBibitem::defaultCommand();
107                 case BIBTEX_CODE:
108                         return InsetBibtex::defaultCommand();
109                 case CITE_CODE:
110                         return InsetCitation::defaultCommand();
111                 case FLOAT_LIST_CODE:
112                         return InsetFloatList::defaultCommand();
113                 case HFILL_CODE:
114                         return InsetHFill::defaultCommand();
115                 case HYPERLINK_CODE:
116                         return InsetHyperlink::defaultCommand();
117                 case INCLUDE_CODE:
118                         return InsetInclude::defaultCommand();
119                 case INDEX_PRINT_CODE:
120                         return InsetPrintIndex::defaultCommand();
121                 case LABEL_CODE:
122                         return InsetLabel::defaultCommand();
123                 case NOMENCL_CODE:
124                         return InsetNomencl::defaultCommand();
125                 case NOMENCL_PRINT_CODE:
126                         return InsetPrintNomencl::defaultCommand();
127                 case REF_CODE:
128                         return InsetRef::defaultCommand();
129                 case TOC_CODE:
130                         return InsetTOC::defaultCommand();
131                 default:
132                         BOOST_ASSERT(false);
133         }
134         return string(); //silence the warning
135 }
136
137
138 bool InsetCommandParams::isCompatibleCommand(
139                 InsetCode code, string const & s)
140 {
141         switch (code) {
142                 case BIBITEM_CODE: 
143                         return InsetBibitem::isCompatibleCommand(s);
144                 case BIBTEX_CODE:
145                         return InsetBibtex::isCompatibleCommand(s);
146                 case CITE_CODE:
147                         return InsetCitation::isCompatibleCommand(s);
148                 case FLOAT_LIST_CODE:
149                         return InsetFloatList::isCompatibleCommand(s);
150                 case HFILL_CODE:
151                         return InsetHFill::isCompatibleCommand(s);
152                 case HYPERLINK_CODE:
153                         return InsetHyperlink::isCompatibleCommand(s);
154                 case INCLUDE_CODE:
155                         return InsetInclude::isCompatibleCommand(s);
156                 case INDEX_PRINT_CODE:
157                         return InsetPrintIndex::isCompatibleCommand(s);
158                 case LABEL_CODE:
159                         return InsetLabel::isCompatibleCommand(s);
160                 case NOMENCL_CODE:
161                         return InsetNomencl::isCompatibleCommand(s);
162                 case NOMENCL_PRINT_CODE:
163                         return InsetPrintNomencl::isCompatibleCommand(s);
164                 case REF_CODE:
165                         return InsetRef::isCompatibleCommand(s);
166                 case TOC_CODE:
167                         return InsetTOC::isCompatibleCommand(s);
168                 default:
169                         BOOST_ASSERT(false);
170         }
171         return false; //silence the warning
172 }
173
174
175 void InsetCommandParams::setCmdName(string const & name)
176 {
177         if (!isCompatibleCommand(insetCode_, cmdName_)){
178                 LYXERR0("InsetCommand: Incompatible command name " << 
179                                 name << ".");
180                 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
181                                        _("Incompatible command name."));
182         }
183
184         cmdName_ = name;
185         CommandInfo const * const info = findInfo(insetCode_, cmdName_);
186         if (!info) {
187                 LYXERR0("Command '" << name << "' is not compatible with a '" <<
188                         insetType() << "' inset.");
189                 return;
190         }
191         ParamVector params(info->n);
192         // Overtake parameters with the same name
193         for (size_t i = 0; i < info_->n; ++i) {
194                 int j = findToken(info->paramnames, info_->paramnames[i]);
195                 if (j >= 0)
196                         params[j] = params_[i];
197         }
198         info_ = info;
199         swap(params, params_);
200 }
201
202
203 void InsetCommandParams::read(Lexer & lex)
204 {
205         if (lex.isOK()) {
206                 lex.next();
207                 string const insetType = lex.getString();
208                 InsetCode const code = insetCode(insetType);
209                 if (code != insetCode_) {
210                         lex.printError("InsetCommandParams: Attempt to change type of inset.");
211                         throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
212                                          _("Attempt to change type of parameters."));
213                 }
214         }
215
216         if (lex.isOK()) {
217                 lex.next();
218                 string const test = lex.getString();
219                 if (test != "LatexCommand") {
220                         lex.printError("InsetCommandParams: No LatexCommand line found.");
221                         throw ExceptionMessage(WarningException, _("InsetCommandParams error:"),
222                                                _("Can't find LatexCommand line."));
223                 }
224         }
225         lex.next();
226         cmdName_ = lex.getString();
227         if (!isCompatibleCommand(insetCode_, cmdName_)){
228                 lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + ".");
229                 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
230                                        _("Incompatible command name."));
231         }
232
233         info_ = findInfo(insetCode_, cmdName_);
234         if (!info_) {
235                 lex.printError("InsetCommandParams: Unknown inset name `$$Token'");
236                 throw ExceptionMessage(WarningException,
237                                        _("Unknown inset name: "), from_utf8(insetType()));
238         }
239         
240         string token;
241         while (lex.isOK()) {
242                 lex.next();
243                 token = lex.getString();
244                 if (token == "\\end_inset")
245                         break;
246                 if (token == "preview") {
247                         lex.next();
248                         preview_ = lex.getBool();
249                         continue;
250                 }
251                 int const i = findToken(info_->paramnames, token);
252                 if (i >= 0) {
253                         lex.next(true);
254                         params_[i] = lex.getDocString();
255                 } else {
256                         lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
257                         throw ExceptionMessage(WarningException,
258                                 _("InsetCommandParams: ") + from_ascii(cmdName_),
259                                 _("Unknown parameter name: ") + from_utf8(token));
260                 }
261         }
262         if (token != "\\end_inset") {
263                 lex.printError("Missing \\end_inset at this point. "
264                                "Read: `$$Token'");
265                 throw ExceptionMessage(WarningException,
266                         _("Missing \\end_inset at this point."),
267                         from_utf8(token));
268         }
269 }
270
271
272 void InsetCommandParams::write(ostream & os) const
273 {
274         os << "CommandInset " << insetType() << '\n';
275         os << "LatexCommand " << cmdName_ << '\n';
276         if (preview_)
277                 os << "preview true\n";
278         for (size_t i = 0; i < info_->n; ++i)
279                 if (!params_[i].empty())
280                         // FIXME UNICODE
281                         os << info_->paramnames[i] << ' '
282                            << Lexer::quoteString(to_utf8(params_[i]))
283                            << '\n';
284 }
285
286
287 docstring const InsetCommandParams::getCommand() const
288 {
289         docstring s = '\\' + from_ascii(cmdName_);
290         bool noparam = true;
291         for (size_t i = 0; i < info_->n; ++i) {
292                 if (info_->optional[i]) {
293                         if (params_[i].empty()) {
294                                 // We need to write this parameter even if
295                                 // it is empty if nonempty optional parameters
296                                 // follow before the next required parameter.
297                                 for (size_t j = i + 1; j < info_->n; ++j) {
298                                         if (!info_->optional[j])
299                                                 break;
300                                         if (!params_[j].empty()) {
301                                                 s += "[]";
302                                                 noparam = false;
303                                                 break;
304                                         }
305                                 }
306                         } else {
307                                 s += '[' + params_[i] + ']';
308                                 noparam = false;
309                         }
310                 } else {
311                         s += '{' + params_[i] + '}';
312                         noparam = false;
313                 }
314         }
315         if (noparam)
316                 // Make sure that following stuff does not change the
317                 // command name.
318                 s += "{}";
319         return s;
320 }
321
322
323 docstring const InsetCommandParams::getFirstNonOptParam() const
324 {
325         for (size_t i = 0; i < info_->n; ++i)
326                 if (!info_->optional[i])
327                         return params_[i];
328         BOOST_ASSERT(false);
329         return docstring();
330 }
331
332
333 docstring const & InsetCommandParams::operator[](string const & name) const
334 {
335         int const i = findToken(info_->paramnames, name);
336         BOOST_ASSERT(i >= 0);
337         return params_[i];
338 }
339
340
341 docstring & InsetCommandParams::operator[](string const & name)
342 {
343         int const i = findToken(info_->paramnames, name);
344         BOOST_ASSERT(i >= 0);
345         return params_[i];
346 }
347
348
349 void InsetCommandParams::clear()
350 {
351         for (size_t i = 0; i < info_->n; ++i)
352                 params_[i].clear();
353 }
354
355
356 bool operator==(InsetCommandParams const & o1,
357                 InsetCommandParams const & o2)
358 {
359         return o1.insetCode_ == o2.insetCode_ &&
360                o1.cmdName_ == o2.cmdName_ &&
361                o1.info_ == o2.info_ &&
362                o1.params_ == o2.params_ &&
363                o1.preview_ == o2.preview_;
364 }
365
366
367 bool operator!=(InsetCommandParams const & o1,
368                 InsetCommandParams const & o2)
369 {
370         return !(o1 == o2);
371 }
372
373
374 } // namespace lyx