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