]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
BufferParams.cpp: change the package loading to:
[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 "debug.h"
25 #include "Encoding.h"
26 #include "gettext.h"
27 #include "Language.h"
28 #include "LaTeXFeatures.h"
29 #include "Messages.h"
30 #include "ModuleList.h"
31 #include "Color.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/filetools.h"
47 #include "support/Translator.h"
48 #include "support/lstrings.h"
49
50 #include <boost/array.hpp>
51
52 #include <algorithm>
53 #include <sstream>
54
55 using std::count;
56 using std::endl;
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, TextClass::PageSides> SidesTranslator;
199
200
201 SidesTranslator const init_sidestranslator()
202 {
203         SidesTranslator translator(1, TextClass::OneSide);
204         translator.addPair(2, TextClass::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         boost::array<Bullet, 4> temp_bullets;
290         boost::array<Bullet, 4> user_defined_bullets;
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 = TextClass::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                 pair<bool, lyx::textclass_type> pp =
473                         textclasslist.numberOfClass(classname);
474                 if (pp.first) {
475                         setBaseClass(pp.second);
476                 } else {
477                         // if text class does not exist, try to load it from filepath
478                         pp = textclasslist.addTextClass(classname, filepath);
479                         if (pp.first) {
480                                 setBaseClass(pp.second);
481                         } else {
482                                 setBaseClass(defaultTextclass());
483                                 return classname;
484                         }
485                 }
486                 if (!getTextClass().isTeXClassAvailable()) {
487                         docstring const msg =
488                                 bformat(_("The layout file requested by this document,\n"
489                                                  "%1$s.layout,\n"
490                                                  "is not usable. This is probably because a LaTeX\n"
491                                                  "class or style file required by it is not\n"
492                                                  "available. See the Customization documentation\n"
493                                                  "for more information.\n"), from_utf8(classname));
494                         frontend::Alert::warning(_("Document class not available"),
495                                        msg + _("LyX will not be able to produce output."));
496                 } 
497                 
498         } else if (token == "\\begin_preamble") {
499                 readPreamble(lex);
500         } else if (token == "\\begin_modules") {
501                 readModules(lex);
502                 makeTextClass();
503         } else if (token == "\\options") {
504                 lex.eatLine();
505                 options = lex.getString();
506         } else if (token == "\\language") {
507                 readLanguage(lex);
508         } else if (token == "\\inputencoding") {
509                 lex >> inputenc;
510         } else if (token == "\\graphics") {
511                 readGraphicsDriver(lex);
512         } else if (token == "\\font_roman") {
513                 lex >> fontsRoman;
514         } else if (token == "\\font_sans") {
515                 lex >> fontsSans;
516         } else if (token == "\\font_typewriter") {
517                 lex >> fontsTypewriter;
518         } else if (token == "\\font_default_family") {
519                 lex >> fontsDefaultFamily;
520         } else if (token == "\\font_sc") {
521                 lex >> fontsSC;
522         } else if (token == "\\font_osf") {
523                 lex >> fontsOSF;
524         } else if (token == "\\font_sf_scale") {
525                 lex >> fontsSansScale;
526         } else if (token == "\\font_tt_scale") {
527                 lex >> fontsTypewriterScale;
528         } else if (token == "\\paragraph_separation") {
529                 string parsep;
530                 lex >> parsep;
531                 paragraph_separation = parseptranslator().find(parsep);
532         } else if (token == "\\defskip") {
533                 lex.next();
534                 pimpl_->defskip = VSpace(lex.getString());
535         } else if (token == "\\quotes_language") {
536                 string quotes_lang;
537                 lex >> quotes_lang;
538                 quotes_language = quoteslangtranslator().find(quotes_lang);
539         } else if (token == "\\papersize") {
540                 string ppsize;
541                 lex >> ppsize;
542                 papersize = papersizetranslator().find(ppsize);
543         } else if (token == "\\use_geometry") {
544                 lex >> use_geometry;
545         } else if (token == "\\use_amsmath") {
546                 int use_ams;
547                 lex >> use_ams;
548                 use_amsmath = packagetranslator().find(use_ams);
549         } else if (token == "\\use_esint") {
550                 int useesint;
551                 lex >> useesint;
552                 use_esint = packagetranslator().find(useesint);
553         } else if (token == "\\cite_engine") {
554                 string engine;
555                 lex >> engine;
556                 cite_engine_ = citeenginetranslator().find(engine);
557         } else if (token == "\\use_bibtopic") {
558                 lex >> use_bibtopic;
559         } else if (token == "\\tracking_changes") {
560                 lex >> trackChanges;
561         } else if (token == "\\output_changes") {
562                 lex >> outputChanges;
563         } else if (token == "\\branch") {
564                 lex.next();
565                 docstring branch = lex.getDocString();
566                 branchlist().add(branch);
567                 while (true) {
568                         lex.next();
569                         string const tok = lex.getString();
570                         if (tok == "\\end_branch")
571                                 break;
572                         Branch * branch_ptr = branchlist().find(branch);
573                         if (tok == "\\selected") {
574                                 lex.next();
575                                 if (branch_ptr)
576                                         branch_ptr->setSelected(lex.getInteger());
577                         }
578                         // not yet operational
579                         if (tok == "\\color") {
580                                 lex.eatLine();
581                                 string color = lex.getString();
582                                 if (branch_ptr)
583                                         branch_ptr->setColor(color);
584                                 // Update also the Color table:
585                                 if (color == "none")
586                                         color = lcolor.getX11Name(Color::background);
587                                 // FIXME UNICODE
588                                 lcolor.setColor(to_utf8(branch), color);
589
590                         }
591                 }
592         } else if (token == "\\author") {
593                 lex.eatLine();
594                 istringstream ss(lex.getString());
595                 Author a;
596                 ss >> a;
597                 author_map.push_back(pimpl_->authorlist.record(a));
598         } else if (token == "\\paperorientation") {
599                 string orient;
600                 lex >> orient;
601                 orientation = paperorientationtranslator().find(orient);
602         } else if (token == "\\paperwidth") {
603                 lex >> paperwidth;
604         } else if (token == "\\paperheight") {
605                 lex >> paperheight;
606         } else if (token == "\\leftmargin") {
607                 lex >> leftmargin;
608         } else if (token == "\\topmargin") {
609                 lex >> topmargin;
610         } else if (token == "\\rightmargin") {
611                 lex >> rightmargin;
612         } else if (token == "\\bottommargin") {
613                 lex >> bottommargin;
614         } else if (token == "\\headheight") {
615                 lex >> headheight;
616         } else if (token == "\\headsep") {
617                 lex >> headsep;
618         } else if (token == "\\footskip") {
619                 lex >> footskip;
620         } else if (token == "\\paperfontsize") {
621                 lex >> fontsize;
622         } else if (token == "\\papercolumns") {
623                 lex >> columns;
624         } else if (token == "\\listings_params") {
625                 string par;
626                 lex >> par;
627                 listings_params = InsetListingsParams(par).params();
628         } else if (token == "\\papersides") {
629                 int psides;
630                 lex >> psides;
631                 sides = sidestranslator().find(psides);
632         } else if (token == "\\paperpagestyle") {
633                 lex >> pagestyle;
634         } else if (token == "\\bullet") {
635                 readBullets(lex);
636         } else if (token == "\\bulletLaTeX") {
637                 readBulletsLaTeX(lex);
638         } else if (token == "\\secnumdepth") {
639                 lex >> secnumdepth;
640         } else if (token == "\\tocdepth") {
641                 lex >> tocdepth;
642         } else if (token == "\\spacing") {
643                 string nspacing;
644                 lex >> nspacing;
645                 string tmp_val;
646                 if (nspacing == "other") {
647                         lex >> tmp_val;
648                 }
649                 spacing().set(spacetranslator().find(nspacing), tmp_val);
650         } else if (token == "\\float_placement") {
651                 lex >> float_placement;
652
653         } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
654                 string toktmp = pdfoptions().readToken(lex, token);
655                 if (!toktmp.empty()) {
656                         lyxerr << "PDFOptions::readToken(): Unknown token: " <<
657                                 toktmp << endl;
658                         return toktmp;
659                 }
660         } else {
661                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
662                         token << endl;
663                 return token;
664         }
665
666         return string();
667 }
668
669
670 void BufferParams::writeFile(ostream & os) const
671 {
672         // The top of the file is written by the buffer.
673         // Prints out the buffer info into the .lyx file given by file
674
675         // the textclass
676         os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
677
678         // then the preamble
679         if (!preamble.empty()) {
680                 // remove '\n' from the end of preamble
681                 string const tmppreamble = rtrim(preamble, "\n");
682                 os << "\\begin_preamble\n"
683                    << tmppreamble
684                    << "\n\\end_preamble\n";
685         }
686
687         // the options
688         if (!options.empty()) {
689                 os << "\\options " << options << '\n';
690         }
691         
692         //the modules
693         if (!layoutModules_.empty()) {
694                 os << "\\begin_modules" << '\n';
695                 LayoutModuleList::const_iterator it = layoutModules_.begin();
696                 for (; it != layoutModules_.end(); it++)
697                         os << *it << '\n';
698                 os << "\\end_modules" << '\n';
699         }
700
701         // then the text parameters
702         if (language != ignore_language)
703                 os << "\\language " << language->lang() << '\n';
704         os << "\\inputencoding " << inputenc
705            << "\n\\font_roman " << fontsRoman
706            << "\n\\font_sans " << fontsSans
707            << "\n\\font_typewriter " << fontsTypewriter
708            << "\n\\font_default_family " << fontsDefaultFamily
709            << "\n\\font_sc " << convert<string>(fontsSC)
710            << "\n\\font_osf " << convert<string>(fontsOSF)
711            << "\n\\font_sf_scale " << fontsSansScale
712            << "\n\\font_tt_scale " << fontsTypewriterScale
713            << "\n\\graphics " << graphicsDriver << '\n';
714
715         if (!float_placement.empty()) {
716                 os << "\\float_placement " << float_placement << '\n';
717         }
718         os << "\\paperfontsize " << fontsize << '\n';
719
720         spacing().writeFile(os);
721         pdfoptions().writeFile(os);
722
723         os << "\\papersize " << string_papersize[papersize]
724            << "\n\\use_geometry " << convert<string>(use_geometry)
725            << "\n\\use_amsmath " << use_amsmath
726            << "\n\\use_esint " << use_esint
727            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
728            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
729            << "\n\\paperorientation " << string_orientation[orientation]
730            << '\n';
731
732         BranchList::const_iterator it = branchlist().begin();
733         BranchList::const_iterator end = branchlist().end();
734         for (; it != end; ++it) {
735                 os << "\\branch " << to_utf8(it->getBranch())
736                    << "\n\\selected " << it->getSelected()
737                    << "\n\\color " << lyx::X11hexname(it->getColor())
738                    << "\n\\end_branch"
739                    << "\n";
740         }
741
742         if (!paperwidth.empty())
743                 os << "\\paperwidth "
744                    << VSpace(paperwidth).asLyXCommand() << '\n';
745         if (!paperheight.empty())
746                 os << "\\paperheight "
747                    << VSpace(paperheight).asLyXCommand() << '\n';
748         if (!leftmargin.empty())
749                 os << "\\leftmargin "
750                    << VSpace(leftmargin).asLyXCommand() << '\n';
751         if (!topmargin.empty())
752                 os << "\\topmargin "
753                    << VSpace(topmargin).asLyXCommand() << '\n';
754         if (!rightmargin.empty())
755                 os << "\\rightmargin "
756                    << VSpace(rightmargin).asLyXCommand() << '\n';
757         if (!bottommargin.empty())
758                 os << "\\bottommargin "
759                    << VSpace(bottommargin).asLyXCommand() << '\n';
760         if (!headheight.empty())
761                 os << "\\headheight "
762                    << VSpace(headheight).asLyXCommand() << '\n';
763         if (!headsep.empty())
764                 os << "\\headsep "
765                    << VSpace(headsep).asLyXCommand() << '\n';
766         if (!footskip.empty())
767                 os << "\\footskip "
768                    << VSpace(footskip).asLyXCommand() << '\n';
769         os << "\\secnumdepth " << secnumdepth
770            << "\n\\tocdepth " << tocdepth
771            << "\n\\paragraph_separation "
772            << string_paragraph_separation[paragraph_separation]
773            << "\n\\defskip " << getDefSkip().asLyXCommand()
774            << "\n\\quotes_language "
775            << string_quotes_language[quotes_language]
776            << "\n\\papercolumns " << columns
777            << "\n\\papersides " << sides
778            << "\n\\paperpagestyle " << pagestyle << '\n';
779         if (!listings_params.empty())
780                 os << "\\listings_params \"" <<
781                         InsetListingsParams(listings_params).encodedString() << "\"\n";
782         for (int i = 0; i < 4; ++i) {
783                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
784                         if (user_defined_bullet(i).getFont() != -1) {
785                                 os << "\\bullet " << i << " "
786                                    << user_defined_bullet(i).getFont() << " "
787                                    << user_defined_bullet(i).getCharacter() << " "
788                                    << user_defined_bullet(i).getSize() << "\n";
789                         }
790                         else {
791                                 // FIXME UNICODE
792                                 os << "\\bulletLaTeX " << i << " \""
793                                    << lyx::to_ascii(user_defined_bullet(i).getText())
794                                    << "\"\n";
795                         }
796                 }
797         }
798
799         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
800         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
801
802         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
803         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
804         for (; a_it != a_end; ++a_it) {
805                 if (a_it->second.used())
806                         os << "\\author " << a_it->second << "\n";
807                 else
808                         os << "\\author " << Author() << "\n";
809         }
810 }
811
812
813 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
814                               TexRow & texrow) const
815 {
816         os << "\\documentclass";
817
818         TextClass const & tclass = getTextClass();
819
820         ostringstream clsoptions; // the document class options.
821
822         if (tokenPos(tclass.opt_fontsize(),
823                      '|', fontsize) >= 0) {
824                 // only write if existing in list (and not default)
825                 clsoptions << fontsize << "pt,";
826         }
827
828         // custom, A3, B3 and B4 paper sizes need geometry
829         bool nonstandard_papersize = papersize == PAPER_B3
830                 || papersize == PAPER_B4
831                 || papersize == PAPER_A3
832                 || papersize == PAPER_CUSTOM;
833
834         if (!use_geometry) {
835                 switch (papersize) {
836                 case PAPER_A4:
837                         clsoptions << "a4paper,";
838                         break;
839                 case PAPER_USLETTER:
840                         clsoptions << "letterpaper,";
841                         break;
842                 case PAPER_A5:
843                         clsoptions << "a5paper,";
844                         break;
845                 case PAPER_B5:
846                         clsoptions << "b5paper,";
847                         break;
848                 case PAPER_USEXECUTIVE:
849                         clsoptions << "executivepaper,";
850                         break;
851                 case PAPER_USLEGAL:
852                         clsoptions << "legalpaper,";
853                         break;
854                 case PAPER_DEFAULT:
855                 case PAPER_A3:
856                 case PAPER_B3:
857                 case PAPER_B4:
858                 case PAPER_CUSTOM:
859                         break;
860                 }
861         }
862
863         // if needed
864         if (sides != tclass.sides()) {
865                 switch (sides) {
866                 case TextClass::OneSide:
867                         clsoptions << "oneside,";
868                         break;
869                 case TextClass::TwoSides:
870                         clsoptions << "twoside,";
871                         break;
872                 }
873         }
874
875         // if needed
876         if (columns != tclass.columns()) {
877                 if (columns == 2)
878                         clsoptions << "twocolumn,";
879                 else
880                         clsoptions << "onecolumn,";
881         }
882
883         if (!use_geometry
884             && orientation == ORIENTATION_LANDSCAPE)
885                 clsoptions << "landscape,";
886
887         // language should be a parameter to \documentclass
888         if (language->babel() == "hebrew"
889             && default_language->babel() != "hebrew")
890                 // This seems necessary
891                 features.useLanguage(default_language);
892
893         ostringstream language_options;
894         bool const use_babel = features.useBabel();
895         if (use_babel) {
896                 language_options << features.getLanguages();
897                 if (!language->babel().empty()) {
898                         if (!language_options.str().empty())
899                                 language_options << ',';
900                         language_options << language->babel();
901                 }
902                 if (lyxrc.language_global_options && !language_options.str().empty())
903                         clsoptions << language_options.str() << ',';
904         }
905
906         // the user-defined options
907         if (!options.empty()) {
908                 clsoptions << options << ',';
909         }
910
911         string strOptions(clsoptions.str());
912         if (!strOptions.empty()) {
913                 strOptions = rtrim(strOptions, ",");
914                 // FIXME UNICODE
915                 os << '[' << from_utf8(strOptions) << ']';
916         }
917
918         os << '{' << from_ascii(tclass.latexname()) << "}\n";
919         texrow.newline();
920         // end of \documentclass defs
921
922         // font selection must be done before loading fontenc.sty
923         string const fonts =
924                 loadFonts(fontsRoman, fontsSans,
925                           fontsTypewriter, fontsSC, fontsOSF,
926                           fontsSansScale, fontsTypewriterScale);
927         if (!fonts.empty()) {
928                 os << from_ascii(fonts);
929                 texrow.newline();
930         }
931         if (fontsDefaultFamily != "default")
932                 os << "\\renewcommand{\\familydefault}{\\"
933                    << from_ascii(fontsDefaultFamily) << "}\n";
934
935         // set font encoding
936         // this one is not per buffer
937         // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
938         if (lyxrc.fontenc != "default") {
939                 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
940                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
941                            << ",LFE,LAE]{fontenc}\n";
942                         texrow.newline();
943                 } else {
944                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
945                            << "]{fontenc}\n";
946                         texrow.newline();
947                 }
948         }
949
950         // handle inputenc etc.
951         writeEncodingPreamble(os, features, texrow);
952
953         if (!listings_params.empty()) {
954                 os << "\\usepackage{listings}\n";
955                 texrow.newline();
956                 os << "\\lstset{";
957                 // do not test validity because listings_params is supposed to be valid
958                 string par = InsetListingsParams(listings_params).separatedParams(true);
959                 os << from_ascii(par);
960                 // count the number of newlines
961                 for (size_t i = 0; i < par.size(); ++i)
962                         if (par[i] == '\n')
963                                 texrow.newline();
964                 os << "}\n";
965                 texrow.newline();
966         }
967         if (use_geometry || nonstandard_papersize) {
968                 os << "\\usepackage{geometry}\n";
969                 texrow.newline();
970                 os << "\\geometry{verbose";
971                 if (orientation == ORIENTATION_LANDSCAPE)
972                         os << ",landscape";
973                 switch (papersize) {
974                 case PAPER_CUSTOM:
975                         if (!paperwidth.empty())
976                                 os << ",paperwidth="
977                                    << from_ascii(paperwidth);
978                         if (!paperheight.empty())
979                                 os << ",paperheight="
980                                    << from_ascii(paperheight);
981                         break;
982                 case PAPER_USLETTER:
983                         os << ",letterpaper";
984                         break;
985                 case PAPER_USLEGAL:
986                         os << ",legalpaper";
987                         break;
988                 case PAPER_USEXECUTIVE:
989                         os << ",executivepaper";
990                         break;
991                 case PAPER_A3:
992                         os << ",a3paper";
993                         break;
994                 case PAPER_A4:
995                         os << ",a4paper";
996                         break;
997                 case PAPER_A5:
998                         os << ",a5paper";
999                         break;
1000                 case PAPER_B3:
1001                         os << ",b3paper";
1002                         break;
1003                 case PAPER_B4:
1004                         os << ",b4paper";
1005                         break;
1006                 case PAPER_B5:
1007                         os << ",b5paper";
1008                         break;
1009                 default:
1010                         // default papersize ie PAPER_DEFAULT
1011                         switch (lyxrc.default_papersize) {
1012                         case PAPER_DEFAULT: // keep compiler happy
1013                         case PAPER_USLETTER:
1014                                 os << ",letterpaper";
1015                                 break;
1016                         case PAPER_USLEGAL:
1017                                 os << ",legalpaper";
1018                                 break;
1019                         case PAPER_USEXECUTIVE:
1020                                 os << ",executivepaper";
1021                                 break;
1022                         case PAPER_A3:
1023                                 os << ",a3paper";
1024                                 break;
1025                         case PAPER_A4:
1026                                 os << ",a4paper";
1027                                 break;
1028                         case PAPER_A5:
1029                                 os << ",a5paper";
1030                                 break;
1031                         case PAPER_B5:
1032                                 os << ",b5paper";
1033                                 break;
1034                         case PAPER_B3:
1035                         case PAPER_B4:
1036                         case PAPER_CUSTOM:
1037                                 break;
1038                         }
1039                 }
1040                 if (!topmargin.empty())
1041                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1042                 if (!bottommargin.empty())
1043                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1044                 if (!leftmargin.empty())
1045                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1046                 if (!rightmargin.empty())
1047                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1048                 if (!headheight.empty())
1049                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1050                 if (!headsep.empty())
1051                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1052                 if (!footskip.empty())
1053                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1054                 os << "}\n";
1055                 texrow.newline();
1056         }
1057
1058         if (tokenPos(tclass.opt_pagestyle(),
1059                      '|', pagestyle) >= 0) {
1060                 if (pagestyle == "fancy") {
1061                         os << "\\usepackage{fancyhdr}\n";
1062                         texrow.newline();
1063                 }
1064                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1065                 texrow.newline();
1066         }
1067
1068         // Only if class has a ToC hierarchy
1069         if (tclass.hasTocLevels()) {
1070                 if (secnumdepth != tclass.secnumdepth()) {
1071                         os << "\\setcounter{secnumdepth}{"
1072                            << secnumdepth
1073                            << "}\n";
1074                         texrow.newline();
1075                 }
1076                 if (tocdepth != tclass.tocdepth()) {
1077                         os << "\\setcounter{tocdepth}{"
1078                            << tocdepth
1079                            << "}\n";
1080                         texrow.newline();
1081                 }
1082         }
1083
1084         if (paragraph_separation) {
1085                 switch (getDefSkip().kind()) {
1086                 case VSpace::SMALLSKIP:
1087                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1088                         break;
1089                 case VSpace::MEDSKIP:
1090                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1091                         break;
1092                 case VSpace::BIGSKIP:
1093                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1094                         break;
1095                 case VSpace::LENGTH:
1096                         os << "\\setlength{\\parskip}{"
1097                            << from_utf8(getDefSkip().length().asLatexString())
1098                            << "}\n";
1099                         break;
1100                 default: // should never happen // Then delete it.
1101                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1102                         break;
1103                 }
1104                 texrow.newline();
1105
1106                 os << "\\setlength{\\parindent}{0pt}\n";
1107                 texrow.newline();
1108         }
1109
1110         // If we use jurabib, we have to call babel here.
1111         if (use_babel && features.isRequired("jurabib")) {
1112                 os << from_ascii(babelCall(language_options.str()))
1113                    << '\n'
1114                    << from_ascii(features.getBabelOptions());
1115                 texrow.newline();
1116         }
1117
1118         // Now insert the LyX specific LaTeX commands...
1119
1120         // The optional packages;
1121         docstring lyxpreamble(from_ascii(features.getPackages()));
1122
1123         // We try to load babel late, in case it interferes
1124         // with other packages. But some packages also need babel to be loaded
1125         // before, e.g. jurabib has to be called after babel.
1126         // So load babel after the optional packages but before the user-defined
1127         // preamble. This allows the users to redefine babel commands, e.g. to
1128         // translate the word "Index" to the German "Stichwortverzeichnis".
1129         if (use_babel && !features.isRequired("jurabib")) {
1130                 // FIXME UNICODE
1131                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1132                 lyxpreamble += from_utf8(features.getBabelOptions());
1133         }
1134
1135         // PDF support.
1136         // * Hyperref manual: "Make sure it comes last of your loaded
1137         //   packages, to give it a fighting chance of not being over-written,
1138         //   since its job is to redefine many LATEX commands."
1139         // * Email from Heiko Oberdiek: "It is usually better to load babel
1140         //   before hyperref. Then hyperref has a chance to detect babel.
1141         // * Has to be loaded before the "LyX specific LaTeX commands" to
1142         //   avoid errors with algorithm floats.
1143         odocstringstream oss;
1144         pdfoptions().writeLaTeX(oss);
1145         lyxpreamble += oss.str();
1146
1147         // this might be useful...
1148         lyxpreamble += "\n\\makeatletter\n";
1149
1150         // Some macros LyX will need
1151         docstring tmppreamble(from_ascii(features.getMacros()));
1152
1153         if (!tmppreamble.empty()) {
1154                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1155                         "LyX specific LaTeX commands.\n"
1156                         + tmppreamble + '\n';
1157         }
1158
1159         // the text class specific preamble
1160         tmppreamble = features.getTClassPreamble();
1161         if (!tmppreamble.empty()) {
1162                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1163                         "Textclass specific LaTeX commands.\n"
1164                         + tmppreamble + '\n';
1165         }
1166
1167         /* the user-defined preamble */
1168         if (!preamble.empty()) {
1169                 // FIXME UNICODE
1170                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1171                         "User specified LaTeX commands.\n"
1172                         + from_utf8(preamble) + '\n';
1173         }
1174
1175         // Itemize bullet settings need to be last in case the user
1176         // defines their own bullets that use a package included
1177         // in the user-defined preamble -- ARRae
1178         // Actually it has to be done much later than that
1179         // since some packages like frenchb make modifications
1180         // at \begin{document} time -- JMarc
1181         docstring bullets_def;
1182         for (int i = 0; i < 4; ++i) {
1183                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1184                         if (bullets_def.empty())
1185                                 bullets_def += "\\AtBeginDocument{\n";
1186                         bullets_def += "  \\def\\labelitemi";
1187                         switch (i) {
1188                                 // `i' is one less than the item to modify
1189                         case 0:
1190                                 break;
1191                         case 1:
1192                                 bullets_def += 'i';
1193                                 break;
1194                         case 2:
1195                                 bullets_def += "ii";
1196                                 break;
1197                         case 3:
1198                                 bullets_def += 'v';
1199                                 break;
1200                         }
1201                         bullets_def += '{' +
1202                                 user_defined_bullet(i).getText()
1203                                 + "}\n";
1204                 }
1205         }
1206
1207         if (!bullets_def.empty())
1208                 lyxpreamble += bullets_def + "}\n\n";
1209
1210         lyxpreamble += "\\makeatother\n\n";
1211
1212         int const nlines =
1213                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1214         for (int j = 0; j != nlines; ++j) {
1215                 texrow.newline();
1216         }
1217
1218         os << lyxpreamble;
1219         return use_babel;
1220 }
1221
1222
1223 void BufferParams::useClassDefaults()
1224 {
1225         TextClass const & tclass = textclasslist[baseClass_];
1226
1227         sides = tclass.sides();
1228         columns = tclass.columns();
1229         pagestyle = tclass.pagestyle();
1230         options = tclass.options();
1231         // Only if class has a ToC hierarchy
1232         if (tclass.hasTocLevels()) {
1233                 secnumdepth = tclass.secnumdepth();
1234                 tocdepth = tclass.tocdepth();
1235         }
1236 }
1237
1238
1239 bool BufferParams::hasClassDefaults() const
1240 {
1241         TextClass const & tclass = textclasslist[baseClass_];
1242
1243         return (sides == tclass.sides()
1244                 && columns == tclass.columns()
1245                 && pagestyle == tclass.pagestyle()
1246                 && options == tclass.options()
1247                 && secnumdepth == tclass.secnumdepth()
1248                 && tocdepth == tclass.tocdepth());
1249 }
1250
1251
1252 TextClass const & BufferParams::getTextClass() const
1253 {
1254         return *textClass_;
1255 }
1256
1257
1258 TextClassPtr BufferParams::getTextClassPtr() const {
1259         return textClass_;
1260 }
1261
1262
1263 void BufferParams::setTextClass(TextClassPtr tc) {
1264         textClass_ = tc;
1265 }
1266
1267
1268 bool BufferParams::setBaseClass(textclass_type tc)
1269 {
1270         bool retVal = true;
1271         if (textclasslist[tc].load())
1272                 baseClass_ = tc;
1273         else {
1274                 docstring s = 
1275                         bformat(_("The document class %1$s could not be loaded."),
1276                  from_utf8(textclasslist[tc].name()));
1277                 frontend::Alert::error(_("Could not load class"), s);
1278                 retVal = false;
1279         }
1280         makeTextClass();
1281         return retVal;
1282 }
1283
1284
1285 void BufferParams::setJustBaseClass(textclass_type tc)
1286
1287         baseClass_ = tc; 
1288 }
1289
1290
1291 textclass_type BufferParams::getBaseClass() const
1292 {
1293         return baseClass_;
1294 }
1295
1296
1297 void BufferParams::makeTextClass()
1298 {
1299         textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1300         //FIXME It might be worth loading the children's modules here,
1301         //just as we load their bibliographies and such, instead of just 
1302         //doing a check in InsetInclude.
1303         LayoutModuleList::const_iterator it = layoutModules_.begin();
1304         for (; it != layoutModules_.end(); it++) {
1305                 string const modName = *it;
1306                 LyXModule * lm = moduleList[modName];
1307                 if (!lm) {
1308                         docstring const msg =
1309                                 bformat(_("The module %1$s has been requested by\n"
1310                                         "this document but has not been found in the list of\n"
1311                                         "available modules. If you recently installed it, you\n"
1312                                         "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1313                         frontend::Alert::warning(_("Module not available"),
1314                                         msg + _("Some layouts may not be available."));
1315                         lyxerr << "BufferParams::makeTextClass(): Module " <<
1316                                         modName << " requested but not found in module list." <<
1317                                         endl;
1318                         continue;
1319                 }
1320                 FileName layout_file = libFileSearch("layouts", lm->filename);
1321                 textClass_->read(layout_file, TextClass::MODULE);
1322         }
1323 }
1324
1325
1326 std::vector<string> const & BufferParams::getModules() const {
1327         return layoutModules_;
1328 }
1329
1330
1331
1332 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1333         LayoutModuleList::const_iterator it = layoutModules_.begin();
1334         LayoutModuleList::const_iterator end = layoutModules_.end();
1335         for (; it != end; it++) {
1336                 if (*it == modName) 
1337                         break;
1338         }
1339         if (it != layoutModules_.end())
1340                 return false;
1341         layoutModules_.push_back(modName);
1342         if (makeClass)
1343                 makeTextClass();
1344         return true;
1345 }
1346
1347
1348 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1349 {
1350         bool retval = true;
1351         std::vector<string>::const_iterator it = modNames.begin();
1352         std::vector<string>::const_iterator end = modNames.end();
1353         for (; it != end; ++it)
1354                 retval &= addLayoutModule(*it, false);
1355         makeTextClass();
1356         return retval;
1357 }
1358
1359
1360 void BufferParams::clearLayoutModules() {
1361         layoutModules_.clear();
1362         makeTextClass();
1363 }
1364
1365
1366 Font const BufferParams::getFont() const
1367 {
1368         Font f = getTextClass().defaultfont();
1369         f.setLanguage(language);
1370         if (fontsDefaultFamily == "rmdefault")
1371                 f.setFamily(Font::ROMAN_FAMILY);
1372         else if (fontsDefaultFamily == "sfdefault")
1373                 f.setFamily(Font::SANS_FAMILY);
1374         else if (fontsDefaultFamily == "ttdefault")
1375                 f.setFamily(Font::TYPEWRITER_FAMILY);
1376         return f;
1377 }
1378
1379
1380 void BufferParams::readPreamble(Lexer & lex)
1381 {
1382         if (lex.getString() != "\\begin_preamble")
1383                 lyxerr << "Error (BufferParams::readPreamble):"
1384                         "consistency check failed." << endl;
1385
1386         preamble = lex.getLongString("\\end_preamble");
1387 }
1388
1389
1390 void BufferParams::readLanguage(Lexer & lex)
1391 {
1392         if (!lex.next()) return;
1393
1394         string const tmptok = lex.getString();
1395
1396         // check if tmptok is part of tex_babel in tex-defs.h
1397         language = languages.getLanguage(tmptok);
1398         if (!language) {
1399                 // Language tmptok was not found
1400                 language = default_language;
1401                 lyxerr << "Warning: Setting language `"
1402                        << tmptok << "' to `" << language->lang()
1403                        << "'." << endl;
1404         }
1405 }
1406
1407
1408 void BufferParams::readGraphicsDriver(Lexer & lex)
1409 {
1410         if (!lex.next()) return;
1411
1412         string const tmptok = lex.getString();
1413         // check if tmptok is part of tex_graphics in tex_defs.h
1414         int n = 0;
1415         while (true) {
1416                 string const test = tex_graphics[n++];
1417
1418                 if (test == tmptok) {
1419                         graphicsDriver = tmptok;
1420                         break;
1421                 } else if (test == "") {
1422                         lex.printError(
1423                                 "Warning: graphics driver `$$Token' not recognized!\n"
1424                                 "         Setting graphics driver to `default'.\n");
1425                         graphicsDriver = "default";
1426                         break;
1427                 }
1428         }
1429 }
1430
1431
1432 void BufferParams::readBullets(Lexer & lex)
1433 {
1434         if (!lex.next()) return;
1435
1436         int const index = lex.getInteger();
1437         lex.next();
1438         int temp_int = lex.getInteger();
1439         user_defined_bullet(index).setFont(temp_int);
1440         temp_bullet(index).setFont(temp_int);
1441         lex >> temp_int;
1442         user_defined_bullet(index).setCharacter(temp_int);
1443         temp_bullet(index).setCharacter(temp_int);
1444         lex >> temp_int;
1445         user_defined_bullet(index).setSize(temp_int);
1446         temp_bullet(index).setSize(temp_int);
1447 }
1448
1449
1450 void BufferParams::readBulletsLaTeX(Lexer & lex)
1451 {
1452         // The bullet class should be able to read this.
1453         if (!lex.next()) return;
1454         int const index = lex.getInteger();
1455         lex.next(true);
1456         docstring const temp_str = lex.getDocString();
1457
1458         user_defined_bullet(index).setText(temp_str);
1459         temp_bullet(index).setText(temp_str);
1460 }
1461
1462
1463 void BufferParams::readModules(Lexer & lex)
1464 {
1465         if (!lex.eatLine()) {
1466                 lyxerr << "Error (BufferParams::readModules):"
1467                                 "Unexpected end of input." << endl;
1468                 return;
1469         }
1470         while (true) {
1471                 string mod = lex.getString();
1472                 if (mod == "\\end_modules")
1473                         break;
1474                 addLayoutModule(mod);
1475                 lex.eatLine();
1476         }
1477 }
1478
1479
1480 string const BufferParams::paperSizeName() const
1481 {
1482         char real_papersize = papersize;
1483         if (real_papersize == PAPER_DEFAULT)
1484                 real_papersize = lyxrc.default_papersize;
1485
1486         switch (real_papersize) {
1487         case PAPER_A3:
1488                 return "a3";
1489         case PAPER_A4:
1490                 return "a4";
1491         case PAPER_A5:
1492                 return "a5";
1493         case PAPER_B5:
1494                 return "b5";
1495         case PAPER_USEXECUTIVE:
1496                 return "foolscap";
1497         case PAPER_USLEGAL:
1498                 return "legal";
1499         case PAPER_USLETTER:
1500         default:
1501                 return "letter";
1502         }
1503 }
1504
1505
1506 string const BufferParams::dvips_options() const
1507 {
1508         string result;
1509
1510         if (use_geometry
1511             && papersize == PAPER_CUSTOM
1512             && !lyxrc.print_paper_dimension_flag.empty()
1513             && !paperwidth.empty()
1514             && !paperheight.empty()) {
1515                 // using a custom papersize
1516                 result = lyxrc.print_paper_dimension_flag;
1517                 result += ' ' + paperwidth;
1518                 result += ',' + paperheight;
1519         } else {
1520                 string const paper_option = paperSizeName();
1521                 if (paper_option != "letter" ||
1522                     orientation != ORIENTATION_LANDSCAPE) {
1523                         // dvips won't accept -t letter -t landscape.
1524                         // In all other cases, include the paper size
1525                         // explicitly.
1526                         result = lyxrc.print_paper_flag;
1527                         result += ' ' + paper_option;
1528                 }
1529         }
1530         if (orientation == ORIENTATION_LANDSCAPE &&
1531             papersize != PAPER_CUSTOM)
1532                 result += ' ' + lyxrc.print_landscape_flag;
1533         return result;
1534 }
1535
1536
1537 string const BufferParams::babelCall(string const & lang_opts) const
1538 {
1539         string lang_pack = lyxrc.language_package;
1540         if (lang_pack != "\\usepackage{babel}")
1541                 return lang_pack;
1542         // suppress the babel call when there is no babel language defined
1543         // for the document language in the lib/languages file and if no
1544         // other languages are used (lang_opts is then empty)
1545         if (lang_opts.empty())
1546                 return string();
1547         if (!lyxrc.language_global_options)
1548                 return "\\usepackage[" + lang_opts + "]{babel}";
1549         return lang_pack;
1550 }
1551
1552
1553 void BufferParams::writeEncodingPreamble(odocstream & os,
1554                 LaTeXFeatures & features, TexRow & texrow) const
1555 {
1556         if (inputenc == "auto") {
1557                 string const doc_encoding =
1558                         language->encoding()->latexName();
1559                 Encoding::Package const package =
1560                         language->encoding()->package();
1561
1562                 // Create a list with all the input encodings used
1563                 // in the document
1564                 std::set<string> encodings =
1565                         features.getEncodingSet(doc_encoding);
1566
1567                 if (!encodings.empty() || package == Encoding::inputenc) {
1568                         os << "\\usepackage[";
1569                         std::set<string>::const_iterator it = encodings.begin();
1570                         std::set<string>::const_iterator const end = encodings.end();
1571                         if (it != end) {
1572                                 os << from_ascii(*it);
1573                                 ++it;
1574                         }
1575                         for (; it != end; ++it)
1576                                 os << ',' << from_ascii(*it);
1577                         if (package == Encoding::inputenc) {
1578                                 if (!encodings.empty())
1579                                         os << ',';
1580                                 os << from_ascii(doc_encoding);
1581                         }
1582                         os << "]{inputenc}\n";
1583                         texrow.newline();
1584                 }
1585                 if (package == Encoding::CJK) {
1586                         os << "\\usepackage{CJK}\n";
1587                         texrow.newline();
1588                 }
1589         } else if (inputenc != "default") {
1590                 switch (encoding().package()) {
1591                 case Encoding::none:
1592                         break;
1593                 case Encoding::inputenc:
1594                         os << "\\usepackage[" << from_ascii(inputenc)
1595                            << "]{inputenc}\n";
1596                         texrow.newline();
1597                         break;
1598                 case Encoding::CJK:
1599                         os << "\\usepackage{CJK}\n";
1600                         texrow.newline();
1601                         break;
1602                 }
1603         }
1604
1605         // The encoding "armscii8" is only available when the package "armtex" is loaded.
1606         // armscii8 is used for Armenian.
1607         if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1608                 os << "\\usepackage{armtex}\n";
1609                 texrow.newline();
1610         }
1611 }
1612
1613
1614 string const BufferParams::loadFonts(string const & rm,
1615                                      string const & sf, string const & tt,
1616                                      bool const & sc, bool const & osf,
1617                                      int const & sfscale, int const & ttscale) const
1618 {
1619         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1620            several packages have been replaced by others, that might not
1621            be installed on every system. We have to take care for that
1622            (see psnfss.pdf). We try to support all psnfss fonts as well
1623            as the fonts that have become de facto standard in the LaTeX
1624            world (e.g. Latin Modern). We do not support obsolete fonts
1625            (like PSLatex). In general, it should be possible to mix any
1626            rm font with any sf or tt font, respectively. (JSpitzm)
1627            TODO:
1628                 -- separate math fonts.
1629         */
1630
1631         if (rm == "default" && sf == "default" && tt == "default")
1632                 //nothing to do
1633                 return string();
1634
1635         ostringstream os;
1636
1637         // ROMAN FONTS
1638         // Computer Modern (must be explicitely selectable -- there might be classes
1639         // that define a different default font!
1640         if (rm == "cmr") {
1641                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1642                 // osf for Computer Modern needs eco.sty
1643                 if (osf)
1644                         os << "\\usepackage{eco}\n";
1645         }
1646         // Latin Modern Roman
1647         else if (rm == "lmodern")
1648                 os << "\\usepackage{lmodern}\n";
1649         // AE
1650         else if (rm == "ae") {
1651                 // not needed when using OT1 font encoding.
1652                 if (lyxrc.fontenc != "default")
1653                         os << "\\usepackage{ae,aecompl}\n";
1654         }
1655         // Times
1656         else if (rm == "times") {
1657                 // try to load the best available package
1658                 if (LaTeXFeatures::isAvailable("mathptmx"))
1659                         os << "\\usepackage{mathptmx}\n";
1660                 else if (LaTeXFeatures::isAvailable("mathptm"))
1661                         os << "\\usepackage{mathptm}\n";
1662                 else
1663                         os << "\\usepackage{times}\n";
1664         }
1665         // Palatino
1666         else if (rm == "palatino") {
1667                 // try to load the best available package
1668                 if (LaTeXFeatures::isAvailable("mathpazo")) {
1669                         os << "\\usepackage";
1670                         if (osf || sc) {
1671                                 os << '[';
1672                                 if (!osf)
1673                                         os << "sc";
1674                                 else
1675                                         // "osf" includes "sc"!
1676                                         os << "osf";
1677                                 os << ']';
1678                         }
1679                         os << "{mathpazo}\n";
1680                 }
1681                 else if (LaTeXFeatures::isAvailable("mathpple"))
1682                         os << "\\usepackage{mathpple}\n";
1683                 else
1684                         os << "\\usepackage{palatino}\n";
1685         }
1686         // Utopia
1687         else if (rm == "utopia") {
1688                 // fourier supersedes utopia.sty, but does
1689                 // not work with OT1 encoding.
1690                 if (LaTeXFeatures::isAvailable("fourier")
1691                     && lyxrc.fontenc != "default") {
1692                         os << "\\usepackage";
1693                         if (osf || sc) {
1694                                 os << '[';
1695                                 if (sc)
1696                                         os << "expert";
1697                                 if (osf && sc)
1698                                         os << ',';
1699                                 if (osf)
1700                                         os << "oldstyle";
1701                                 os << ']';
1702                         }
1703                         os << "{fourier}\n";
1704                 }
1705                 else
1706                         os << "\\usepackage{utopia}\n";
1707         }
1708         // Bera (complete fontset)
1709         else if (rm == "bera" && sf == "default" && tt == "default")
1710                 os << "\\usepackage{bera}\n";
1711         // everything else
1712         else if (rm != "default")
1713                 os << "\\usepackage" << "{" << rm << "}\n";
1714
1715         // SANS SERIF
1716         // Helvetica, Bera Sans
1717         if (sf == "helvet" || sf == "berasans") {
1718                 if (sfscale != 100)
1719                         os << "\\usepackage[scaled=" << float(sfscale) / 100
1720                            << "]{" << sf << "}\n";
1721                 else
1722                         os << "\\usepackage{" << sf << "}\n";
1723         }
1724         // Avant Garde
1725         else if (sf == "avant")
1726                 os << "\\usepackage{" << sf << "}\n";
1727         // Computer Modern, Latin Modern, CM Bright
1728         else if (sf != "default")
1729                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1730
1731         // monospaced/typewriter
1732         // Courier, LuxiMono
1733         if (tt == "luximono" || tt == "beramono") {
1734                 if (ttscale != 100)
1735                         os << "\\usepackage[scaled=" << float(ttscale) / 100
1736                            << "]{" << tt << "}\n";
1737                 else
1738                         os << "\\usepackage{" << tt << "}\n";
1739         }
1740         // Courier
1741         else if (tt == "courier" )
1742                 os << "\\usepackage{" << tt << "}\n";
1743         // Computer Modern, Latin Modern, CM Bright
1744         else if  (tt != "default")
1745                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1746
1747         return os.str();
1748 }
1749
1750
1751 Encoding const & BufferParams::encoding() const
1752 {
1753         if (inputenc == "auto" || inputenc == "default")
1754                 return *(language->encoding());
1755         Encoding const * const enc =
1756                 encodings.getFromLaTeXName(inputenc);
1757         if (enc)
1758                 return *enc;
1759         lyxerr << "Unknown inputenc value `" << inputenc
1760                << "'. Using `auto' instead." << endl;
1761         return *(language->encoding());
1762 }
1763
1764
1765 biblio::CiteEngine BufferParams::getEngine() const
1766 {
1767         // FIXME the class should provide the numerical/
1768         // authoryear choice
1769         if (getTextClass().provides("natbib")
1770             && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1771                 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1772         return cite_engine_;
1773 }
1774
1775
1776 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1777 {
1778         cite_engine_ = cite_engine;
1779 }
1780
1781 } // namespace lyx