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