]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
cosmetics
[lyx.git] / src / BufferParams.cpp
1 /**
2  * \file BufferParams.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author John Levon
10  * \author André Pönitz
11  * \author Martin Vermeer
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "BufferParams.h"
19
20 #include "Author.h"
21 #include "BranchList.h"
22 #include "buffer_funcs.h"
23 #include "Bullet.h"
24 #include "Color.h"
25 #include "debug.h"
26 #include "Encoding.h"
27 #include "gettext.h"
28 #include "Language.h"
29 #include "LaTeXFeatures.h"
30 #include "Messages.h"
31 #include "ModuleList.h"
32 #include "Font.h"
33 #include "Lexer.h"
34 #include "LyXRC.h"
35 #include "TextClassList.h"
36 #include "OutputParams.h"
37 #include "Spacing.h"
38 #include "TexRow.h"
39 #include "VSpace.h"
40 #include "PDFOptions.h"
41
42 #include "frontends/alert.h"
43 #include "insets/InsetListingsParams.h"
44
45 #include "support/convert.h"
46 #include "support/docstream.h"
47 #include "support/filetools.h"
48 #include "support/Translator.h"
49 #include "support/lstrings.h"
50
51 #include <algorithm>
52 #include <sstream>
53
54 using std::count;
55 using std::endl;
56 using std::find;
57 using std::string;
58 using std::istringstream;
59 using std::ostream;
60 using std::ostringstream;
61 using std::pair;
62 using std::string;
63 using lyx::support::FileName;
64 using lyx::support::libFileSearch;
65 using lyx::support::bformat;
66 using lyx::support::rtrim;
67 using lyx::support::tokenPos;
68 using lyx::support::prefixIs;
69
70
71 static char const * const string_paragraph_separation[] = {
72         "indent", "skip", ""
73 };
74
75
76 static char const * const string_quotes_language[] = {
77         "english", "swedish", "german", "polish", "french", "danish", ""
78 };
79
80
81 static char const * const string_papersize[] = {
82         "default", "custom", "letterpaper", "executivepaper", "legalpaper",
83         "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
84 };
85
86
87 static char const * const string_orientation[] = {
88         "portrait", "landscape", ""
89 };
90
91
92 static char const * const string_footnotekinds[] = {
93         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
94 };
95
96
97 static char const * const tex_graphics[] = {
98         "default", "dvips", "dvitops", "emtex",
99         "ln", "oztex", "textures", "none", ""
100 };
101
102
103 namespace lyx {
104
105 // Local translators
106 namespace {
107
108 // Paragraph separation
109 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
110
111
112 ParSepTranslator const init_parseptranslator()
113 {
114         ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
115         translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
116         return translator;
117 }
118
119
120 ParSepTranslator const & parseptranslator()
121 {
122         static ParSepTranslator translator = init_parseptranslator();
123         return translator;
124 }
125
126
127 // Quotes language
128 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
129
130
131 QuotesLangTranslator const init_quoteslangtranslator()
132 {
133         QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
134         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
135         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
136         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
137         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
138         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
139         return translator;
140 }
141
142
143 QuotesLangTranslator const & quoteslangtranslator()
144 {
145         static QuotesLangTranslator translator = init_quoteslangtranslator();
146         return translator;
147 }
148
149
150 // Paper size
151 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
152
153
154 PaperSizeTranslator const init_papersizetranslator()
155 {
156         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
157         translator.addPair(string_papersize[1], PAPER_CUSTOM);
158         translator.addPair(string_papersize[2], PAPER_USLETTER);
159         translator.addPair(string_papersize[3], PAPER_USLEGAL);
160         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
161         translator.addPair(string_papersize[5], PAPER_A3);
162         translator.addPair(string_papersize[6], PAPER_A4);
163         translator.addPair(string_papersize[7], PAPER_A5);
164         translator.addPair(string_papersize[8], PAPER_B3);
165         translator.addPair(string_papersize[9], PAPER_B4);
166         translator.addPair(string_papersize[10], PAPER_B5);
167         return translator;
168 }
169
170
171 PaperSizeTranslator const & papersizetranslator()
172 {
173         static PaperSizeTranslator translator = init_papersizetranslator();
174         return translator;
175 }
176
177
178 // Paper orientation
179 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180
181
182 PaperOrientationTranslator const init_paperorientationtranslator()
183 {
184         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
185         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
186         return translator;
187 }
188
189
190 PaperOrientationTranslator const & paperorientationtranslator()
191 {
192         static PaperOrientationTranslator translator = init_paperorientationtranslator();
193         return translator;
194 }
195
196
197 // Page sides
198 typedef Translator<int, PageSides> SidesTranslator;
199
200
201 SidesTranslator const init_sidestranslator()
202 {
203         SidesTranslator translator(1, OneSide);
204         translator.addPair(2, TwoSides);
205         return translator;
206 }
207
208
209 SidesTranslator const & sidestranslator()
210 {
211         static SidesTranslator translator = init_sidestranslator();
212         return translator;
213 }
214
215
216 // LaTeX packages
217 typedef Translator<int, BufferParams::Package> PackageTranslator;
218
219
220 PackageTranslator const init_packagetranslator()
221 {
222         PackageTranslator translator(0, BufferParams::package_off);
223         translator.addPair(1, BufferParams::package_auto);
224         translator.addPair(2, BufferParams::package_on);
225         return translator;
226 }
227
228
229 PackageTranslator const & packagetranslator()
230 {
231         static PackageTranslator translator = init_packagetranslator();
232         return translator;
233 }
234
235
236 // Cite engine
237 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
238
239
240 CiteEngineTranslator const init_citeenginetranslator()
241 {
242         CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
243         translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
244         translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
245         translator.addPair("jurabib", biblio::ENGINE_JURABIB);
246         return translator;
247 }
248
249
250 CiteEngineTranslator const & citeenginetranslator()
251 {
252         static CiteEngineTranslator translator = init_citeenginetranslator();
253         return translator;
254 }
255
256
257 // Spacing
258 typedef Translator<string, Spacing::Space> SpaceTranslator;
259
260
261 SpaceTranslator const init_spacetranslator()
262 {
263         SpaceTranslator translator("default", Spacing::Default);
264         translator.addPair("single", Spacing::Single);
265         translator.addPair("onehalf", Spacing::Onehalf);
266         translator.addPair("double", Spacing::Double);
267         translator.addPair("other", Spacing::Other);
268         return translator;
269 }
270
271
272 SpaceTranslator const & spacetranslator()
273 {
274         static SpaceTranslator translator = init_spacetranslator();
275         return translator;
276 }
277
278
279 } // anon namespace
280
281
282 class BufferParams::Impl
283 {
284 public:
285         Impl();
286
287         AuthorList authorlist;
288         BranchList branchlist;
289         Bullet temp_bullets[4];
290         Bullet user_defined_bullets[4];
291         Spacing spacing;
292         /** This is the amount of space used for paragraph_separation "skip",
293          * and for detached paragraphs in "indented" documents.
294          */
295         VSpace defskip;
296         PDFOptions pdfoptions;
297 };
298
299
300 BufferParams::Impl::Impl()
301         : defskip(VSpace::MEDSKIP)
302 {
303         // set initial author
304         // FIXME UNICODE
305         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
306 }
307
308
309 BufferParams::Impl *
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
311 {
312         BOOST_ASSERT(ptr);
313
314         return new BufferParams::Impl(*ptr);
315 }
316
317
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
319 {
320         delete ptr;
321 }
322
323
324 BufferParams::BufferParams()
325         : pimpl_(new Impl)
326 {
327         setBaseClass(defaultTextclass());
328         paragraph_separation = PARSEP_INDENT;
329         quotes_language = InsetQuotes::EnglishQ;
330         fontsize = "default";
331
332         /*  PaperLayout */
333         papersize = PAPER_DEFAULT;
334         orientation = ORIENTATION_PORTRAIT;
335         use_geometry = false;
336         use_amsmath = package_auto;
337         use_esint = package_auto;
338         cite_engine_ = biblio::ENGINE_BASIC;
339         use_bibtopic = false;
340         trackChanges = false;
341         outputChanges = false;
342         secnumdepth = 3;
343         tocdepth = 3;
344         language = default_language;
345         fontsRoman = "default";
346         fontsSans = "default";
347         fontsTypewriter = "default";
348         fontsDefaultFamily = "default";
349         fontsSC = false;
350         fontsOSF = false;
351         fontsSansScale = 100;
352         fontsTypewriterScale = 100;
353         inputenc = "auto";
354         graphicsDriver = "default";
355         sides = OneSide;
356         columns = 1;
357         listings_params = string();
358         pagestyle = "default";
359         compressed = false;
360         embedded = false;
361         for (int iter = 0; iter < 4; ++iter) {
362                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
364         }
365 }
366
367
368 BufferParams::~BufferParams()
369 {}
370
371
372 docstring const BufferParams::B_(string const & l10n) const
373 {
374         BOOST_ASSERT(language);
375         return getMessages(language->code()).get(l10n);
376 }
377
378
379 AuthorList & BufferParams::authors()
380 {
381         return pimpl_->authorlist;
382 }
383
384
385 AuthorList const & BufferParams::authors() const
386 {
387         return pimpl_->authorlist;
388 }
389
390
391 BranchList & BufferParams::branchlist()
392 {
393         return pimpl_->branchlist;
394 }
395
396
397 BranchList const & BufferParams::branchlist() const
398 {
399         return pimpl_->branchlist;
400 }
401
402
403 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
404 {
405         BOOST_ASSERT(index < 4);
406         return pimpl_->temp_bullets[index];
407 }
408
409
410 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
411 {
412         BOOST_ASSERT(index < 4);
413         return pimpl_->temp_bullets[index];
414 }
415
416
417 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
418 {
419         BOOST_ASSERT(index < 4);
420         return pimpl_->user_defined_bullets[index];
421 }
422
423
424 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
425 {
426         BOOST_ASSERT(index < 4);
427         return pimpl_->user_defined_bullets[index];
428 }
429
430
431 Spacing & BufferParams::spacing()
432 {
433         return pimpl_->spacing;
434 }
435
436
437 Spacing const & BufferParams::spacing() const
438 {
439         return pimpl_->spacing;
440 }
441
442
443 PDFOptions & BufferParams::pdfoptions()
444 {
445         return pimpl_->pdfoptions;
446 }
447
448
449 PDFOptions const & BufferParams::pdfoptions() const
450 {
451         return pimpl_->pdfoptions;
452 }
453
454
455 VSpace const & BufferParams::getDefSkip() const
456 {
457         return pimpl_->defskip;
458 }
459
460
461 void BufferParams::setDefSkip(VSpace const & vs)
462 {
463         pimpl_->defskip = vs;
464 }
465
466
467 string const BufferParams::readToken(Lexer & lex, string const & token)
468 {
469         if (token == "\\textclass") {
470                 lex.next();
471                 string const classname = lex.getString();
472                 // if there exists a local layout file, ignore the system one
473                 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
474                 pair<bool, lyx::textclass_type> pp = textclasslist.addTextClass(classname, filepath);
475                 if (pp.first)
476                         setBaseClass(pp.second);
477                 else {
478                         pp = textclasslist.numberOfClass(classname);
479                         if (pp.first)
480                                 setBaseClass(pp.second);
481                         else {
482                                 // a warning will be given for unknown class
483                                 setBaseClass(defaultTextclass());
484                                 return classname;
485                         }
486                 }
487                 // FIXME: this warning will be given even if there exists a local .cls
488                 // file. Even worse, the .lyx file can not be compiled or exported
489                 // because the textclass is marked as unavilable.
490                 if (!getTextClass().isTeXClassAvailable()) {
491                         docstring const msg =
492                                 bformat(_("The layout file requested by this document,\n"
493                                                  "%1$s.layout,\n"
494                                                  "is not usable. This is probably because a LaTeX\n"
495                                                  "class or style file required by it is not\n"
496                                                  "available. See the Customization documentation\n"
497                                                  "for more information.\n"), from_utf8(classname));
498                         frontend::Alert::warning(_("Document class not available"),
499                                        msg + _("LyX will not be able to produce output."));
500                 } 
501                 
502         } else if (token == "\\begin_preamble") {
503                 readPreamble(lex);
504         } else if (token == "\\begin_modules") {
505                 readModules(lex);
506                 makeTextClass();
507         } else if (token == "\\options") {
508                 lex.eatLine();
509                 options = lex.getString();
510         } else if (token == "\\language") {
511                 readLanguage(lex);
512         } else if (token == "\\inputencoding") {
513                 lex >> inputenc;
514         } else if (token == "\\graphics") {
515                 readGraphicsDriver(lex);
516         } else if (token == "\\font_roman") {
517                 lex >> fontsRoman;
518         } else if (token == "\\font_sans") {
519                 lex >> fontsSans;
520         } else if (token == "\\font_typewriter") {
521                 lex >> fontsTypewriter;
522         } else if (token == "\\font_default_family") {
523                 lex >> fontsDefaultFamily;
524         } else if (token == "\\font_sc") {
525                 lex >> fontsSC;
526         } else if (token == "\\font_osf") {
527                 lex >> fontsOSF;
528         } else if (token == "\\font_sf_scale") {
529                 lex >> fontsSansScale;
530         } else if (token == "\\font_tt_scale") {
531                 lex >> fontsTypewriterScale;
532         } else if (token == "\\paragraph_separation") {
533                 string parsep;
534                 lex >> parsep;
535                 paragraph_separation = parseptranslator().find(parsep);
536         } else if (token == "\\defskip") {
537                 lex.next();
538                 pimpl_->defskip = VSpace(lex.getString());
539         } else if (token == "\\quotes_language") {
540                 string quotes_lang;
541                 lex >> quotes_lang;
542                 quotes_language = quoteslangtranslator().find(quotes_lang);
543         } else if (token == "\\papersize") {
544                 string ppsize;
545                 lex >> ppsize;
546                 papersize = papersizetranslator().find(ppsize);
547         } else if (token == "\\use_geometry") {
548                 lex >> use_geometry;
549         } else if (token == "\\use_amsmath") {
550                 int use_ams;
551                 lex >> use_ams;
552                 use_amsmath = packagetranslator().find(use_ams);
553         } else if (token == "\\use_esint") {
554                 int useesint;
555                 lex >> useesint;
556                 use_esint = packagetranslator().find(useesint);
557         } else if (token == "\\cite_engine") {
558                 string engine;
559                 lex >> engine;
560                 cite_engine_ = citeenginetranslator().find(engine);
561         } else if (token == "\\use_bibtopic") {
562                 lex >> use_bibtopic;
563         } else if (token == "\\tracking_changes") {
564                 lex >> trackChanges;
565         } else if (token == "\\output_changes") {
566                 lex >> outputChanges;
567         } else if (token == "\\branch") {
568                 lex.next();
569                 docstring branch = lex.getDocString();
570                 branchlist().add(branch);
571                 while (true) {
572                         lex.next();
573                         string const tok = lex.getString();
574                         if (tok == "\\end_branch")
575                                 break;
576                         Branch * branch_ptr = branchlist().find(branch);
577                         if (tok == "\\selected") {
578                                 lex.next();
579                                 if (branch_ptr)
580                                         branch_ptr->setSelected(lex.getInteger());
581                         }
582                         // not yet operational
583                         if (tok == "\\color") {
584                                 lex.eatLine();
585                                 string color = lex.getString();
586                                 if (branch_ptr)
587                                         branch_ptr->setColor(color);
588                                 // Update also the Color table:
589                                 if (color == "none")
590                                         color = lcolor.getX11Name(Color_background);
591                                 // FIXME UNICODE
592                                 lcolor.setColor(to_utf8(branch), color);
593
594                         }
595                 }
596         } else if (token == "\\author") {
597                 lex.eatLine();
598                 istringstream ss(lex.getString());
599                 Author a;
600                 ss >> a;
601                 author_map.push_back(pimpl_->authorlist.record(a));
602         } else if (token == "\\paperorientation") {
603                 string orient;
604                 lex >> orient;
605                 orientation = paperorientationtranslator().find(orient);
606         } else if (token == "\\paperwidth") {
607                 lex >> paperwidth;
608         } else if (token == "\\paperheight") {
609                 lex >> paperheight;
610         } else if (token == "\\leftmargin") {
611                 lex >> leftmargin;
612         } else if (token == "\\topmargin") {
613                 lex >> topmargin;
614         } else if (token == "\\rightmargin") {
615                 lex >> rightmargin;
616         } else if (token == "\\bottommargin") {
617                 lex >> bottommargin;
618         } else if (token == "\\headheight") {
619                 lex >> headheight;
620         } else if (token == "\\headsep") {
621                 lex >> headsep;
622         } else if (token == "\\footskip") {
623                 lex >> footskip;
624         } else if (token == "\\paperfontsize") {
625                 lex >> fontsize;
626         } else if (token == "\\papercolumns") {
627                 lex >> columns;
628         } else if (token == "\\listings_params") {
629                 string par;
630                 lex >> par;
631                 listings_params = InsetListingsParams(par).params();
632         } else if (token == "\\papersides") {
633                 int psides;
634                 lex >> psides;
635                 sides = sidestranslator().find(psides);
636         } else if (token == "\\paperpagestyle") {
637                 lex >> pagestyle;
638         } else if (token == "\\bullet") {
639                 readBullets(lex);
640         } else if (token == "\\bulletLaTeX") {
641                 readBulletsLaTeX(lex);
642         } else if (token == "\\secnumdepth") {
643                 lex >> secnumdepth;
644         } else if (token == "\\tocdepth") {
645                 lex >> tocdepth;
646         } else if (token == "\\spacing") {
647                 string nspacing;
648                 lex >> nspacing;
649                 string tmp_val;
650                 if (nspacing == "other") {
651                         lex >> tmp_val;
652                 }
653                 spacing().set(spacetranslator().find(nspacing), tmp_val);
654         } else if (token == "\\float_placement") {
655                 lex >> float_placement;
656
657         } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
658                 string toktmp = pdfoptions().readToken(lex, token);
659                 if (!toktmp.empty()) {
660                         lyxerr << "PDFOptions::readToken(): Unknown token: " <<
661                                 toktmp << endl;
662                         return toktmp;
663                 }
664         } else {
665                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
666                         token << endl;
667                 return token;
668         }
669
670         return string();
671 }
672
673
674 void BufferParams::writeFile(ostream & os) const
675 {
676         // The top of the file is written by the buffer.
677         // Prints out the buffer info into the .lyx file given by file
678
679         // the textclass
680         os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
681
682         // then the preamble
683         if (!preamble.empty()) {
684                 // remove '\n' from the end of preamble
685                 string const tmppreamble = rtrim(preamble, "\n");
686                 os << "\\begin_preamble\n"
687                    << tmppreamble
688                    << "\n\\end_preamble\n";
689         }
690
691         // the options
692         if (!options.empty()) {
693                 os << "\\options " << options << '\n';
694         }
695         
696         //the modules
697         if (!layoutModules_.empty()) {
698                 os << "\\begin_modules" << '\n';
699                 LayoutModuleList::const_iterator it = layoutModules_.begin();
700                 for (; it != layoutModules_.end(); it++)
701                         os << *it << '\n';
702                 os << "\\end_modules" << '\n';
703         }
704
705         // then the text parameters
706         if (language != ignore_language)
707                 os << "\\language " << language->lang() << '\n';
708         os << "\\inputencoding " << inputenc
709            << "\n\\font_roman " << fontsRoman
710            << "\n\\font_sans " << fontsSans
711            << "\n\\font_typewriter " << fontsTypewriter
712            << "\n\\font_default_family " << fontsDefaultFamily
713            << "\n\\font_sc " << convert<string>(fontsSC)
714            << "\n\\font_osf " << convert<string>(fontsOSF)
715            << "\n\\font_sf_scale " << fontsSansScale
716            << "\n\\font_tt_scale " << fontsTypewriterScale
717            << "\n\\graphics " << graphicsDriver << '\n';
718
719         if (!float_placement.empty()) {
720                 os << "\\float_placement " << float_placement << '\n';
721         }
722         os << "\\paperfontsize " << fontsize << '\n';
723
724         spacing().writeFile(os);
725         pdfoptions().writeFile(os);
726
727         os << "\\papersize " << string_papersize[papersize]
728            << "\n\\use_geometry " << convert<string>(use_geometry)
729            << "\n\\use_amsmath " << use_amsmath
730            << "\n\\use_esint " << use_esint
731            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
732            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
733            << "\n\\paperorientation " << string_orientation[orientation]
734            << '\n';
735
736         BranchList::const_iterator it = branchlist().begin();
737         BranchList::const_iterator end = branchlist().end();
738         for (; it != end; ++it) {
739                 os << "\\branch " << to_utf8(it->getBranch())
740                    << "\n\\selected " << it->getSelected()
741                    << "\n\\color " << lyx::X11hexname(it->getColor())
742                    << "\n\\end_branch"
743                    << "\n";
744         }
745
746         if (!paperwidth.empty())
747                 os << "\\paperwidth "
748                    << VSpace(paperwidth).asLyXCommand() << '\n';
749         if (!paperheight.empty())
750                 os << "\\paperheight "
751                    << VSpace(paperheight).asLyXCommand() << '\n';
752         if (!leftmargin.empty())
753                 os << "\\leftmargin "
754                    << VSpace(leftmargin).asLyXCommand() << '\n';
755         if (!topmargin.empty())
756                 os << "\\topmargin "
757                    << VSpace(topmargin).asLyXCommand() << '\n';
758         if (!rightmargin.empty())
759                 os << "\\rightmargin "
760                    << VSpace(rightmargin).asLyXCommand() << '\n';
761         if (!bottommargin.empty())
762                 os << "\\bottommargin "
763                    << VSpace(bottommargin).asLyXCommand() << '\n';
764         if (!headheight.empty())
765                 os << "\\headheight "
766                    << VSpace(headheight).asLyXCommand() << '\n';
767         if (!headsep.empty())
768                 os << "\\headsep "
769                    << VSpace(headsep).asLyXCommand() << '\n';
770         if (!footskip.empty())
771                 os << "\\footskip "
772                    << VSpace(footskip).asLyXCommand() << '\n';
773         os << "\\secnumdepth " << secnumdepth
774            << "\n\\tocdepth " << tocdepth
775            << "\n\\paragraph_separation "
776            << string_paragraph_separation[paragraph_separation]
777            << "\n\\defskip " << getDefSkip().asLyXCommand()
778            << "\n\\quotes_language "
779            << string_quotes_language[quotes_language]
780            << "\n\\papercolumns " << columns
781            << "\n\\papersides " << sides
782            << "\n\\paperpagestyle " << pagestyle << '\n';
783         if (!listings_params.empty())
784                 os << "\\listings_params \"" <<
785                         InsetListingsParams(listings_params).encodedString() << "\"\n";
786         for (int i = 0; i < 4; ++i) {
787                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
788                         if (user_defined_bullet(i).getFont() != -1) {
789                                 os << "\\bullet " << i << " "
790                                    << user_defined_bullet(i).getFont() << " "
791                                    << user_defined_bullet(i).getCharacter() << " "
792                                    << user_defined_bullet(i).getSize() << "\n";
793                         }
794                         else {
795                                 // FIXME UNICODE
796                                 os << "\\bulletLaTeX " << i << " \""
797                                    << lyx::to_ascii(user_defined_bullet(i).getText())
798                                    << "\"\n";
799                         }
800                 }
801         }
802
803         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
804         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
805
806         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
807         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
808         for (; a_it != a_end; ++a_it) {
809                 if (a_it->second.used())
810                         os << "\\author " << a_it->second << "\n";
811                 else
812                         os << "\\author " << Author() << "\n";
813         }
814 }
815
816
817 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
818                               TexRow & texrow) const
819 {
820         os << "\\documentclass";
821
822         TextClass const & tclass = getTextClass();
823
824         ostringstream clsoptions; // the document class options.
825
826         if (tokenPos(tclass.opt_fontsize(),
827                      '|', fontsize) >= 0) {
828                 // only write if existing in list (and not default)
829                 clsoptions << fontsize << "pt,";
830         }
831
832         // custom, A3, B3 and B4 paper sizes need geometry
833         bool nonstandard_papersize = papersize == PAPER_B3
834                 || papersize == PAPER_B4
835                 || papersize == PAPER_A3
836                 || papersize == PAPER_CUSTOM;
837
838         if (!use_geometry) {
839                 switch (papersize) {
840                 case PAPER_A4:
841                         clsoptions << "a4paper,";
842                         break;
843                 case PAPER_USLETTER:
844                         clsoptions << "letterpaper,";
845                         break;
846                 case PAPER_A5:
847                         clsoptions << "a5paper,";
848                         break;
849                 case PAPER_B5:
850                         clsoptions << "b5paper,";
851                         break;
852                 case PAPER_USEXECUTIVE:
853                         clsoptions << "executivepaper,";
854                         break;
855                 case PAPER_USLEGAL:
856                         clsoptions << "legalpaper,";
857                         break;
858                 case PAPER_DEFAULT:
859                 case PAPER_A3:
860                 case PAPER_B3:
861                 case PAPER_B4:
862                 case PAPER_CUSTOM:
863                         break;
864                 }
865         }
866
867         // if needed
868         if (sides != tclass.sides()) {
869                 switch (sides) {
870                 case OneSide:
871                         clsoptions << "oneside,";
872                         break;
873                 case TwoSides:
874                         clsoptions << "twoside,";
875                         break;
876                 }
877         }
878
879         // if needed
880         if (columns != tclass.columns()) {
881                 if (columns == 2)
882                         clsoptions << "twocolumn,";
883                 else
884                         clsoptions << "onecolumn,";
885         }
886
887         if (!use_geometry
888             && orientation == ORIENTATION_LANDSCAPE)
889                 clsoptions << "landscape,";
890
891         // language should be a parameter to \documentclass
892         if (language->babel() == "hebrew"
893             && default_language->babel() != "hebrew")
894                 // This seems necessary
895                 features.useLanguage(default_language);
896
897         ostringstream language_options;
898         bool const use_babel = features.useBabel();
899         if (use_babel) {
900                 language_options << features.getLanguages();
901                 if (!language->babel().empty()) {
902                         if (!language_options.str().empty())
903                                 language_options << ',';
904                         language_options << language->babel();
905                 }
906                 // when Vietnamese is used, babel must directly be loaded with the
907                 // language options, not in the class options, see
908                 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
909                 size_t viet = language_options.str().find("vietnam");
910                 // viet = string::npos when not found
911                 if (lyxrc.language_global_options && !language_options.str().empty()
912                         && viet == string::npos)
913                         clsoptions << language_options.str() << ',';
914         }
915
916         // the user-defined options
917         if (!options.empty()) {
918                 clsoptions << options << ',';
919         }
920
921         string strOptions(clsoptions.str());
922         if (!strOptions.empty()) {
923                 strOptions = rtrim(strOptions, ",");
924                 // FIXME UNICODE
925                 os << '[' << from_utf8(strOptions) << ']';
926         }
927
928         os << '{' << from_ascii(tclass.latexname()) << "}\n";
929         texrow.newline();
930         // end of \documentclass defs
931
932         // font selection must be done before loading fontenc.sty
933         string const fonts =
934                 loadFonts(fontsRoman, fontsSans,
935                           fontsTypewriter, fontsSC, fontsOSF,
936                           fontsSansScale, fontsTypewriterScale);
937         if (!fonts.empty()) {
938                 os << from_ascii(fonts);
939                 texrow.newline();
940         }
941         if (fontsDefaultFamily != "default")
942                 os << "\\renewcommand{\\familydefault}{\\"
943                    << from_ascii(fontsDefaultFamily) << "}\n";
944
945         // set font encoding
946         // this one is not per buffer
947         // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
948         if (lyxrc.fontenc != "default") {
949                 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
950                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
951                            << ",LFE,LAE]{fontenc}\n";
952                         texrow.newline();
953                 } else {
954                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
955                            << "]{fontenc}\n";
956                         texrow.newline();
957                 }
958         }
959
960         // handle inputenc etc.
961         writeEncodingPreamble(os, features, texrow);
962
963         if (!listings_params.empty()) {
964                 os << "\\usepackage{listings}\n";
965                 texrow.newline();
966                 os << "\\lstset{";
967                 // do not test validity because listings_params is supposed to be valid
968                 string par = InsetListingsParams(listings_params).separatedParams(true);
969                 os << from_ascii(par);
970                 // count the number of newlines
971                 for (size_t i = 0; i < par.size(); ++i)
972                         if (par[i] == '\n')
973                                 texrow.newline();
974                 os << "}\n";
975                 texrow.newline();
976         }
977         if (use_geometry || nonstandard_papersize) {
978                 os << "\\usepackage{geometry}\n";
979                 texrow.newline();
980                 os << "\\geometry{verbose";
981                 if (orientation == ORIENTATION_LANDSCAPE)
982                         os << ",landscape";
983                 switch (papersize) {
984                 case PAPER_CUSTOM:
985                         if (!paperwidth.empty())
986                                 os << ",paperwidth="
987                                    << from_ascii(paperwidth);
988                         if (!paperheight.empty())
989                                 os << ",paperheight="
990                                    << from_ascii(paperheight);
991                         break;
992                 case PAPER_USLETTER:
993                         os << ",letterpaper";
994                         break;
995                 case PAPER_USLEGAL:
996                         os << ",legalpaper";
997                         break;
998                 case PAPER_USEXECUTIVE:
999                         os << ",executivepaper";
1000                         break;
1001                 case PAPER_A3:
1002                         os << ",a3paper";
1003                         break;
1004                 case PAPER_A4:
1005                         os << ",a4paper";
1006                         break;
1007                 case PAPER_A5:
1008                         os << ",a5paper";
1009                         break;
1010                 case PAPER_B3:
1011                         os << ",b3paper";
1012                         break;
1013                 case PAPER_B4:
1014                         os << ",b4paper";
1015                         break;
1016                 case PAPER_B5:
1017                         os << ",b5paper";
1018                         break;
1019                 default:
1020                         // default papersize ie PAPER_DEFAULT
1021                         switch (lyxrc.default_papersize) {
1022                         case PAPER_DEFAULT: // keep compiler happy
1023                         case PAPER_USLETTER:
1024                                 os << ",letterpaper";
1025                                 break;
1026                         case PAPER_USLEGAL:
1027                                 os << ",legalpaper";
1028                                 break;
1029                         case PAPER_USEXECUTIVE:
1030                                 os << ",executivepaper";
1031                                 break;
1032                         case PAPER_A3:
1033                                 os << ",a3paper";
1034                                 break;
1035                         case PAPER_A4:
1036                                 os << ",a4paper";
1037                                 break;
1038                         case PAPER_A5:
1039                                 os << ",a5paper";
1040                                 break;
1041                         case PAPER_B5:
1042                                 os << ",b5paper";
1043                                 break;
1044                         case PAPER_B3:
1045                         case PAPER_B4:
1046                         case PAPER_CUSTOM:
1047                                 break;
1048                         }
1049                 }
1050                 if (!topmargin.empty())
1051                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1052                 if (!bottommargin.empty())
1053                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1054                 if (!leftmargin.empty())
1055                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1056                 if (!rightmargin.empty())
1057                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1058                 if (!headheight.empty())
1059                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1060                 if (!headsep.empty())
1061                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1062                 if (!footskip.empty())
1063                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1064                 os << "}\n";
1065                 texrow.newline();
1066         }
1067
1068         if (tokenPos(tclass.opt_pagestyle(),
1069                      '|', pagestyle) >= 0) {
1070                 if (pagestyle == "fancy") {
1071                         os << "\\usepackage{fancyhdr}\n";
1072                         texrow.newline();
1073                 }
1074                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1075                 texrow.newline();
1076         }
1077
1078         // Only if class has a ToC hierarchy
1079         if (tclass.hasTocLevels()) {
1080                 if (secnumdepth != tclass.secnumdepth()) {
1081                         os << "\\setcounter{secnumdepth}{"
1082                            << secnumdepth
1083                            << "}\n";
1084                         texrow.newline();
1085                 }
1086                 if (tocdepth != tclass.tocdepth()) {
1087                         os << "\\setcounter{tocdepth}{"
1088                            << tocdepth
1089                            << "}\n";
1090                         texrow.newline();
1091                 }
1092         }
1093
1094         if (paragraph_separation) {
1095                 switch (getDefSkip().kind()) {
1096                 case VSpace::SMALLSKIP:
1097                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1098                         break;
1099                 case VSpace::MEDSKIP:
1100                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1101                         break;
1102                 case VSpace::BIGSKIP:
1103                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1104                         break;
1105                 case VSpace::LENGTH:
1106                         os << "\\setlength{\\parskip}{"
1107                            << from_utf8(getDefSkip().length().asLatexString())
1108                            << "}\n";
1109                         break;
1110                 default: // should never happen // Then delete it.
1111                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1112                         break;
1113                 }
1114                 texrow.newline();
1115
1116                 os << "\\setlength{\\parindent}{0pt}\n";
1117                 texrow.newline();
1118         }
1119
1120         // If we use jurabib, we have to call babel here.
1121         if (use_babel && features.isRequired("jurabib")) {
1122                 os << from_ascii(babelCall(language_options.str()))
1123                    << '\n'
1124                    << from_ascii(features.getBabelOptions());
1125                 texrow.newline();
1126         }
1127
1128         // Now insert the LyX specific LaTeX commands...
1129
1130         // The optional packages;
1131         docstring lyxpreamble(from_ascii(features.getPackages()));
1132
1133         // We try to load babel late, in case it interferes
1134         // with other packages. But some packages also need babel to be loaded
1135         // before, e.g. jurabib has to be called after babel.
1136         // So load babel after the optional packages but before the user-defined
1137         // preamble. This allows the users to redefine babel commands, e.g. to
1138         // translate the word "Index" to the German "Stichwortverzeichnis".
1139         // For more infos why this place was chosen, see
1140         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128425.html
1141         // If you encounter problems, you can shift babel to its old place behind
1142         // the user-defined preamble. But in this case you must change the Vietnamese
1143         // support from currently "\usepackage[vietnamese]{babel}" to:
1144         // \usepackage{vietnamese}
1145         // \usepackage{babel}
1146         // because vietnamese must be loaded before hyperref
1147         if (use_babel && !features.isRequired("jurabib")) {
1148                 // FIXME UNICODE
1149                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1150                 lyxpreamble += from_utf8(features.getBabelOptions());
1151         }
1152
1153         // When the language "japanese-plain" is used, the package "japanese" must
1154         // be loaded behind babel (it provides babel support for Japanese) but before
1155         // hyperref, see
1156         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1157         if (language->lang() == "japanese-plain" &&
1158                 !getTextClass().provides("japanese")) {
1159                 //load babel in case it was not loaded due to an empty language list
1160                 if (language_options.str().empty())
1161                         lyxpreamble += "\\usepackage{babel}\n";
1162                 lyxpreamble += "\\usepackage{japanese}\n";
1163         }
1164
1165         // PDF support.
1166         // * Hyperref manual: "Make sure it comes last of your loaded
1167         //   packages, to give it a fighting chance of not being over-written,
1168         //   since its job is to redefine many LATEX commands."
1169         // * Email from Heiko Oberdiek: "It is usually better to load babel
1170         //   before hyperref. Then hyperref has a chance to detect babel.
1171         // * Has to be loaded before the "LyX specific LaTeX commands" to
1172         //   avoid errors with algorithm floats.
1173         odocstringstream oss;
1174         // use hyperref explicitely when it is required
1175         pdfoptions().writeLaTeX(oss, features.isRequired("hyperref"));
1176         lyxpreamble += oss.str();
1177
1178         // this might be useful...
1179         lyxpreamble += "\n\\makeatletter\n";
1180
1181         // Some macros LyX will need
1182         docstring tmppreamble(from_ascii(features.getMacros()));
1183
1184         if (!tmppreamble.empty()) {
1185                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1186                         "LyX specific LaTeX commands.\n"
1187                         + tmppreamble + '\n';
1188         }
1189
1190         // the text class specific preamble
1191         tmppreamble = features.getTClassPreamble();
1192         if (!tmppreamble.empty()) {
1193                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1194                         "Textclass specific LaTeX commands.\n"
1195                         + tmppreamble + '\n';
1196         }
1197
1198         /* the user-defined preamble */
1199         if (!preamble.empty()) {
1200                 // FIXME UNICODE
1201                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1202                         "User specified LaTeX commands.\n"
1203                         + from_utf8(preamble) + '\n';
1204         }
1205
1206         // Itemize bullet settings need to be last in case the user
1207         // defines their own bullets that use a package included
1208         // in the user-defined preamble -- ARRae
1209         // Actually it has to be done much later than that
1210         // since some packages like frenchb make modifications
1211         // at \begin{document} time -- JMarc
1212         docstring bullets_def;
1213         for (int i = 0; i < 4; ++i) {
1214                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1215                         if (bullets_def.empty())
1216                                 bullets_def += "\\AtBeginDocument{\n";
1217                         bullets_def += "  \\def\\labelitemi";
1218                         switch (i) {
1219                                 // `i' is one less than the item to modify
1220                         case 0:
1221                                 break;
1222                         case 1:
1223                                 bullets_def += 'i';
1224                                 break;
1225                         case 2:
1226                                 bullets_def += "ii";
1227                                 break;
1228                         case 3:
1229                                 bullets_def += 'v';
1230                                 break;
1231                         }
1232                         bullets_def += '{' +
1233                                 user_defined_bullet(i).getText()
1234                                 + "}\n";
1235                 }
1236         }
1237
1238         if (!bullets_def.empty())
1239                 lyxpreamble += bullets_def + "}\n\n";
1240
1241         lyxpreamble += "\\makeatother\n\n";
1242
1243         int const nlines =
1244                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1245         for (int j = 0; j != nlines; ++j) {
1246                 texrow.newline();
1247         }
1248
1249         os << lyxpreamble;
1250         return use_babel;
1251 }
1252
1253
1254 void BufferParams::useClassDefaults()
1255 {
1256         TextClass const & tclass = textclasslist[baseClass_];
1257
1258         sides = tclass.sides();
1259         columns = tclass.columns();
1260         pagestyle = tclass.pagestyle();
1261         options = tclass.options();
1262         // Only if class has a ToC hierarchy
1263         if (tclass.hasTocLevels()) {
1264                 secnumdepth = tclass.secnumdepth();
1265                 tocdepth = tclass.tocdepth();
1266         }
1267 }
1268
1269
1270 bool BufferParams::hasClassDefaults() const
1271 {
1272         TextClass const & tclass = textclasslist[baseClass_];
1273
1274         return (sides == tclass.sides()
1275                 && columns == tclass.columns()
1276                 && pagestyle == tclass.pagestyle()
1277                 && options == tclass.options()
1278                 && secnumdepth == tclass.secnumdepth()
1279                 && tocdepth == tclass.tocdepth());
1280 }
1281
1282
1283 TextClass const & BufferParams::getTextClass() const
1284 {
1285         return *textClass_;
1286 }
1287
1288
1289 TextClassPtr BufferParams::getTextClassPtr() const {
1290         return textClass_;
1291 }
1292
1293
1294 void BufferParams::setTextClass(TextClassPtr tc) {
1295         textClass_ = tc;
1296 }
1297
1298
1299 bool BufferParams::setBaseClass(textclass_type tc)
1300 {
1301         bool retVal = true;
1302         if (textclasslist[tc].load())
1303                 baseClass_ = tc;
1304         else {
1305                 docstring s = 
1306                         bformat(_("The document class %1$s could not be loaded."),
1307                  from_utf8(textclasslist[tc].name()));
1308                 frontend::Alert::error(_("Could not load class"), s);
1309                 retVal = false;
1310         }
1311         makeTextClass();
1312         return retVal;
1313 }
1314
1315
1316 void BufferParams::setJustBaseClass(textclass_type tc)
1317
1318         baseClass_ = tc; 
1319 }
1320
1321
1322 textclass_type BufferParams::getBaseClass() const
1323 {
1324         return baseClass_;
1325 }
1326
1327
1328 void BufferParams::makeTextClass()
1329 {
1330         textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1331         //FIXME It might be worth loading the children's modules here,
1332         //just as we load their bibliographies and such, instead of just 
1333         //doing a check in InsetInclude.
1334         LayoutModuleList::const_iterator it = layoutModules_.begin();
1335         for (; it != layoutModules_.end(); it++) {
1336                 string const modName = *it;
1337                 LyXModule * lm = moduleList[modName];
1338                 if (!lm) {
1339                         docstring const msg =
1340                                 bformat(_("The module %1$s has been requested by\n"
1341                                         "this document but has not been found in the list of\n"
1342                                         "available modules. If you recently installed it, you\n"
1343                                         "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1344                         frontend::Alert::warning(_("Module not available"),
1345                                         msg + _("Some layouts may not be available."));
1346                         lyxerr << "BufferParams::makeTextClass(): Module " <<
1347                                         modName << " requested but not found in module list." <<
1348                                         endl;
1349                         continue;
1350                 }
1351                 FileName layout_file = libFileSearch("layouts", lm->filename);
1352                 textClass_->read(layout_file, TextClass::MODULE);
1353         }
1354 }
1355
1356
1357 std::vector<string> const & BufferParams::getModules() const {
1358         return layoutModules_;
1359 }
1360
1361
1362
1363 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1364         LayoutModuleList::const_iterator it = layoutModules_.begin();
1365         LayoutModuleList::const_iterator end = layoutModules_.end();
1366         for (; it != end; it++) {
1367                 if (*it == modName) 
1368                         break;
1369         }
1370         if (it != layoutModules_.end())
1371                 return false;
1372         layoutModules_.push_back(modName);
1373         if (makeClass)
1374                 makeTextClass();
1375         return true;
1376 }
1377
1378
1379 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1380 {
1381         bool retval = true;
1382         std::vector<string>::const_iterator it = modNames.begin();
1383         std::vector<string>::const_iterator end = modNames.end();
1384         for (; it != end; ++it)
1385                 retval &= addLayoutModule(*it, false);
1386         makeTextClass();
1387         return retval;
1388 }
1389
1390
1391 void BufferParams::clearLayoutModules() {
1392         layoutModules_.clear();
1393         makeTextClass();
1394 }
1395
1396
1397 Font const BufferParams::getFont() const
1398 {
1399         FontInfo f = getTextClass().defaultfont();
1400         if (fontsDefaultFamily == "rmdefault")
1401                 f.setFamily(ROMAN_FAMILY);
1402         else if (fontsDefaultFamily == "sfdefault")
1403                 f.setFamily(SANS_FAMILY);
1404         else if (fontsDefaultFamily == "ttdefault")
1405                 f.setFamily(TYPEWRITER_FAMILY);
1406         return Font(f, language);
1407 }
1408
1409
1410 void BufferParams::readPreamble(Lexer & lex)
1411 {
1412         if (lex.getString() != "\\begin_preamble")
1413                 lyxerr << "Error (BufferParams::readPreamble):"
1414                         "consistency check failed." << endl;
1415
1416         preamble = lex.getLongString("\\end_preamble");
1417 }
1418
1419
1420 void BufferParams::readLanguage(Lexer & lex)
1421 {
1422         if (!lex.next()) return;
1423
1424         string const tmptok = lex.getString();
1425
1426         // check if tmptok is part of tex_babel in tex-defs.h
1427         language = languages.getLanguage(tmptok);
1428         if (!language) {
1429                 // Language tmptok was not found
1430                 language = default_language;
1431                 lyxerr << "Warning: Setting language `"
1432                        << tmptok << "' to `" << language->lang()
1433                        << "'." << endl;
1434         }
1435 }
1436
1437
1438 void BufferParams::readGraphicsDriver(Lexer & lex)
1439 {
1440         if (!lex.next()) return;
1441
1442         string const tmptok = lex.getString();
1443         // check if tmptok is part of tex_graphics in tex_defs.h
1444         int n = 0;
1445         while (true) {
1446                 string const test = tex_graphics[n++];
1447
1448                 if (test == tmptok) {
1449                         graphicsDriver = tmptok;
1450                         break;
1451                 } else if (test == "") {
1452                         lex.printError(
1453                                 "Warning: graphics driver `$$Token' not recognized!\n"
1454                                 "         Setting graphics driver to `default'.\n");
1455                         graphicsDriver = "default";
1456                         break;
1457                 }
1458         }
1459 }
1460
1461
1462 void BufferParams::readBullets(Lexer & lex)
1463 {
1464         if (!lex.next()) return;
1465
1466         int const index = lex.getInteger();
1467         lex.next();
1468         int temp_int = lex.getInteger();
1469         user_defined_bullet(index).setFont(temp_int);
1470         temp_bullet(index).setFont(temp_int);
1471         lex >> temp_int;
1472         user_defined_bullet(index).setCharacter(temp_int);
1473         temp_bullet(index).setCharacter(temp_int);
1474         lex >> temp_int;
1475         user_defined_bullet(index).setSize(temp_int);
1476         temp_bullet(index).setSize(temp_int);
1477 }
1478
1479
1480 void BufferParams::readBulletsLaTeX(Lexer & lex)
1481 {
1482         // The bullet class should be able to read this.
1483         if (!lex.next()) return;
1484         int const index = lex.getInteger();
1485         lex.next(true);
1486         docstring const temp_str = lex.getDocString();
1487
1488         user_defined_bullet(index).setText(temp_str);
1489         temp_bullet(index).setText(temp_str);
1490 }
1491
1492
1493 void BufferParams::readModules(Lexer & lex)
1494 {
1495         if (!lex.eatLine()) {
1496                 lyxerr << "Error (BufferParams::readModules):"
1497                                 "Unexpected end of input." << endl;
1498                 return;
1499         }
1500         while (true) {
1501                 string mod = lex.getString();
1502                 if (mod == "\\end_modules")
1503                         break;
1504                 addLayoutModule(mod);
1505                 lex.eatLine();
1506         }
1507 }
1508
1509
1510 string const BufferParams::paperSizeName() const
1511 {
1512         char real_papersize = papersize;
1513         if (real_papersize == PAPER_DEFAULT)
1514                 real_papersize = lyxrc.default_papersize;
1515
1516         switch (real_papersize) {
1517         case PAPER_A3:
1518                 return "a3";
1519         case PAPER_A4:
1520                 return "a4";
1521         case PAPER_A5:
1522                 return "a5";
1523         case PAPER_B5:
1524                 return "b5";
1525         case PAPER_USEXECUTIVE:
1526                 return "foolscap";
1527         case PAPER_USLEGAL:
1528                 return "legal";
1529         case PAPER_USLETTER:
1530         default:
1531                 return "letter";
1532         }
1533 }
1534
1535
1536 string const BufferParams::dvips_options() const
1537 {
1538         string result;
1539
1540         if (use_geometry
1541             && papersize == PAPER_CUSTOM
1542             && !lyxrc.print_paper_dimension_flag.empty()
1543             && !paperwidth.empty()
1544             && !paperheight.empty()) {
1545                 // using a custom papersize
1546                 result = lyxrc.print_paper_dimension_flag;
1547                 result += ' ' + paperwidth;
1548                 result += ',' + paperheight;
1549         } else {
1550                 string const paper_option = paperSizeName();
1551                 if (paper_option != "letter" ||
1552                     orientation != ORIENTATION_LANDSCAPE) {
1553                         // dvips won't accept -t letter -t landscape.
1554                         // In all other cases, include the paper size
1555                         // explicitly.
1556                         result = lyxrc.print_paper_flag;
1557                         result += ' ' + paper_option;
1558                 }
1559         }
1560         if (orientation == ORIENTATION_LANDSCAPE &&
1561             papersize != PAPER_CUSTOM)
1562                 result += ' ' + lyxrc.print_landscape_flag;
1563         return result;
1564 }
1565
1566
1567 string const BufferParams::babelCall(string const & lang_opts) const
1568 {
1569         string lang_pack = lyxrc.language_package;
1570         if (lang_pack != "\\usepackage{babel}")
1571                 return lang_pack;
1572         // suppress the babel call when there is no babel language defined
1573         // for the document language in the lib/languages file and if no
1574         // other languages are used (lang_opts is then empty)
1575         if (lang_opts.empty())
1576                 return string();
1577         // when Vietnamese is used, babel must directly be loaded with the
1578         // language options, see
1579         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1580         size_t viet = lang_opts.find("vietnam");
1581         // viet = string::npos when not found
1582         if (!lyxrc.language_global_options || viet != string::npos)
1583                 return "\\usepackage[" + lang_opts + "]{babel}";
1584         return lang_pack;
1585 }
1586
1587
1588 void BufferParams::writeEncodingPreamble(odocstream & os,
1589                 LaTeXFeatures & features, TexRow & texrow) const
1590 {
1591         if (inputenc == "auto") {
1592                 string const doc_encoding =
1593                         language->encoding()->latexName();
1594                 Encoding::Package const package =
1595                         language->encoding()->package();
1596
1597                 // Create a list with all the input encodings used
1598                 // in the document
1599                 std::set<string> encodings =
1600                         features.getEncodingSet(doc_encoding);
1601
1602                 // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the
1603                 // package inputenc must be omitted. Therefore set the encoding to empty.
1604                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1605                 if (doc_encoding == "EUC-JP-plain" || doc_encoding == "JIS-plain" ||
1606                         doc_encoding == "SJIS-plain")
1607                         encodings.clear();
1608
1609                 if (!encodings.empty() || package == Encoding::inputenc) {
1610                         os << "\\usepackage[";
1611                         std::set<string>::const_iterator it = encodings.begin();
1612                         std::set<string>::const_iterator const end = encodings.end();
1613                         if (it != end) {
1614                                 os << from_ascii(*it);
1615                                 ++it;
1616                         }
1617                         for (; it != end; ++it)
1618                                 os << ',' << from_ascii(*it);
1619                         if (package == Encoding::inputenc) {
1620                                 if (!encodings.empty())
1621                                         os << ',';
1622                                 os << from_ascii(doc_encoding);
1623                         }
1624                         os << "]{inputenc}\n";
1625                         texrow.newline();
1626                 }
1627                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1628                         os << "\\usepackage{CJK}\n";
1629                         texrow.newline();
1630                 }
1631         } else if (inputenc != "default") {
1632                 switch (encoding().package()) {
1633                 case Encoding::none:
1634                         break;
1635                 case Encoding::inputenc:
1636                         os << "\\usepackage[" << from_ascii(inputenc)
1637                            << "]{inputenc}\n";
1638                         texrow.newline();
1639                         break;
1640                 case Encoding::CJK:
1641                         os << "\\usepackage{CJK}\n";
1642                         texrow.newline();
1643                         break;
1644                 }
1645         }
1646
1647         // The encoding "armscii8" is only available when the package "armtex" is loaded.
1648         // armscii8 is used for Armenian.
1649         if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1650                 os << "\\usepackage{armtex}\n";
1651                 texrow.newline();
1652         }
1653 }
1654
1655
1656 string const BufferParams::loadFonts(string const & rm,
1657                                      string const & sf, string const & tt,
1658                                      bool const & sc, bool const & osf,
1659                                      int const & sfscale, int const & ttscale) const
1660 {
1661         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1662            several packages have been replaced by others, that might not
1663            be installed on every system. We have to take care for that
1664            (see psnfss.pdf). We try to support all psnfss fonts as well
1665            as the fonts that have become de facto standard in the LaTeX
1666            world (e.g. Latin Modern). We do not support obsolete fonts
1667            (like PSLatex). In general, it should be possible to mix any
1668            rm font with any sf or tt font, respectively. (JSpitzm)
1669            TODO:
1670                 -- separate math fonts.
1671         */
1672
1673         if (rm == "default" && sf == "default" && tt == "default")
1674                 //nothing to do
1675                 return string();
1676
1677         ostringstream os;
1678
1679         // ROMAN FONTS
1680         // Computer Modern (must be explicitely selectable -- there might be classes
1681         // that define a different default font!
1682         if (rm == "cmr") {
1683                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1684                 // osf for Computer Modern needs eco.sty
1685                 if (osf)
1686                         os << "\\usepackage{eco}\n";
1687         }
1688         // Latin Modern Roman
1689         else if (rm == "lmodern")
1690                 os << "\\usepackage{lmodern}\n";
1691         // AE
1692         else if (rm == "ae") {
1693                 // not needed when using OT1 font encoding.
1694                 if (lyxrc.fontenc != "default")
1695                         os << "\\usepackage{ae,aecompl}\n";
1696         }
1697         // Times
1698         else if (rm == "times") {
1699                 // try to load the best available package
1700                 if (LaTeXFeatures::isAvailable("mathptmx"))
1701                         os << "\\usepackage{mathptmx}\n";
1702                 else if (LaTeXFeatures::isAvailable("mathptm"))
1703                         os << "\\usepackage{mathptm}\n";
1704                 else
1705                         os << "\\usepackage{times}\n";
1706         }
1707         // Palatino
1708         else if (rm == "palatino") {
1709                 // try to load the best available package
1710                 if (LaTeXFeatures::isAvailable("mathpazo")) {
1711                         os << "\\usepackage";
1712                         if (osf || sc) {
1713                                 os << '[';
1714                                 if (!osf)
1715                                         os << "sc";
1716                                 else
1717                                         // "osf" includes "sc"!
1718                                         os << "osf";
1719                                 os << ']';
1720                         }
1721                         os << "{mathpazo}\n";
1722                 }
1723                 else if (LaTeXFeatures::isAvailable("mathpple"))
1724                         os << "\\usepackage{mathpple}\n";
1725                 else
1726                         os << "\\usepackage{palatino}\n";
1727         }
1728         // Utopia
1729         else if (rm == "utopia") {
1730                 // fourier supersedes utopia.sty, but does
1731                 // not work with OT1 encoding.
1732                 if (LaTeXFeatures::isAvailable("fourier")
1733                     && lyxrc.fontenc != "default") {
1734                         os << "\\usepackage";
1735                         if (osf || sc) {
1736                                 os << '[';
1737                                 if (sc)
1738                                         os << "expert";
1739                                 if (osf && sc)
1740                                         os << ',';
1741                                 if (osf)
1742                                         os << "oldstyle";
1743                                 os << ']';
1744                         }
1745                         os << "{fourier}\n";
1746                 }
1747                 else
1748                         os << "\\usepackage{utopia}\n";
1749         }
1750         // Bera (complete fontset)
1751         else if (rm == "bera" && sf == "default" && tt == "default")
1752                 os << "\\usepackage{bera}\n";
1753         // everything else
1754         else if (rm != "default")
1755                 os << "\\usepackage" << "{" << rm << "}\n";
1756
1757         // SANS SERIF
1758         // Helvetica, Bera Sans
1759         if (sf == "helvet" || sf == "berasans") {
1760                 if (sfscale != 100)
1761                         os << "\\usepackage[scaled=" << float(sfscale) / 100
1762                            << "]{" << sf << "}\n";
1763                 else
1764                         os << "\\usepackage{" << sf << "}\n";
1765         }
1766         // Avant Garde
1767         else if (sf == "avant")
1768                 os << "\\usepackage{" << sf << "}\n";
1769         // Computer Modern, Latin Modern, CM Bright
1770         else if (sf != "default")
1771                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1772
1773         // monospaced/typewriter
1774         // Courier, LuxiMono
1775         if (tt == "luximono" || tt == "beramono") {
1776                 if (ttscale != 100)
1777                         os << "\\usepackage[scaled=" << float(ttscale) / 100
1778                            << "]{" << tt << "}\n";
1779                 else
1780                         os << "\\usepackage{" << tt << "}\n";
1781         }
1782         // Courier
1783         else if (tt == "courier" )
1784                 os << "\\usepackage{" << tt << "}\n";
1785         // Computer Modern, Latin Modern, CM Bright
1786         else if  (tt != "default")
1787                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1788
1789         return os.str();
1790 }
1791
1792
1793 Encoding const & BufferParams::encoding() const
1794 {
1795         if (inputenc == "auto" || inputenc == "default")
1796                 return *(language->encoding());
1797         Encoding const * const enc =
1798                 encodings.getFromLaTeXName(inputenc);
1799         if (enc)
1800                 return *enc;
1801         lyxerr << "Unknown inputenc value `" << inputenc
1802                << "'. Using `auto' instead." << endl;
1803         return *(language->encoding());
1804 }
1805
1806
1807 biblio::CiteEngine BufferParams::getEngine() const
1808 {
1809         // FIXME the class should provide the numerical/
1810         // authoryear choice
1811         if (getTextClass().provides("natbib")
1812             && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1813                 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1814         return cite_engine_;
1815 }
1816
1817
1818 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1819 {
1820         cite_engine_ = cite_engine;
1821 }
1822
1823 } // namespace lyx