]> git.lyx.org Git - lyx.git/blobdiff - src/BufferParams.cpp
Move part of Buffer::validate into a new method BufferParams::validate.
[lyx.git] / src / BufferParams.cpp
index 6f2e3ed3a9dbc18801e7beba3fa5b6842c9ac77d..11145b8189424076579b679df22ec667744476da 100644 (file)
 #include "BranchList.h"
 #include "buffer_funcs.h"
 #include "Bullet.h"
-#include "debug.h"
+#include "Color.h"
 #include "Encoding.h"
-#include "gettext.h"
 #include "Language.h"
 #include "LaTeXFeatures.h"
-#include "Messages.h"
 #include "ModuleList.h"
-#include "Color.h"
 #include "Font.h"
 #include "Lexer.h"
 #include "LyXRC.h"
 #include "PDFOptions.h"
 
 #include "frontends/alert.h"
+
 #include "insets/InsetListingsParams.h"
 
 #include "support/convert.h"
+#include "support/debug.h"
+#include "support/docstream.h"
+#include "support/FileName.h"
 #include "support/filetools.h"
+#include "support/gettext.h"
+#include "support/Messages.h"
 #include "support/Translator.h"
 #include "support/lstrings.h"
 
-#include <boost/array.hpp>
-
 #include <algorithm>
 #include <sstream>
 
