]> git.lyx.org Git - lyx.git/blob - src/factory.cpp
* Only enter inset which return true on isActive(). This is the behavior in the curso...
[lyx.git] / src / factory.cpp
1 /**
2  * \file factory.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "factory.h"
14
15 #include "Buffer.h"
16 #include "BufferView.h"
17 #include "BufferParams.h"
18 #include "debug.h"
19 #include "FloatList.h"
20 #include "FuncRequest.h"
21 #include "Color.h"
22 #include "Lexer.h"
23 #include "LyX.h"
24 #include "Paragraph.h"
25
26 #include "insets/InsetBibitem.h"
27 #include "insets/InsetBibtex.h"
28 #include "insets/InsetCaption.h"
29 #include "insets/InsetCitation.h"
30 #include "insets/InsetCharStyle.h"
31 #include "insets/InsetEnvironment.h"
32 #include "insets/InsetERT.h"
33 #include "insets/InsetListings.h"
34 #include "insets/InsetExternal.h"
35 #include "insets/InsetFloat.h"
36 #include "insets/InsetFloatList.h"
37 #include "insets/InsetFoot.h"
38 #include "insets/InsetGraphics.h"
39 #include "insets/InsetHFill.h"
40 #include "insets/InsetInclude.h"
41 #include "insets/InsetIndex.h"
42 #include "insets/InsetNomencl.h"
43 #include "insets/InsetLabel.h"
44 #include "insets/InsetLine.h"
45 #include "insets/InsetMarginal.h"
46 #include "insets/InsetNote.h"
47 #include "insets/InsetBox.h"
48 #include "insets/InsetBranch.h"
49 #include "insets/InsetOptArg.h"
50 #include "insets/InsetPagebreak.h"
51 #include "insets/InsetRef.h"
52 #include "insets/InsetSpace.h"
53 #include "insets/InsetTabular.h"
54 #include "insets/InsetTOC.h"
55 #include "insets/InsetUrl.h"
56 #include "insets/InsetVSpace.h"
57 #include "insets/InsetWrap.h"
58
59 #include "mathed/MathMacroTemplate.h"
60 #include "mathed/InsetMathHull.h"
61
62 #include "frontends/alert.h"
63
64 #include "support/lstrings.h"
65 #include "support/ExceptionMessage.h"
66
67 #include <boost/assert.hpp>
68 #include <boost/current_function.hpp>
69
70 #include <sstream>
71
72
73 namespace lyx {
74
75 namespace Alert = frontend::Alert;
76
77 using support::compare_ascii_no_case;
78
79 using std::auto_ptr;
80 using std::endl;
81 using std::string;
82
83
84 Inset * createInset(BufferView * bv, FuncRequest const & cmd)
85 {
86         BufferParams const & params = bv->buffer()->params();
87
88         try {
89
90                 switch (cmd.action) {
91                 case LFUN_HFILL_INSERT:
92                         return new InsetHFill;
93
94                 case LFUN_LINE_INSERT:
95                         return new InsetLine;
96
97                 case LFUN_PAGEBREAK_INSERT:
98                         return new InsetPagebreak;
99
100                 case LFUN_CLEARPAGE_INSERT:
101                         return new InsetClearPage;
102
103                 case LFUN_CLEARDOUBLEPAGE_INSERT:
104                         return new InsetClearDoublePage;
105
106                 case LFUN_CHARSTYLE_INSERT: {
107                         string s = cmd.getArg(0);
108                         TextClass tclass = params.getTextClass();
109                         CharStyles::iterator found_cs = tclass.charstyle(s);
110                         if (found_cs != tclass.charstyles().end())
111                                 return new InsetCharStyle(params, found_cs);
112                         else
113                                 return new InsetCharStyle(params, s);
114                 }
115
116                 case LFUN_NOTE_INSERT: {
117                         string arg = cmd.getArg(0);
118                         if (arg.empty())
119                                 arg = "Note";
120                         return new InsetNote(params, arg);
121                 }
122
123                 case LFUN_BOX_INSERT: {
124                         string arg = cmd.getArg(0);
125                         if (arg.empty())
126                                 arg = "Boxed";
127                         return new InsetBox(params, arg);
128                 }
129
130                 case LFUN_BRANCH_INSERT: {
131                         docstring arg = cmd.argument();
132                         if (arg.empty())
133                                 arg = from_ascii("none");
134                         return new InsetBranch(params, InsetBranchParams(arg));
135                 }
136
137                 case LFUN_ERT_INSERT:
138                         return new InsetERT(params);
139
140                 case LFUN_LISTING_INSERT:
141                         return new InsetListings(params);
142
143                 case LFUN_FOOTNOTE_INSERT:
144                         return new InsetFoot(params);
145
146                 case LFUN_MARGINALNOTE_INSERT:
147                         return new InsetMarginal(params);
148
149                 case LFUN_OPTIONAL_INSERT:
150                         return new InsetOptArg(params);
151
152                 case LFUN_BIBITEM_INSERT:
153                         return new InsetBibitem(InsetCommandParams("bibitem"));
154
155                 case LFUN_FLOAT_INSERT: {
156                         // check if the float type exists
157                         string const argument = to_utf8(cmd.argument());
158                         if (params.getTextClass().floats().typeExist(argument))
159                                 return new InsetFloat(params, argument);
160                         lyxerr << "Non-existent float type: " << argument << endl;
161                         return 0;
162                 }
163
164                 case LFUN_FLOAT_WIDE_INSERT: {
165                         // check if the float type exists
166                         string const argument = to_utf8(cmd.argument());
167                         if (params.getTextClass().floats().typeExist(argument)) {
168                                 auto_ptr<InsetFloat> p(new InsetFloat(params, argument));
169                                 p->wide(true, params);
170                                 return p.release();
171                         }
172                         lyxerr << "Non-existent float type: " << argument << endl;
173                         return 0;
174                 }
175
176                 case LFUN_WRAP_INSERT: {
177                         string const argument = to_utf8(cmd.argument());
178                         if (argument == "figure")
179                                 return new InsetWrap(params, argument);
180                         lyxerr << "Non-existent floatflt type: " << argument << endl;
181                         return 0;
182                 }
183
184                 case LFUN_INDEX_INSERT: {
185                         // Try and generate a valid index entry.
186                         InsetCommandParams icp("index");
187                         icp["name"] = cmd.argument().empty() ?
188                                 bv->cursor().innerText()->getStringToIndex(bv->cursor()) :
189                                 cmd.argument();
190                         return new InsetIndex(icp);
191                 }
192
193                 case LFUN_NOMENCL_INSERT: {
194                         InsetCommandParams icp("nomenclature");
195                         icp["symbol"] = cmd.argument().empty() ?
196                                 bv->cursor().innerText()->getStringToIndex(bv->cursor()) :
197                                 cmd.argument();
198                         return new InsetNomencl(icp);
199                 }
200
201                 case LFUN_TABULAR_INSERT: {
202                         if (cmd.argument().empty())
203                                 return 0;
204                         std::istringstream ss(to_utf8(cmd.argument()));
205                         int r = 0, c = 0;
206                         ss >> r >> c;
207                         if (r <= 0)
208                                 r = 2;
209                         if (c <= 0)
210                                 c = 2;
211                         return new InsetTabular(*bv->buffer(), r, c);
212                 }
213
214                 case LFUN_CAPTION_INSERT: {
215                         auto_ptr<InsetCaption> inset(new InsetCaption(params));
216                         inset->setAutoBreakRows(true);
217                         inset->setDrawFrame(true);
218                         inset->setFrameColor(Color::captionframe);
219                         return inset.release();
220                 }
221
222                 case LFUN_INDEX_PRINT:
223                         return new InsetPrintIndex(InsetCommandParams("printindex"));
224
225                 case LFUN_NOMENCL_PRINT:
226                         return new InsetPrintNomencl(InsetCommandParams("printnomenclature"));
227
228                 case LFUN_TOC_INSERT:
229                         return new InsetTOC(InsetCommandParams("tableofcontents"));
230
231                 case LFUN_ENVIRONMENT_INSERT:
232                         return new InsetEnvironment(params, to_utf8(cmd.argument()));
233
234 #if 0
235                 case LFUN_LIST_INSERT:
236                         return new InsetList;
237
238                 case LFUN_THEOREM_INSERT:
239                         return new InsetTheorem;
240 #endif
241
242                 case LFUN_INSET_INSERT: {
243                         string const name = cmd.getArg(0);
244
245                         if (name == "bibitem") {
246                                 InsetCommandParams icp(name);
247                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
248                                         icp);
249                                 return new InsetBibitem(icp);
250
251                         } else if (name == "bibtex") {
252                                 InsetCommandParams icp(name);
253                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
254                                         icp);
255                                 return new InsetBibtex(icp);
256
257                         } else if (name == "citation") {
258                                 InsetCommandParams icp("cite");
259                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
260                                         icp);
261                                 return new InsetCitation(icp);
262
263                         } else if (name == "ert") {
264                                 InsetCollapsable::CollapseStatus st;
265                                 InsetERTMailer::string2params(to_utf8(cmd.argument()), st);
266                                 return new InsetERT(params, st);
267
268                         } else if (name == "listings") {
269                                 InsetListingsParams par;
270                                 InsetListingsMailer::string2params(to_utf8(cmd.argument()), par);
271                                 return new InsetListings(params, par);
272
273                         } else if (name == "external") {
274                                 Buffer const & buffer = *bv->buffer();
275                                 InsetExternalParams iep;
276                                 InsetExternalMailer::string2params(to_utf8(cmd.argument()),
277                                         buffer, iep);
278                                 auto_ptr<InsetExternal> inset(new InsetExternal);
279                                 inset->setParams(iep, buffer);
280                                 return inset.release();
281
282                         } else if (name == "graphics") {
283                                 Buffer const & buffer = *bv->buffer();
284                                 InsetGraphicsParams igp;
285                                 InsetGraphicsMailer::string2params(to_utf8(cmd.argument()),
286                                         buffer, igp);
287                                 auto_ptr<InsetGraphics> inset(new InsetGraphics);
288                                 inset->setParams(igp);
289                                 return inset.release();
290
291                         } else if (name == "include") {
292                                 InsetCommandParams iip(name);
293                                 InsetIncludeMailer::string2params(to_utf8(cmd.argument()), iip);
294                                 return new InsetInclude(iip);
295
296                         } else if (name == "index") {
297                                 InsetCommandParams icp(name);
298                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
299                                         icp);
300                                 return new InsetIndex(icp);
301
302                         } else if (name == "nomenclature") {
303                                 InsetCommandParams icp(name);
304                                 InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
305                                         icp);
306                                 return new InsetNomencl(icp);
307
308                         } else if (name == "label") {
309                                 InsetCommandParams icp(name);
310                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
311                                         icp);
312                                 return new InsetLabel(icp);
313
314                         } else if (name == "ref") {
315                                 InsetCommandParams icp(name);
316                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
317                                         icp);
318                                 return new InsetRef(icp, *bv->buffer());
319
320                         } else if (name == "toc") {
321                                 InsetCommandParams icp("tableofcontents");
322                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
323                                         icp);
324                                 return new InsetTOC(icp);
325
326                         } else if (name == "url") {
327                                 InsetCommandParams icp(name);
328                                 InsetCommandMailer::string2params(name, to_utf8(cmd.argument()),
329                                         icp);
330                                 return new InsetUrl(icp);
331
332                         } else if (name == "vspace") {
333                                 VSpace vspace;
334                                 InsetVSpaceMailer::string2params(to_utf8(cmd.argument()), vspace);
335                                 return new InsetVSpace(vspace);
336                         }
337                 }
338
339                 case LFUN_SPACE_INSERT: {
340                         string const name = to_utf8(cmd.argument());
341                         if (name == "normal")
342                                 return new InsetSpace(InsetSpace::NORMAL);
343                         else if (name == "protected")
344                                 return new InsetSpace(InsetSpace::PROTECTED);
345                         else if (name == "thin")
346                                 return new InsetSpace(InsetSpace::THIN);
347                         else if (name == "quad")
348                                 return new InsetSpace(InsetSpace::QUAD);
349                         else if (name == "qquad")
350                                 return new InsetSpace(InsetSpace::QQUAD);
351                         else if (name == "enspace")
352                                 return new InsetSpace(InsetSpace::ENSPACE);
353                         else if (name == "enskip")
354                                 return new InsetSpace(InsetSpace::ENSKIP);
355                         else if (name == "negthinspace")
356                                 return new InsetSpace(InsetSpace::NEGTHIN);
357                         else if (name.empty())
358                                 lyxerr << "LyX function 'space' needs an argument." << endl;
359                         else
360                                 lyxerr << "Wrong argument for LyX function 'space'." << endl;
361                 }
362                 break;
363
364                 default:
365                         break;
366                 }
367
368         } catch (support::ExceptionMessage const & message) {
369                 if (message.type_ == support::ErrorException) {
370                         Alert::error(message.title_, message.details_);
371                         LyX::cref().emergencyCleanup();
372                         abort();
373                 } else if (message.type_ == support::WarningException) {
374                         Alert::warning(message.title_, message.details_);
375                         return 0;
376                 }
377         }
378
379
380         return 0;
381 }
382
383
384 Inset * readInset(Lexer & lex, Buffer const & buf)
385 {
386         // consistency check
387         if (lex.getString() != "\\begin_inset") {
388                 lyxerr << "Buffer::readInset: Consistency check failed."
389                        << endl;
390         }
391
392         auto_ptr<Inset> inset;
393
394         TextClass tclass = buf.params().getTextClass();
395
396         lex.next();
397         string tmptok = lex.getString();
398
399         // test the different insets
400         if (tmptok == "LatexCommand") {
401                 lex.next();
402                 string const cmdName = lex.getString();
403                 lex.pushToken(cmdName);
404
405                 InsetCommandParams inscmd(cmdName);
406                 inscmd.read(lex);
407
408                 // This strange command allows LyX to recognize "natbib" style
409                 // citations: citet, citep, Citet etc.
410                 // FIXME: We already have partial support for \\fullcite and
411                 // the various \\footcite commands. We should increase the
412                 // file format number and read these commands here, too.
413                 // Then we should use is_possible_cite_command() in
414                 // src/frontends/controllers/frontend_helpers.cpp to test for valid cite
415                 // commands.
416                 if (compare_ascii_no_case(cmdName.substr(0,4), "cite") == 0) {
417                         inset.reset(new InsetCitation(inscmd));
418                 } else if (cmdName == "bibitem") {
419                         inset.reset(new InsetBibitem(inscmd));
420                 } else if (cmdName == "bibtex") {
421                         inset.reset(new InsetBibtex(inscmd));
422                 } else if (cmdName == "index") {
423                         inset.reset(new InsetIndex(inscmd));
424                 } else if (cmdName == "nomenclature") {
425                         inset.reset(new InsetNomencl(inscmd));
426                 } else if (cmdName == "include") {
427                         inset.reset(new InsetInclude(inscmd));
428                 } else if (cmdName == "label") {
429                         inset.reset(new InsetLabel(inscmd));
430                 } else if (cmdName == "url"
431                            || cmdName == "htmlurl") {
432                         inset.reset(new InsetUrl(inscmd));
433                 } else if (cmdName == "ref"
434                            || cmdName == "eqref"
435                            || cmdName == "pageref"
436                            || cmdName == "vref"
437                            || cmdName == "vpageref"
438                            || cmdName == "prettyref") {
439                         if (!inscmd["name"].empty()
440                             || !inscmd["reference"].empty()) {
441                                 inset.reset(new InsetRef(inscmd, buf));
442                         }
443                 } else if (cmdName == "tableofcontents") {
444                         inset.reset(new InsetTOC(inscmd));
445                 } else if (cmdName == "listofalgorithms") {
446                         inset.reset(new InsetFloatList("algorithm"));
447                 } else if (cmdName == "listoffigures") {
448                         inset.reset(new InsetFloatList("figure"));
449                 } else if (cmdName == "listoftables") {
450                         inset.reset(new InsetFloatList("table"));
451                 } else if (cmdName == "printindex") {
452                         inset.reset(new InsetPrintIndex(inscmd));
453                 } else if (cmdName == "printnomenclature") {
454                         inset.reset(new InsetPrintNomencl(inscmd));
455                 } else {
456                         lyxerr << "unknown CommandInset '" << cmdName
457                                << "'" << std::endl;
458                         while (lex.isOK() && lex.getString() != "\\end_inset")
459                                 lex.next();
460                         return 0;
461                 }
462         } else {
463                 if (tmptok == "Quotes") {
464                         inset.reset(new InsetQuotes);
465                 } else if (tmptok == "External") {
466                         inset.reset(new InsetExternal);
467                 } else if (tmptok == "FormulaMacro") {
468                         inset.reset(new MathMacroTemplate);
469                 } else if (tmptok == "Formula") {
470                         inset.reset(new InsetMathHull);
471                 } else if (tmptok == "Graphics") {
472                         inset.reset(new InsetGraphics);
473                 } else if (tmptok == "Note") {
474                         inset.reset(new InsetNote(buf.params(), tmptok));
475                 } else if (tmptok == "Box") {
476                         inset.reset(new InsetBox(buf.params(), tmptok));
477                 } else if (tmptok == "CharStyle") {
478                         lex.next();
479                         string s = lex.getString();
480                         CharStyles::iterator found_cs = tclass.charstyle(s);
481                         if (found_cs != tclass.charstyles().end())
482                                 inset.reset(new InsetCharStyle(buf.params(), found_cs));
483                         else {
484                                 // "Undefined" inset
485                                 inset.reset(new InsetCharStyle(buf.params(), s));
486                         }
487                 } else if (tmptok == "Branch") {
488                         inset.reset(new InsetBranch(buf.params(),
489                                                     InsetBranchParams()));
490                 } else if (tmptok == "Include") {
491                         InsetCommandParams p("include");
492                         inset.reset(new InsetInclude(p));
493                 } else if (tmptok == "Environment") {
494                         lex.next();
495                         inset.reset(new InsetEnvironment(buf.params(), lex.getString()));
496                 } else if (tmptok == "ERT") {
497                         inset.reset(new InsetERT(buf.params()));
498                 } else if (tmptok == "listings") {
499                         inset.reset(new InsetListings(buf.params()));
500                 } else if (tmptok == "InsetSpace") {
501                         inset.reset(new InsetSpace);
502                 } else if (tmptok == "Tabular") {
503                         inset.reset(new InsetTabular(buf));
504                 } else if (tmptok == "Text") {
505                         inset.reset(new InsetText(buf.params()));
506                 } else if (tmptok == "VSpace") {
507                         inset.reset(new InsetVSpace);
508                 } else if (tmptok == "Foot") {
509                         inset.reset(new InsetFoot(buf.params()));
510                 } else if (tmptok == "Marginal") {
511                         inset.reset(new InsetMarginal(buf.params()));
512                 } else if (tmptok == "OptArg") {
513                         inset.reset(new InsetOptArg(buf.params()));
514                 } else if (tmptok == "Float") {
515                         lex.next();
516                         string tmptok = lex.getString();
517                         inset.reset(new InsetFloat(buf.params(), tmptok));
518                 } else if (tmptok == "Wrap") {
519                         lex.next();
520                         string tmptok = lex.getString();
521                         inset.reset(new InsetWrap(buf.params(), tmptok));
522 #if 0
523                 } else if (tmptok == "List") {
524                         inset.reset(new InsetList);
525                 } else if (tmptok == "Theorem") {
526                         inset.reset(new InsetList);
527 #endif
528                 } else if (tmptok == "Caption") {
529                         inset.reset(new InsetCaption(buf.params()));
530                 } else if (tmptok == "FloatList") {
531                         inset.reset(new InsetFloatList);
532                 } else {
533                         lyxerr << "unknown Inset type '" << tmptok
534                                << "'" << std::endl;
535                         while (lex.isOK() && lex.getString() != "\\end_inset")
536                                 lex.next();
537                         return 0;
538                 }
539
540                 inset->read(buf, lex);
541
542 #ifdef WITH_WARNINGS
543 #warning hack..
544 #endif
545                 if (inset->lyxCode() == Inset::MATHMACRO_CODE) {
546                         MathMacroTemplate const * tmpl =
547                                 static_cast<MathMacroTemplate*>(inset.get());
548                         MacroTable::globalMacros().insert
549                                 (tmpl->name(), tmpl->asMacroData());
550                         LYXERR(Debug::DEBUG)
551                                 << BOOST_CURRENT_FUNCTION
552                                 << ": creating local macro " << to_utf8(tmpl->name())
553                                 << endl;
554                 }
555         }
556
557         return inset.release();
558 }
559
560
561 } // namespace lyx