]> git.lyx.org Git - features.git/blobdiff - src/BufferParams.cpp
The way this was done here is inconsistent with how it is done
[features.git] / src / BufferParams.cpp
index 7a527a75927e35bb79b897edd2cc2c213b0d4645..269c74c45e9d114b1d3de64a581f89a57d13d9a9 100644 (file)
@@ -20,6 +20,7 @@
 #include "Author.h"
 #include "LayoutFile.h"
 #include "BranchList.h"
+#include "Buffer.h"
 #include "buffer_funcs.h"
 #include "Bullet.h"
 #include "Color.h"
@@ -53,6 +54,7 @@
 #include "support/gettext.h"
 #include "support/Messages.h"
 #include "support/mutex.h"
+#include "support/Package.h"
 #include "support/Translator.h"
 #include "support/lstrings.h"
 
@@ -601,6 +603,8 @@ void BufferParams::setDefSkip(VSpace const & vs)
 string BufferParams::readToken(Lexer & lex, string const & token,
        FileName const & filepath)
 {
+       string result;
+
        if (token == "\\textclass") {
                lex.next();
                string const classname = lex.getString();
@@ -609,13 +613,31 @@ string BufferParams::readToken(Lexer & lex, string const & token,
                // be available.
                string tcp;
                LayoutFileList & bcl = LayoutFileList::get();
-               if (!filepath.empty())
-                       tcp = bcl.addLocalLayout(classname, filepath.absFileName());
+               if (!filepath.empty()) {
+                       // If classname is an absolute path, the document is
+                       // using a local layout file which could not be accessed
+                       // by a relative path. In this case the path is correct
+                       // even if the document was moved to a different
+                       // location. However, we will have a problem if the
+                       // document was generated on a different platform.
+                       bool isabsolute = FileName::isAbsolute(classname);
+                       string const classpath = onlyPath(classname);
+                       string const path = isabsolute ? classpath
+                               : FileName(addPath(filepath.absFileName(),
+                                               classpath)).realPath();
+                       string const oldpath = isabsolute ? string()
+                               : FileName(addPath(origin, classpath)).realPath();
+                       tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
+               }
                // that returns non-empty if a "local" layout file is found.
-               if (!tcp.empty())
-                       setBaseClass(tcp);
-               else
-                       setBaseClass(classname);
+               if (!tcp.empty()) {
+                       result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
+                                               from_utf8(filepath.absFileName())));
+                       if (result.empty())
+                               result = ".";
+                       setBaseClass(onlyFileName(tcp));
+               } else
+                       setBaseClass(onlyFileName(classname));
                // We assume that a tex class exists for local or unknown
                // layouts so this warning, will only be given for system layouts.
                if (!baseClass()->isTeXClassAvailable()) {
@@ -634,7 +656,15 @@ string BufferParams::readToken(Lexer & lex, string const & token,
                                                 "See section 3.1.2.2 (Class Availability) of the\n"
                                                 "User's Guide for more information."), desc, prereqs);
                        frontend::Alert::warning(_("Document class not available"),
-                                      msg);
+                                      msg, true);
+               }
+       } else if (token == "\\origin") {
+               lex.eatLine();
+               origin = lex.getString();
+               string const sysdirprefix = "/systemlyxdir/";
+               if (prefixIs(origin, sysdirprefix)) {
+                       origin.replace(0, sysdirprefix.length() - 1,
+                               package().system_support().absFileName());
                }
        } else if (token == "\\begin_preamble") {
                readPreamble(lex);
@@ -658,6 +688,19 @@ string BufferParams::readToken(Lexer & lex, string const & token,
        } else if (token == "\\master") {
                lex.eatLine();
                master = lex.getString();
+               if (!filepath.empty() && FileName::isAbsolute(origin)) {
+                       bool const isabs = FileName::isAbsolute(master);
+                       FileName const abspath(isabs ? master : origin + master);
+                       bool const moved = filepath != FileName(origin);
+                       if (moved && abspath.exists()) {
+                               docstring const path = isabs
+                                       ? from_utf8(master)
+                                       : from_utf8(abspath.realPath());
+                               docstring const refpath =
+                                       from_utf8(filepath.absFileName());
+                               master = to_utf8(makeRelPath(path, refpath));
+                       }
+               }
        } else if (token == "\\suppress_date") {
                lex >> suppress_date;
        } else if (token == "\\justification") {
@@ -936,17 +979,28 @@ string BufferParams::readToken(Lexer & lex, string const & token,
                return token;
        }
 
-       return string();
+       return result;
 }
 
 
-void BufferParams::writeFile(ostream & os) const
+void BufferParams::writeFile(ostream & os, Buffer const * buf) const
 {
        // The top of the file is written by the buffer.
        // Prints out the buffer info into the .lyx file given by file
 
+       // the document directory
+       string filepath = buf->filePath();
+       string const sysdir = package().system_support().absFileName();
+       if (prefixIs(filepath, sysdir))
+               filepath.replace(0, sysdir.length(), "/systemlyxdir/");
+       else if (!lyxrc.save_origin)
+               filepath = "unavailable";
+       os << "\\origin " << filepath << '\n';
+
        // the textclass
-       os << "\\textclass " << baseClass()->name() << '\n';
+       os << "\\textclass " << buf->includedFilePath(addName(buf->layoutPos(),
+                                               baseClass()->name()), "layout")
+          << '\n';
 
        // then the preamble
        if (!preamble.empty()) {
@@ -1302,7 +1356,8 @@ void BufferParams::validate(LaTeXFeatures & features) const
        }
 
        // some languages are only available via polyglossia
-       if (features.runparams().flavor == OutputParams::XETEX
+       if ((features.runparams().flavor == OutputParams::XETEX
+            || features.runparams().flavor == OutputParams::LUATEX)
            && (features.hasPolyglossiaExclusiveLanguages()
                || useNonTeXFonts))
                features.require("polyglossia");
@@ -1326,6 +1381,11 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
        // are doing!
        if (features.mustProvide("fix-cm"))
                os << "\\RequirePackage{fix-cm}\n";
+       // Likewise for fixltx2e. If other packages conflict with this policy,
+       // treat it as a package bug (and report it!)
+       // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
+       if (features.mustProvide("fixltx2e"))
+               os << "\\RequirePackage{fixltx2e}\n";
 
        os << "\\documentclass";
 
@@ -1494,18 +1554,8 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
        // XeTeX and LuaTeX (with OS fonts) do not need fontenc
        if (!useNonTeXFonts && !features.isProvided("fontenc")
            && font_encoding() != "default") {
-               vector<string> fontencs;
-               // primary language font encoding and default encoding
-               if (ascii_lowercase(language->fontenc()) != "none") {
-                       vector<string> fencs = getVectorFromString(font_encoding());
-                       fontencs.insert(fontencs.end(), fencs.begin(), fencs.end());
-                       fencs = getVectorFromString(language->fontenc());
-                       vector<string>::const_iterator fit = fencs.begin();
-                       for (; fit != fencs.end(); ++fit) {
-                               if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
-                                       fontencs.push_back(*fit);
-                       }
-               }
+               // get main font encodings
+               vector<string> fontencs = font_encodings();
                // get font encodings of secondary languages
                features.getFontEncodings(fontencs);
                if (!fontencs.empty()) {
@@ -1952,7 +2002,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
                        + atlyxpreamble + "\\makeatother\n\n";
 
        // We try to load babel late, in case it interferes with other packages.
-       // Jurabib, hyperref, varioref and listings (bug 8995) have to be
+       // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
        // called after babel, though.
        if (use_babel && !features.isRequired("jurabib")
            && !features.isRequired("hyperref")
@@ -1965,6 +2015,8 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
                                                   features.needBabelLangOptions())) + '\n';
                lyxpreamble += from_utf8(features.getBabelPostsettings());
        }
+       if (features.isRequired("bicaption"))
+               lyxpreamble += "\\usepackage{bicaption}\n";
        if (!listings_params.empty() || features.isRequired("listings"))
                lyxpreamble += "\\usepackage{listings}\n";
        if (!listings_params.empty()) {
@@ -2306,7 +2358,7 @@ OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
        else if (dformat == "lyx")
                result = OutputParams::LYX;
        else if (dformat == "pdflatex")
-               result = OutputParams::PDFLATEX;
+               result = OutputParams::PDFLATEX;
        else if (dformat == "xetex")
                result = OutputParams::XETEX;
        else if (dformat == "luatex")
@@ -2755,7 +2807,31 @@ string const BufferParams::dvips_options() const
 
 string const BufferParams::font_encoding() const
 {
-       return (fontenc == "global") ? lyxrc.fontenc : fontenc;
+       return font_encodings().empty() ? "default" : font_encodings().back();
+}
+
+
+vector<string> const BufferParams::font_encodings() const
+{
+       string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
+
+       vector<string> fontencs;
+
+       // "default" means "no explicit font encoding"
+       if (doc_fontenc != "default") {
+               fontencs = getVectorFromString(doc_fontenc);
+               if (!language->fontenc().empty()
+                   && ascii_lowercase(language->fontenc()) != "none") {
+                       vector<string> fencs = getVectorFromString(language->fontenc());
+                       vector<string>::const_iterator fit = fencs.begin();
+                       for (; fit != fencs.end(); ++fit) {
+                               if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
+                                       fontencs.push_back(*fit);
+                       }
+               }
+       }
+
+       return fontencs;
 }
 
 
@@ -2825,7 +2901,8 @@ void BufferParams::writeEncodingPreamble(otexstream & os,
                // inputenc must be omitted.
                // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
                if ((!encodings.empty() || package == Encoding::inputenc)
-                   && !features.isRequired("japanese")) {
+                   && !features.isRequired("japanese")
+                   && !features.isProvided("inputenc")) {
                        os << "\\usepackage[";
                        set<string>::const_iterator it = encodings.begin();
                        set<string>::const_iterator const end = encodings.end();
@@ -2856,7 +2933,9 @@ void BufferParams::writeEncodingPreamble(otexstream & os,
                        break;
                case Encoding::inputenc:
                        // do not load inputenc if japanese is used
-                       if (features.isRequired("japanese"))
+                       // or if the class provides inputenc
+                       if (features.isRequired("japanese")
+                           || features.isProvided("inputenc"))
                                break;
                        os << "\\usepackage[" << from_ascii(encoding().latexName())
                           << "]{inputenc}\n";
@@ -2992,7 +3071,8 @@ Encoding const & BufferParams::encoding() const
        // FIXME: actually, we should check for the flavor
        // or runparams.isFullyUnicode() here:
        // This check will not work with XeTeX/LuaTeX and tex fonts.
-       // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
+       // Thus we have to reset the encoding in Buffer::makeLaTeXFile
+       // (for export) and Buffer::writeLaTeXSource (for preview).
        if (useNonTeXFonts)
                return *(encodings.fromLyXName("utf8-plain"));
        if (inputenc == "auto" || inputenc == "default")