-using std::count;
-using std::endl;
-using std::find;
-using std::string;
-using std::istringstream;
-using std::ostream;
-using std::ostringstream;
-using std::pair;
-using std::string;
-using lyx::support::FileName;
-using lyx::support::libFileSearch;
-using lyx::support::bformat;
-using lyx::support::rtrim;
-using lyx::support::tokenPos;
-using lyx::support::prefixIs;
+using namespace std;
+using namespace lyx::support;
 
 
 static char const * const string_paragraph_separation[] = {
@@ -149,7 +137,7 @@ QuotesLangTranslator const & quoteslangtranslator()
 
 
 // Paper size
-typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
+typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
 
 
 PaperSizeTranslator const init_papersizetranslator()
@@ -196,13 +184,13 @@ PaperOrientationTranslator const & paperorientationtranslator()
 
 
 // Page sides
-typedef Translator<int, TextClass::PageSides> SidesTranslator;
+typedef Translator<int, PageSides> SidesTranslator;
 
 
 SidesTranslator const init_sidestranslator()
 {
-       SidesTranslator translator(1, TextClass::OneSide);
-       translator.addPair(2, TextClass::TwoSides);
+       SidesTranslator translator(1, OneSide);
+       translator.addPair(2, TwoSides);
        return translator;
 }
 
@@ -287,8 +275,8 @@ public:
 
        AuthorList authorlist;
        BranchList branchlist;
-       boost::array<Bullet, 4> temp_bullets;
-       boost::array<Bullet, 4> user_defined_bullets;
+       Bullet temp_bullets[4];
+       Bullet user_defined_bullets[4];
        Spacing spacing;
        /** This is the amount of space used for paragraph_separation "skip",
         * and for detached paragraphs in "indented" documents.
@@ -353,7 +341,7 @@ BufferParams::BufferParams()
        fontsTypewriterScale = 100;
        inputenc = "auto";
        graphicsDriver = "default";
-       sides = TextClass::OneSide;
+       sides = OneSide;
        columns = 1;
        listings_params = string();
        pagestyle = "default";
@@ -465,25 +453,34 @@ void BufferParams::setDefSkip(VSpace const & vs)
 }
 
 
-string const BufferParams::readToken(Lexer & lex, string const & token)
+string const BufferParams::readToken(Lexer & lex, string const & token,
+       FileName const & filepath)
 {
        if (token == "\\textclass") {
                lex.next();
                string const classname = lex.getString();
+               // if there exists a local layout file, ignore the system one
+               // NOTE: in this case, the textclass (.cls file) is assumed to be available.
                pair<bool, lyx::textclass_type> pp =
-                       textclasslist.numberOfClass(classname);
-               if (pp.first) {
+                       make_pair(false, textclass_type(0));
+               if (!filepath.empty())
+                       pp = textclasslist.addTextClass(
+                               classname, filepath.absFilename());
+               if (pp.first)
                        setBaseClass(pp.second);
-               } else {
-                       // if text class does not exist, try to load it from filepath
-                       pp = textclasslist.addTextClass(classname, filepath);
-                       if (pp.first) {
+               else {
+                       pp = textclasslist.numberOfClass(classname);
+                       if (pp.first)
                                setBaseClass(pp.second);
-                       } else {
+                       else {
+                               // a warning will be given for unknown class
                                setBaseClass(defaultTextclass());
                                return classname;
                        }
                }
+               // FIXME: this warning will be given even if there exists a local .cls
+               // file. Even worse, the .lyx file can not be compiled or exported
+               // because the textclass is marked as unavilable.
                if (!getTextClass().isTeXClassAvailable()) {
                        docstring const msg =
                                bformat(_("The layout file requested by this document,\n"
@@ -584,7 +581,7 @@ string const BufferParams::readToken(Lexer & lex, string const & token)
                                        branch_ptr->setColor(color);
                                // Update also the Color table:
                                if (color == "none")
-                                       color = lcolor.getX11Name(Color::background);
+                                       color = lcolor.getX11Name(Color_background);
                                // FIXME UNICODE
                                lcolor.setColor(to_utf8(branch), color);
 
@@ -811,6 +808,77 @@ void BufferParams::writeFile(ostream & os) const
 }
 
 
+void BufferParams::validate(LaTeXFeatures & features) const
+{
+       if (outputChanges) {
+               bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
+               bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
+                                 LaTeXFeatures::isAvailable("xcolor");
+
+               switch (features.runparams().flavor) {
+               case OutputParams::LATEX:
+                       if (dvipost) {
+                               features.require("ct-dvipost");
+                               features.require("dvipost");
+                       } else if (xcolorsoul) {
+                               features.require("ct-xcolor-soul");
+                               features.require("soul");
+                               features.require("xcolor");
+                       } else {
+                               features.require("ct-none");
+                       }
+                       break;
+               case OutputParams::PDFLATEX:
+                       if (xcolorsoul) {
+                               features.require("ct-xcolor-soul");
+                               features.require("soul");
+                               features.require("xcolor");
+                               // improves color handling in PDF output
+                               features.require("pdfcolmk"); 
+                       } else {
+                               features.require("ct-none");
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       // Floats with 'Here definitely' as default setting.
+       if (float_placement.find('H') != string::npos)
+               features.require("float");
+
+       // AMS Style is at document level
+       if (use_amsmath == package_on
+           || getTextClass().provides("amsmath"))
+               features.require("amsmath");
+       if (use_esint == package_on)
+               features.require("esint");
+
+       // the bullet shapes are buffer level not paragraph level
+       // so they are tested here
+       for (int i = 0; i < 4; ++i) {
+               if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) 
+                       continue;
+               int const font = user_defined_bullet(i).getFont();
+               if (font == 0) {
+                       int const c = user_defined_bullet(i).getCharacter();
+                       if (c == 16
+                           || c == 17
+                           || c == 25
+                           || c == 26
+                           || c == 31) {
+                               features.require("latexsym");
+                       }
+               } else if (font == 1) {
+                       features.require("amssymb");
+               } else if (font >= 2 && font <= 5) {
+                       features.require("pifont");
+               }
+       }
+}
+
+
 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
                              TexRow & texrow) const
 {
@@ -864,10 +932,10 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
        // if needed
        if (sides != tclass.sides()) {
                switch (sides) {
-               case TextClass::OneSide:
+               case OneSide:
                        clsoptions << "oneside,";
                        break;
-               case TextClass::TwoSides:
+               case TwoSides:
                        clsoptions << "twoside,";
                        break;
                }
@@ -901,8 +969,9 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
                        language_options << language->babel();
                }
                // when Vietnamese is used, babel must directly be loaded with the
-               // language options, not in the class options
-               int viet = language_options.str().find("vietnam");
+               // language options, not in the class options, see
+               // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
+               size_t viet = language_options.str().find("vietnam");
                // viet = string::npos when not found
                if (lyxrc.language_global_options && !language_options.str().empty()
                        && viet == string::npos)
@@ -1134,8 +1203,12 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
        // translate the word "Index" to the German "Stichwortverzeichnis".
        // For more infos why this place was chosen, see
        // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128425.html
-       // if you encounter problem, you can shift babel to its old place behind
-       // the user-defined preamble
+       // If you encounter problems, you can shift babel to its old place behind
+       // the user-defined preamble. But in this case you must change the Vietnamese
+       // support from currently "\usepackage[vietnamese]{babel}" to:
+       // \usepackage{vietnamese}
+       // \usepackage{babel}
+       // because vietnamese must be loaded before hyperref
        if (use_babel && !features.isRequired("jurabib")) {
                // FIXME UNICODE
                lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
@@ -1143,10 +1216,16 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
        }
 
        // When the language "japanese-plain" is used, the package "japanese" must
-       // be loaded behind babel (it provides babel support for Japanese)
-       // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
-       if (language->lang() == "japanese-plain")
+       // be loaded behind babel (it provides babel support for Japanese) but before
+       // hyperref, see
+       // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
+       if (language->lang() == "japanese-plain" &&
+               !getTextClass().provides("japanese")) {
+               //load babel in case it was not loaded due to an empty language list
+               if (language_options.str().empty())
+                       lyxpreamble += "\\usepackage{babel}\n";
                lyxpreamble += "\\usepackage{japanese}\n";
+       }
 
        // PDF support.
        // * Hyperref manual: "Make sure it comes last of your loaded
@@ -1157,7 +1236,8 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
        // * Has to be loaded before the "LyX specific LaTeX commands" to
        //   avoid errors with algorithm floats.
        odocstringstream oss;
-       pdfoptions().writeLaTeX(oss);
+       // use hyperref explicitely when it is required
+       pdfoptions().writeLaTeX(oss, features.isRequired("hyperref"));
        lyxpreamble += oss.str();
 
        // this might be useful...
@@ -1325,7 +1405,7 @@ void BufferParams::makeTextClass()
                                bformat(_("The module %1$s has been requested by\n"
                                        "this document but has not been found in the list of\n"
                                        "available modules. If you recently installed it, you\n"
-                                       "probalby need to reconfigure LyX.\n"), from_utf8(modName));
+                                       "probably need to reconfigure LyX.\n"), from_utf8(modName));
                        frontend::Alert::warning(_("Module not available"),
                                        msg + _("Some layouts may not be available."));
                        lyxerr << "BufferParams::makeTextClass(): Module " <<
@@ -1339,7 +1419,7 @@ void BufferParams::makeTextClass()
 }
 
 
-std::vector<string> const & BufferParams::getModules() const {
+vector<string> const & BufferParams::getModules() const {
        return layoutModules_;
 }
 
@@ -1361,11 +1441,11 @@ bool BufferParams::addLayoutModule(string modName, bool makeClass) {
 }
 
 
-bool BufferParams::addLayoutModules(std::vector<string>modNames)
+bool BufferParams::addLayoutModules(vector<string>modNames)
 {
        bool retval = true;
-       std::vector<string>::const_iterator it = modNames.begin();
-       std::vector<string>::const_iterator end = modNames.end();
+       vector<string>::const_iterator it = modNames.begin();
+       vector<string>::const_iterator end = modNames.end();
        for (; it != end; ++it)
                retval &= addLayoutModule(*it, false);
        makeTextClass();
@@ -1381,15 +1461,14 @@ void BufferParams::clearLayoutModules() {
 
 Font const BufferParams::getFont() const
 {
-       Font f = getTextClass().defaultfont();
-       f.setLanguage(language);
+       FontInfo f = getTextClass().defaultfont();
        if (fontsDefaultFamily == "rmdefault")
-               f.setFamily(Font::ROMAN_FAMILY);
+               f.setFamily(ROMAN_FAMILY);
        else if (fontsDefaultFamily == "sfdefault")
-               f.setFamily(Font::SANS_FAMILY);
+               f.setFamily(SANS_FAMILY);
        else if (fontsDefaultFamily == "ttdefault")
-               f.setFamily(Font::TYPEWRITER_FAMILY);
-       return f;
+               f.setFamily(TYPEWRITER_FAMILY);
+       return Font(f, language);
 }
 
 
@@ -1561,8 +1640,9 @@ string const BufferParams::babelCall(string const & lang_opts) const
        if (lang_opts.empty())
                return string();
        // when Vietnamese is used, babel must directly be loaded with the
-       // language options
-       int viet = lang_opts.find("vietnam");
+       // language options, see
+       // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
+       size_t viet = lang_opts.find("vietnam");
        // viet = string::npos when not found
        if (!lyxrc.language_global_options || viet != string::npos)
                return "\\usepackage[" + lang_opts + "]{babel}";
@@ -1581,7 +1661,7 @@ void BufferParams::writeEncodingPreamble(odocstream & os,
 
                // Create a list with all the input encodings used
                // in the document
-               std::set<string> encodings =
+               set<string> encodings =
                        features.getEncodingSet(doc_encoding);
 
                // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the
@@ -1593,8 +1673,8 @@ void BufferParams::writeEncodingPreamble(odocstream & os,
 
                if (!encodings.empty() || package == Encoding::inputenc) {
                        os << "\\usepackage[";
-                       std::set<string>::const_iterator it = encodings.begin();
-                       std::set<string>::const_iterator const end = encodings.end();
+                       set<string>::const_iterator it = encodings.begin();
+                       set<string>::const_iterator const end = encodings.end();
                        if (it != end) {
                                os << from_ascii(*it);
                                ++it;
@@ -1609,7 +1689,7 @@ void BufferParams::writeEncodingPreamble(odocstream & os,
                        os << "]{inputenc}\n";
                        texrow.newline();
                }
-               if (package == Encoding::CJK) {
+               if (package == Encoding::CJK || features.mustProvide("CJK")) {
                        os << "\\usepackage{CJK}\n";
                        texrow.newline();
                }