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
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "bufferparams.h"
21 #include "BranchList.h"
27 #include "LaTeXFeatures.h"
32 #include "lyxtextclasslist.h"
33 #include "outputparams.h"
34 #include "tex-strings.h"
39 #include "frontends/Alert.h"
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/translator.h"
45 #include <boost/array.hpp>
52 using support::bformat;
54 using support::tokenPos;
58 using std::istringstream;
60 using std::ostringstream;
63 namespace Alert = lyx::frontend::Alert;
69 // Paragraph separation
70 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
73 ParSepTranslator const init_parseptranslator()
75 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
76 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
81 ParSepTranslator const & parseptranslator()
83 static ParSepTranslator translator = init_parseptranslator();
89 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
92 QuotesLangTranslator const init_quoteslangtranslator()
94 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
95 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
96 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
97 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
98 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
99 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
104 QuotesLangTranslator const & quoteslangtranslator()
106 static QuotesLangTranslator translator = init_quoteslangtranslator();
112 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
115 PaperSizeTranslator const init_papersizetranslator()
117 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
118 translator.addPair(string_papersize[1], PAPER_CUSTOM);
119 translator.addPair(string_papersize[2], PAPER_USLETTER);
120 translator.addPair(string_papersize[3], PAPER_USLEGAL);
121 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
122 translator.addPair(string_papersize[5], PAPER_A3);
123 translator.addPair(string_papersize[6], PAPER_A4);
124 translator.addPair(string_papersize[7], PAPER_A5);
125 translator.addPair(string_papersize[8], PAPER_B3);
126 translator.addPair(string_papersize[9], PAPER_B4);
127 translator.addPair(string_papersize[10], PAPER_B5);
132 PaperSizeTranslator const & papersizetranslator()
134 static PaperSizeTranslator translator = init_papersizetranslator();
140 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
143 PaperOrientationTranslator const init_paperorientationtranslator()
145 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
146 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
151 PaperOrientationTranslator const & paperorientationtranslator()
153 static PaperOrientationTranslator translator = init_paperorientationtranslator();
159 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
162 SidesTranslator const init_sidestranslator()
164 SidesTranslator translator(1, LyXTextClass::OneSide);
165 translator.addPair(2, LyXTextClass::TwoSides);
170 SidesTranslator const & sidestranslator()
172 static SidesTranslator translator = init_sidestranslator();
179 typedef Translator<int, BufferParams::AMS> AMSTranslator;
182 AMSTranslator const init_amstranslator()
184 AMSTranslator translator(0, BufferParams::AMS_OFF);
185 translator.addPair(1, BufferParams::AMS_AUTO);
186 translator.addPair(2, BufferParams::AMS_ON);
191 AMSTranslator const & amstranslator()
193 static AMSTranslator translator = init_amstranslator();
199 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
202 CiteEngineTranslator const init_citeenginetranslator()
204 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
205 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
206 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
207 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
212 CiteEngineTranslator const & citeenginetranslator()
214 static CiteEngineTranslator translator = init_citeenginetranslator();
220 typedef Translator<string, Spacing::Space> SpaceTranslator;
223 SpaceTranslator const init_spacetranslator()
225 SpaceTranslator translator("default", Spacing::Default);
226 translator.addPair("single", Spacing::Single);
227 translator.addPair("onehalf", Spacing::Onehalf);
228 translator.addPair("double", Spacing::Double);
229 translator.addPair("other", Spacing::Other);
234 SpaceTranslator const & spacetranslator()
236 static SpaceTranslator translator = init_spacetranslator();
240 // ends annonym namespace
244 class BufferParams::Impl
249 AuthorList authorlist;
250 BranchList branchlist;
251 boost::array<Bullet, 4> temp_bullets;
252 boost::array<Bullet, 4> user_defined_bullets;
254 /** This is the amount of space used for paragraph_separation "skip",
255 * and for detached paragraphs in "indented" documents.
261 BufferParams::Impl::Impl()
262 : defskip(VSpace::MEDSKIP)
264 // set initial author
265 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
270 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
274 return new BufferParams::Impl(*ptr);
278 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
284 BufferParams::BufferParams()
285 : // Initialize textclass to point to article. if `first' is
286 // true in the returned pair, then `second' is the textclass
287 // number; if it is false, second is 0. In both cases, second
289 textclass(textclasslist.numberOfClass("article").second),
292 paragraph_separation = PARSEP_INDENT;
293 quotes_language = InsetQuotes::EnglishQ;
294 fontsize = "default";
297 papersize = PAPER_DEFAULT;
298 orientation = ORIENTATION_PORTRAIT;
299 use_geometry = false;
300 use_amsmath = AMS_AUTO;
301 cite_engine = biblio::ENGINE_BASIC;
302 use_bibtopic = false;
303 trackChanges = false;
304 outputChanges = false;
307 language = default_language;
308 fontsRoman = "default";
309 fontsSans = "default";
310 fontsTypewriter = "default";
311 fontsDefaultFamily = "default";
314 fontsSansScale = 100;
315 fontsTypewriterScale = 100;
317 graphicsDriver = "default";
318 sides = LyXTextClass::OneSide;
320 pagestyle = "default";
322 for (int iter = 0; iter < 4; ++iter) {
323 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
324 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
329 BufferParams::~BufferParams()
333 AuthorList & BufferParams::authors()
335 return pimpl_->authorlist;
339 AuthorList const & BufferParams::authors() const
341 return pimpl_->authorlist;
345 BranchList & BufferParams::branchlist()
347 return pimpl_->branchlist;
351 BranchList const & BufferParams::branchlist() const
353 return pimpl_->branchlist;
357 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
359 BOOST_ASSERT(index < 4);
360 return pimpl_->temp_bullets[index];
364 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
366 BOOST_ASSERT(index < 4);
367 return pimpl_->temp_bullets[index];
371 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
373 BOOST_ASSERT(index < 4);
374 return pimpl_->user_defined_bullets[index];
378 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
380 BOOST_ASSERT(index < 4);
381 return pimpl_->user_defined_bullets[index];
385 Spacing & BufferParams::spacing()
387 return pimpl_->spacing;
391 Spacing const & BufferParams::spacing() const
393 return pimpl_->spacing;
397 VSpace const & BufferParams::getDefSkip() const
399 return pimpl_->defskip;
403 void BufferParams::setDefSkip(VSpace const & vs)
405 pimpl_->defskip = vs;
409 string const BufferParams::readToken(LyXLex & lex, string const & token)
411 if (token == "\\textclass") {
413 string const classname = lex.getString();
414 pair<bool, lyx::textclass_type> pp =
415 textclasslist.numberOfClass(classname);
417 textclass = pp.second;
419 // if text class does not exist, try to load it from filepath
420 pp = textclasslist.addTextClass(classname, filepath);
422 textclass = pp.second;
428 // FIXME: isTeXClassAvailable will try to load the layout file, but will
429 // fail because of the lack of path info. Warnings will be given although
430 // the layout file will be correctly loaded later.
431 if (!getLyXTextClass().isTeXClassAvailable()) {
432 docstring const msg =
433 bformat(_("The document uses a missing "
434 "TeX class \"%1$s\".\n"), from_utf8(classname));
435 Alert::warning(_("Document class not available"),
436 msg + _("LyX will not be able to produce output."));
438 } else if (token == "\\begin_preamble") {
440 } else if (token == "\\options") {
442 options = lex.getString();
443 } else if (token == "\\language") {
445 } else if (token == "\\inputencoding") {
447 } else if (token == "\\graphics") {
448 readGraphicsDriver(lex);
449 } else if (token == "\\font_roman") {
451 } else if (token == "\\font_sans") {
453 } else if (token == "\\font_typewriter") {
454 lex >> fontsTypewriter;
455 } else if (token == "\\font_default_family") {
456 lex >> fontsDefaultFamily;
457 } else if (token == "\\font_sc") {
459 } else if (token == "\\font_osf") {
461 } else if (token == "\\font_sf_scale") {
462 lex >> fontsSansScale;
463 } else if (token == "\\font_tt_scale") {
464 lex >> fontsTypewriterScale;
465 } else if (token == "\\paragraph_separation") {
468 paragraph_separation = parseptranslator().find(parsep);
469 } else if (token == "\\defskip") {
471 pimpl_->defskip = VSpace(lex.getString());
472 } else if (token == "\\quotes_language") {
475 quotes_language = quoteslangtranslator().find(quotes_lang);
476 } else if (token == "\\papersize") {
479 papersize = papersizetranslator().find(ppsize);
480 } else if (token == "\\use_geometry") {
482 } else if (token == "\\use_amsmath") {
485 use_amsmath = amstranslator().find(use_ams);
486 } else if (token == "\\cite_engine") {
489 cite_engine = citeenginetranslator().find(engine);
490 } else if (token == "\\use_bibtopic") {
492 } else if (token == "\\tracking_changes") {
494 } else if (token == "\\output_changes") {
495 lex >> outputChanges;
496 } else if (token == "\\branch") {
498 docstring branch = lex.getDocString();
499 branchlist().add(branch);
502 string const tok = lex.getString();
503 if (tok == "\\end_branch")
505 Branch * branch_ptr = branchlist().find(branch);
506 if (tok == "\\selected") {
509 branch_ptr->setSelected(lex.getInteger());
511 // not yet operational
512 if (tok == "\\color") {
514 string color = lex.getString();
516 branch_ptr->setColor(color);
517 // Update also the LColor table:
519 color = lcolor.getX11Name(LColor::background);
521 lcolor.setColor(to_utf8(branch), color);
525 } else if (token == "\\author") {
527 istringstream ss(lex.getString());
530 author_map.push_back(pimpl_->authorlist.record(a));
531 } else if (token == "\\paperorientation") {
534 orientation = paperorientationtranslator().find(orient);
535 } else if (token == "\\paperwidth") {
537 } else if (token == "\\paperheight") {
539 } else if (token == "\\leftmargin") {
541 } else if (token == "\\topmargin") {
543 } else if (token == "\\rightmargin") {
545 } else if (token == "\\bottommargin") {
547 } else if (token == "\\headheight") {
549 } else if (token == "\\headsep") {
551 } else if (token == "\\footskip") {
553 } else if (token == "\\paperfontsize") {
555 } else if (token == "\\papercolumns") {
557 } else if (token == "\\papersides") {
560 sides = sidestranslator().find(psides);
561 } else if (token == "\\paperpagestyle") {
563 } else if (token == "\\bullet") {
565 } else if (token == "\\bulletLaTeX") {
566 readBulletsLaTeX(lex);
567 } else if (token == "\\secnumdepth") {
569 } else if (token == "\\tocdepth") {
571 } else if (token == "\\spacing") {
575 if (nspacing == "other") {
578 spacing().set(spacetranslator().find(nspacing), tmp_val);
579 } else if (token == "\\float_placement") {
580 lex >> float_placement;
589 void BufferParams::writeFile(ostream & os) const
591 // The top of the file is written by the buffer.
592 // Prints out the buffer info into the .lyx file given by file
595 os << "\\textclass " << textclasslist[textclass].name() << '\n';
597 // then the the preamble
598 if (!preamble.empty()) {
599 // remove '\n' from the end of preamble
600 string const tmppreamble = rtrim(preamble, "\n");
601 os << "\\begin_preamble\n"
603 << "\n\\end_preamble\n";
607 if (!options.empty()) {
608 os << "\\options " << options << '\n';
611 // then the text parameters
612 if (language != ignore_language)
613 os << "\\language " << language->lang() << '\n';
614 os << "\\inputencoding " << inputenc
615 << "\n\\font_roman " << fontsRoman
616 << "\n\\font_sans " << fontsSans
617 << "\n\\font_typewriter " << fontsTypewriter
618 << "\n\\font_default_family " << fontsDefaultFamily
619 << "\n\\font_sc " << convert<string>(fontsSC)
620 << "\n\\font_osf " << convert<string>(fontsOSF)
621 << "\n\\font_sf_scale " << fontsSansScale
622 << "\n\\font_tt_scale " << fontsTypewriterScale
623 << "\n\\graphics " << graphicsDriver << '\n';
625 if (!float_placement.empty()) {
626 os << "\\float_placement " << float_placement << '\n';
628 os << "\\paperfontsize " << fontsize << '\n';
630 spacing().writeFile(os);
632 os << "\\papersize " << string_papersize[papersize]
633 << "\n\\use_geometry " << convert<string>(use_geometry)
634 << "\n\\use_amsmath " << use_amsmath
635 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
636 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
637 << "\n\\paperorientation " << string_orientation[orientation]
640 BranchList::const_iterator it = branchlist().begin();
641 BranchList::const_iterator end = branchlist().end();
642 for (; it != end; ++it) {
643 os << "\\branch " << to_utf8(it->getBranch())
644 << "\n\\selected " << it->getSelected()
645 << "\n\\color " << lyx::X11hexname(it->getColor())
650 if (!paperwidth.empty())
651 os << "\\paperwidth "
652 << VSpace(paperwidth).asLyXCommand() << '\n';
653 if (!paperheight.empty())
654 os << "\\paperheight "
655 << VSpace(paperheight).asLyXCommand() << '\n';
656 if (!leftmargin.empty())
657 os << "\\leftmargin "
658 << VSpace(leftmargin).asLyXCommand() << '\n';
659 if (!topmargin.empty())
661 << VSpace(topmargin).asLyXCommand() << '\n';
662 if (!rightmargin.empty())
663 os << "\\rightmargin "
664 << VSpace(rightmargin).asLyXCommand() << '\n';
665 if (!bottommargin.empty())
666 os << "\\bottommargin "
667 << VSpace(bottommargin).asLyXCommand() << '\n';
668 if (!headheight.empty())
669 os << "\\headheight "
670 << VSpace(headheight).asLyXCommand() << '\n';
671 if (!headsep.empty())
673 << VSpace(headsep).asLyXCommand() << '\n';
674 if (!footskip.empty())
676 << VSpace(footskip).asLyXCommand() << '\n';
677 os << "\\secnumdepth " << secnumdepth
678 << "\n\\tocdepth " << tocdepth
679 << "\n\\paragraph_separation "
680 << string_paragraph_separation[paragraph_separation]
681 << "\n\\defskip " << getDefSkip().asLyXCommand()
682 << "\n\\quotes_language "
683 << string_quotes_language[quotes_language]
684 << "\n\\papercolumns " << columns
685 << "\n\\papersides " << sides
686 << "\n\\paperpagestyle " << pagestyle << '\n';
687 for (int i = 0; i < 4; ++i) {
688 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
689 if (user_defined_bullet(i).getFont() != -1) {
690 os << "\\bullet " << i << " "
691 << user_defined_bullet(i).getFont() << " "
692 << user_defined_bullet(i).getCharacter() << " "
693 << user_defined_bullet(i).getSize() << "\n";
697 os << "\\bulletLaTeX " << i << " \""
698 << lyx::to_ascii(user_defined_bullet(i).getText())
704 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
705 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
707 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
708 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
709 for (; a_it != a_end; ++a_it) {
710 os << "\\author " << a_it->second << "\n";
715 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
716 TexRow & texrow) const
718 os << "\\documentclass";
720 LyXTextClass const & tclass = getLyXTextClass();
722 ostringstream clsoptions; // the document class options.
724 if (tokenPos(tclass.opt_fontsize(),
725 '|', fontsize) >= 0) {
726 // only write if existing in list (and not default)
727 clsoptions << fontsize << "pt,";
730 // custom, A3, B3 and B4 paper sizes need geometry
731 bool nonstandard_papersize = papersize == PAPER_B3
732 || papersize == PAPER_B4
733 || papersize == PAPER_A3
734 || papersize == PAPER_CUSTOM;
739 clsoptions << "a4paper,";
742 clsoptions << "letterpaper,";
745 clsoptions << "a5paper,";
748 clsoptions << "b5paper,";
750 case PAPER_USEXECUTIVE:
751 clsoptions << "executivepaper,";
754 clsoptions << "legalpaper,";
766 if (sides != tclass.sides()) {
768 case LyXTextClass::OneSide:
769 clsoptions << "oneside,";
771 case LyXTextClass::TwoSides:
772 clsoptions << "twoside,";
778 if (columns != tclass.columns()) {
780 clsoptions << "twocolumn,";
782 clsoptions << "onecolumn,";
786 && orientation == ORIENTATION_LANDSCAPE)
787 clsoptions << "landscape,";
789 // language should be a parameter to \documentclass
790 if (language->babel() == "hebrew"
791 && default_language->babel() != "hebrew")
792 // This seems necessary
793 features.useLanguage(default_language);
795 ostringstream language_options;
796 bool const use_babel = features.useBabel();
798 language_options << features.getLanguages();
799 language_options << language->babel();
800 if (lyxrc.language_global_options)
801 clsoptions << language_options.str() << ',';
804 // the user-defined options
805 if (!options.empty()) {
806 clsoptions << options << ',';
809 string strOptions(clsoptions.str());
810 if (!strOptions.empty()) {
811 strOptions = rtrim(strOptions, ",");
813 os << '[' << from_utf8(strOptions) << ']';
816 os << '{' << from_ascii(tclass.latexname()) << "}\n";
818 // end of \documentclass defs
820 // font selection must be done before loading fontenc.sty
822 loadFonts(features, fontsRoman, fontsSans,
823 fontsTypewriter, fontsSC, fontsOSF,
824 fontsSansScale, fontsTypewriterScale);
825 if (!fonts.empty()) {
826 os << from_ascii(fonts);
829 if (fontsDefaultFamily != "default")
830 os << "\\renewcommand{\\familydefault}{\\"
831 << from_ascii(fontsDefaultFamily) << "}\n";
832 // this one is not per buffer
833 if (lyxrc.fontenc != "default") {
834 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
839 if (inputenc == "auto") {
840 string const doc_encoding =
841 language->encoding()->latexName();
843 // Create a list with all the input encodings used
845 std::set<string> encodings =
846 features.getEncodingSet(doc_encoding);
848 os << "\\usepackage[";
849 std::set<string>::const_iterator it = encodings.begin();
850 std::set<string>::const_iterator const end = encodings.end();
851 for (; it != end; ++it)
852 os << from_ascii(*it) << ',';
853 os << from_ascii(doc_encoding) << "]{inputenc}\n";
855 } else if (inputenc != "default") {
856 os << "\\usepackage[" << from_ascii(inputenc)
861 if (use_geometry || nonstandard_papersize) {
862 os << "\\usepackage{geometry}\n";
864 os << "\\geometry{verbose";
865 if (orientation == ORIENTATION_LANDSCAPE)
869 if (!paperwidth.empty())
871 << from_ascii(paperwidth);
872 if (!paperheight.empty())
873 os << ",paperheight="
874 << from_ascii(paperheight);
877 os << ",letterpaper";
882 case PAPER_USEXECUTIVE:
883 os << ",executivepaper";
904 // default papersize ie PAPER_DEFAULT
905 switch (lyxrc.default_papersize) {
906 case PAPER_DEFAULT: // keep compiler happy
908 os << ",letterpaper";
913 case PAPER_USEXECUTIVE:
914 os << ",executivepaper";
934 if (!topmargin.empty())
935 os << ",tmargin=" << from_ascii(topmargin);
936 if (!bottommargin.empty())
937 os << ",bmargin=" << from_ascii(bottommargin);
938 if (!leftmargin.empty())
939 os << ",lmargin=" << from_ascii(leftmargin);
940 if (!rightmargin.empty())
941 os << ",rmargin=" << from_ascii(rightmargin);
942 if (!headheight.empty())
943 os << ",headheight=" << from_ascii(headheight);
944 if (!headsep.empty())
945 os << ",headsep=" << from_ascii(headsep);
946 if (!footskip.empty())
947 os << ",footskip=" << from_ascii(footskip);
952 if (tokenPos(tclass.opt_pagestyle(),
953 '|', pagestyle) >= 0) {
954 if (pagestyle == "fancy") {
955 os << "\\usepackage{fancyhdr}\n";
958 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
962 // Only if class has a ToC hierarchy
963 if (tclass.hasTocLevels()) {
964 if (secnumdepth != tclass.secnumdepth()) {
965 os << "\\setcounter{secnumdepth}{"
970 if (tocdepth != tclass.tocdepth()) {
971 os << "\\setcounter{tocdepth}{"
978 if (paragraph_separation) {
979 switch (getDefSkip().kind()) {
980 case VSpace::SMALLSKIP:
981 os << "\\setlength\\parskip{\\smallskipamount}\n";
983 case VSpace::MEDSKIP:
984 os << "\\setlength\\parskip{\\medskipamount}\n";
986 case VSpace::BIGSKIP:
987 os << "\\setlength\\parskip{\\bigskipamount}\n";
990 os << "\\setlength\\parskip{"
991 << from_utf8(getDefSkip().length().asLatexString())
994 default: // should never happen // Then delete it.
995 os << "\\setlength\\parskip{\\medskipamount}\n";
1000 os << "\\setlength\\parindent{0pt}\n";
1004 // If we use jurabib, we have to call babel here.
1005 if (use_babel && features.isRequired("jurabib")) {
1006 os << from_ascii(babelCall(language_options.str()))
1008 << from_ascii(features.getBabelOptions());
1012 // Now insert the LyX specific LaTeX commands...
1014 // The optional packages;
1015 string lyxpreamble(features.getPackages());
1017 // this might be useful...
1018 lyxpreamble += "\n\\makeatletter\n";
1020 // Some macros LyX will need
1021 string tmppreamble(features.getMacros());
1023 if (!tmppreamble.empty()) {
1024 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1025 "LyX specific LaTeX commands.\n"
1026 + tmppreamble + '\n';
1029 // the text class specific preamble
1030 tmppreamble = features.getTClassPreamble();
1031 if (!tmppreamble.empty()) {
1032 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1033 "Textclass specific LaTeX commands.\n"
1034 + tmppreamble + '\n';
1037 /* the user-defined preamble */
1038 if (!preamble.empty()) {
1039 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1040 "User specified LaTeX commands.\n"
1044 // Itemize bullet settings need to be last in case the user
1045 // defines their own bullets that use a package included
1046 // in the user-defined preamble -- ARRae
1047 // Actually it has to be done much later than that
1048 // since some packages like frenchb make modifications
1049 // at \begin{document} time -- JMarc
1051 for (int i = 0; i < 4; ++i) {
1052 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1053 if (bullets_def.empty())
1054 bullets_def="\\AtBeginDocument{\n";
1055 bullets_def += " \\def\\labelitemi";
1057 // `i' is one less than the item to modify
1064 bullets_def += "ii";
1071 bullets_def += '{' +
1072 lyx::to_ascii(user_defined_bullet(i).getText())
1077 if (!bullets_def.empty())
1078 lyxpreamble += bullets_def + "}\n\n";
1080 // We try to load babel late, in case it interferes
1081 // with other packages.
1082 // Jurabib has to be called after babel, though.
1083 if (use_babel && !features.isRequired("jurabib")) {
1084 lyxpreamble += babelCall(language_options.str()) + '\n';
1085 lyxpreamble += features.getBabelOptions();
1088 lyxpreamble += "\\makeatother\n";
1090 // dvipost settings come after everything else
1091 if (features.isAvailable("dvipost") && outputChanges) {
1094 "\\dvipost{osstart color push Red}\n"
1095 "\\dvipost{osend color pop}\n"
1096 "\\dvipost{cbstart color push Blue}\n"
1097 "\\dvipost{cbend color pop}\n";
1101 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1102 for (int j = 0; j != nlines; ++j) {
1107 os << from_utf8(lyxpreamble);
1112 void BufferParams::useClassDefaults()
1114 LyXTextClass const & tclass = textclasslist[textclass];
1116 sides = tclass.sides();
1117 columns = tclass.columns();
1118 pagestyle = tclass.pagestyle();
1119 options = tclass.options();
1120 // Only if class has a ToC hierarchy
1121 if (tclass.hasTocLevels()) {
1122 secnumdepth = tclass.secnumdepth();
1123 tocdepth = tclass.tocdepth();
1128 bool BufferParams::hasClassDefaults() const
1130 LyXTextClass const & tclass = textclasslist[textclass];
1132 return (sides == tclass.sides()
1133 && columns == tclass.columns()
1134 && pagestyle == tclass.pagestyle()
1135 && options == tclass.options()
1136 && secnumdepth == tclass.secnumdepth()
1137 && tocdepth == tclass.tocdepth());
1141 LyXTextClass const & BufferParams::getLyXTextClass() const
1143 return textclasslist[textclass];
1147 LyXFont const BufferParams::getFont() const
1149 LyXFont f = getLyXTextClass().defaultfont();
1150 f.setLanguage(language);
1151 if (fontsDefaultFamily == "rmdefault")
1152 f.setFamily(LyXFont::ROMAN_FAMILY);
1153 else if (fontsDefaultFamily == "sfdefault")
1154 f.setFamily(LyXFont::SANS_FAMILY);
1155 else if (fontsDefaultFamily == "ttdefault")
1156 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1161 void BufferParams::readPreamble(LyXLex & lex)
1163 if (lex.getString() != "\\begin_preamble")
1164 lyxerr << "Error (BufferParams::readPreamble):"
1165 "consistency check failed." << endl;
1167 preamble = lex.getLongString("\\end_preamble");
1171 void BufferParams::readLanguage(LyXLex & lex)
1173 if (!lex.next()) return;
1175 string const tmptok = lex.getString();
1177 // check if tmptok is part of tex_babel in tex-defs.h
1178 language = languages.getLanguage(tmptok);
1180 // Language tmptok was not found
1181 language = default_language;
1182 lyxerr << "Warning: Setting language `"
1183 << tmptok << "' to `" << language->lang()
1189 void BufferParams::readGraphicsDriver(LyXLex & lex)
1191 if (!lex.next()) return;
1193 string const tmptok = lex.getString();
1194 // check if tmptok is part of tex_graphics in tex_defs.h
1197 string const test = tex_graphics[n++];
1199 if (test == tmptok) {
1200 graphicsDriver = tmptok;
1202 } else if (test == "") {
1204 "Warning: graphics driver `$$Token' not recognized!\n"
1205 " Setting graphics driver to `default'.\n");
1206 graphicsDriver = "default";
1213 void BufferParams::readBullets(LyXLex & lex)
1215 if (!lex.next()) return;
1217 int const index = lex.getInteger();
1219 int temp_int = lex.getInteger();
1220 user_defined_bullet(index).setFont(temp_int);
1221 temp_bullet(index).setFont(temp_int);
1223 user_defined_bullet(index).setCharacter(temp_int);
1224 temp_bullet(index).setCharacter(temp_int);
1226 user_defined_bullet(index).setSize(temp_int);
1227 temp_bullet(index).setSize(temp_int);
1231 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1233 // The bullet class should be able to read this.
1234 if (!lex.next()) return;
1235 int const index = lex.getInteger();
1237 docstring const temp_str = lex.getDocString();
1239 user_defined_bullet(index).setText(temp_str);
1240 temp_bullet(index).setText(temp_str);
1244 string const BufferParams::paperSizeName() const
1246 char real_papersize = papersize;
1247 if (real_papersize == PAPER_DEFAULT)
1248 real_papersize = lyxrc.default_papersize;
1250 switch (real_papersize) {
1259 case PAPER_USEXECUTIVE:
1263 case PAPER_USLETTER:
1270 string const BufferParams::dvips_options() const
1275 && papersize == PAPER_CUSTOM
1276 && !lyxrc.print_paper_dimension_flag.empty()
1277 && !paperwidth.empty()
1278 && !paperheight.empty()) {
1279 // using a custom papersize
1280 result = lyxrc.print_paper_dimension_flag;
1281 result += ' ' + paperwidth;
1282 result += ',' + paperheight;
1284 string const paper_option = paperSizeName();
1285 if (paper_option != "letter" ||
1286 orientation != ORIENTATION_LANDSCAPE) {
1287 // dvips won't accept -t letter -t landscape.
1288 // In all other cases, include the paper size
1290 result = lyxrc.print_paper_flag;
1291 result += ' ' + paper_option;
1294 if (orientation == ORIENTATION_LANDSCAPE &&
1295 papersize != PAPER_CUSTOM)
1296 result += ' ' + lyxrc.print_landscape_flag;
1301 string const BufferParams::babelCall(string const & lang_opts) const
1303 string tmp = lyxrc.language_package;
1304 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1305 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1310 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1311 string const & sf, string const & tt,
1312 bool const & sc, bool const & osf,
1313 int const & sfscale, int const & ttscale) const
1315 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1316 several packages have been replaced by others, that might not
1317 be installed on every system. We have to take care for that
1318 (see psnfss.pdf). We try to support all psnfss fonts as well
1319 as the fonts that have become de facto standard in the LaTeX
1320 world (e.g. Latin Modern). We do not support obsolete fonts
1321 (like PSLatex). In general, it should be possible to mix any
1322 rm font with any sf or tt font, respectively. (JSpitzm)
1324 -- separate math fonts.
1327 if (rm == "default" && sf == "default" && tt == "default")
1334 // Computer Modern (must be explicitely selectable -- there might be classes
1335 // that define a different default font!
1337 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1338 // osf for Computer Modern needs eco.sty
1340 os << "\\usepackage{eco}\n";
1342 // Latin Modern Roman
1343 else if (rm == "lmodern")
1344 os << "\\usepackage{lmodern}\n";
1346 else if (rm == "ae") {
1347 // not needed when using OT1 font encoding.
1348 if (lyxrc.fontenc != "default")
1349 os << "\\usepackage{ae,aecompl}\n";
1352 else if (rm == "times") {
1353 // try to load the best available package
1354 if (features.isAvailable("mathptmx"))
1355 os << "\\usepackage{mathptmx}\n";
1356 else if (features.isAvailable("mathptm"))
1357 os << "\\usepackage{mathptm}\n";
1359 os << "\\usepackage{times}\n";
1362 else if (rm == "palatino") {
1363 // try to load the best available package
1364 if (features.isAvailable("mathpazo")) {
1365 os << "\\usepackage";
1371 // "osf" includes "sc"!
1375 os << "{mathpazo}\n";
1377 else if (features.isAvailable("mathpple"))
1378 os << "\\usepackage{mathpple}\n";
1380 os << "\\usepackage{palatino}\n";
1383 else if (rm == "utopia") {
1384 // fourier supersedes utopia.sty, but does
1385 // not work with OT1 encoding.
1386 if (features.isAvailable("fourier")
1387 && lyxrc.fontenc != "default") {
1388 os << "\\usepackage";
1399 os << "{fourier}\n";
1402 os << "\\usepackage{utopia}\n";
1404 // Bera (complete fontset)
1405 else if (rm == "bera" && sf == "default" && tt == "default")
1406 os << "\\usepackage{bera}\n";
1408 else if (rm != "default")
1409 os << "\\usepackage" << "{" << rm << "}\n";
1412 // Helvetica, Bera Sans
1413 if (sf == "helvet" || sf == "berasans") {
1415 os << "\\usepackage[scaled=" << float(sfscale) / 100
1416 << "]{" << sf << "}\n";
1418 os << "\\usepackage{" << sf << "}\n";
1421 else if (sf == "avant")
1422 os << "\\usepackage{" << sf << "}\n";
1423 // Computer Modern, Latin Modern, CM Bright
1424 else if (sf != "default")
1425 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1427 // monospaced/typewriter
1428 // Courier, LuxiMono
1429 if (tt == "luximono" || tt == "beramono") {
1431 os << "\\usepackage[scaled=" << float(ttscale) / 100
1432 << "]{" << tt << "}\n";
1434 os << "\\usepackage{" << tt << "}\n";
1437 else if (tt == "courier" )
1438 os << "\\usepackage{" << tt << "}\n";
1439 // Computer Modern, Latin Modern, CM Bright
1440 else if (tt != "default")
1441 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";