]> git.lyx.org Git - lyx.git/blobdiff - src/TextClass.cpp
Fix text direction issue for InsetInfo in RTL context
[lyx.git] / src / TextClass.cpp
index 5d01b9d2198444e1d01fb5975cc47d2c6e3523ae..df8aebeef91484155c9ff31c4f9a07f954b2547e 100644 (file)
@@ -62,7 +62,7 @@ namespace lyx {
 // You should also run the development/tools/updatelayouts.py script,
 // to update the format of all of our layout files.
 //
-int const LAYOUT_FORMAT = 63; //spitz: new tags CiteFramework, MaxCiteNames, extended InsetCite syntax.
+int const LAYOUT_FORMAT = 68; //spitz: New layout tag AddToCiteEngine
 
 
 // Layout format for the current lyx file format. Controls which format is
@@ -133,7 +133,7 @@ string translateReadType(TextClass::ReadType rt)
        return string();
 }
 
-} // namespace anon
+} // namespace
 
 
 // This string should not be translated here,
@@ -152,7 +152,7 @@ TextClass::TextClass()
          opt_enginetype_("authoryear|numerical"), opt_fontsize_("10|11|12"),
          opt_pagestyle_("empty|plain|headings|fancy"), pagestyle_("default"),
          columns_(1), sides_(OneSide), secnumdepth_(3), tocdepth_(3),
-         outputType_(LATEX), outputFormat_("latex"),
+         outputType_(LATEX), outputFormat_("latex"), has_output_format_(false),
          defaultfont_(sane_font),
          titletype_(TITLE_COMMAND_AFTER), titlename_("maketitle"),
          min_toclevel_(0), max_toclevel_(0), maxcitenames_(2),
@@ -219,6 +219,7 @@ enum TextClassTags {
        TC_EXCLUDESMODULE,
        TC_HTMLTOCSECTION,
        TC_CITEENGINE,
+       TC_ADDTOCITEENGINE,
        TC_CITEENGINETYPE,
        TC_CITEFORMAT,
        TC_CITEFRAMEWORK,
@@ -232,6 +233,7 @@ enum TextClassTags {
 namespace {
 
 LexerKeyword textClassTags[] = {
+       { "addtociteengine",   TC_ADDTOCITEENGINE },
        { "addtohtmlpreamble", TC_ADDTOHTMLPREAMBLE },
        { "addtohtmlstyles",   TC_ADDTOHTMLSTYLES },
        { "addtopreamble",     TC_ADDTOPREAMBLE },
@@ -282,7 +284,7 @@ LexerKeyword textClassTags[] = {
        { "tocdepth",          TC_TOCDEPTH }
 };
 
-} //namespace anon
+} // namespace
 
 
 bool TextClass::convertLayoutFormat(support::FileName const & filename, ReadType rt)
@@ -408,11 +410,14 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
        if (!lexrc.isOK())
                return ERROR;
 
-       // Format of files before the 'Format' tag was introduced
-       int format = 1;
-       bool error = false;
+       // The first usable line should be
+       // Format LAYOUT_FORMAT
+       if (lexrc.lex() != TC_FORMAT || !lexrc.next()
+           || lexrc.getInteger() != LAYOUT_FORMAT)
+               return FORMAT_MISMATCH;
 
        // parsing
+       bool error = false;
        while (lexrc.isOK() && !error) {
                int le = lexrc.lex();
 
@@ -437,13 +442,15 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                switch (static_cast<TextClassTags>(le)) {
 
                case TC_FORMAT:
-                       if (lexrc.next())
-                               format = lexrc.getInteger();
+                       lexrc.next();
+                       lexrc.printError("Duplicate Format directive");
                        break;
 
                case TC_OUTPUTFORMAT:
-                       if (lexrc.next())
+                       if (lexrc.next()) {
                                outputFormat_ = lexrc.getString();
+                               has_output_format_ = true;
+                       }
                        break;
 
                case TC_OUTPUTTYPE:
@@ -463,8 +470,13 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
 
                case TC_INPUT: // Include file
                        if (lexrc.next()) {
+                               FileName tmp;
                                string const inc = lexrc.getString();
-                               FileName tmp = libFileSearch("layouts", inc,
+                               if (!path().empty() && (prefixIs(inc, "./") ||
+                                                       prefixIs(inc, "../")))
+                                       tmp = fileSearch(path(), inc, "layout");
+                               else
+                                       tmp = libFileSearch("layouts", inc,
                                                            "layout");
 
                                if (tmp.empty()) {
@@ -512,9 +524,9 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                                error = !readStyle(lexrc, lay);
                                break;
                        }
-                       
+
                        bool const have_layout = hasLayout(name);
-                       
+
                        // If the layout already exists, then we want to add it to
                        // the existing layout, as long as we are not in an ProvideStyle
                        // block.
@@ -544,9 +556,8 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                        // Either way, we just scan the rest and discard it
                        else {
                                Layout lay;
-                               // false positive from coverity
-                               // coverity[CHECKED_RETURN]
-                               readStyle(lexrc, lay);
+                               // signal to coverity that we do not care about the result
+                               (void)readStyle(lexrc, lay);
                        }
                        break;
                }
@@ -750,7 +761,11 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                        break;
 
                case TC_CITEENGINE:
-                       error = !readCiteEngine(lexrc);
+                       error = !readCiteEngine(lexrc, rt);
+                       break;
+
+               case TC_ADDTOCITEENGINE:
+                       error = !readCiteEngine(lexrc, rt, true);
                        break;
 
                case TC_CITEENGINETYPE:
@@ -759,7 +774,7 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                        break;
 
                case TC_CITEFORMAT:
-                       error = !readCiteFormat(lexrc);
+                       error = !readCiteFormat(lexrc, rt);
                        break;
 
                case TC_CITEFRAMEWORK:
@@ -849,11 +864,6 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
                        error = !readOutlinerName(lexrc);
                        break;
                } // end of switch
-
-               // Note that this is triggered the first time through the loop unless
-               // we hit a format tag.
-               if (format != LAYOUT_FORMAT)
-                       return FORMAT_MISMATCH;
        }
 
        // at present, we abort if we encounter an error,
@@ -1026,15 +1036,46 @@ void TextClass::readClassOptions(Lexer & lexrc)
 }
 
 
-bool TextClass::readCiteEngine(Lexer & lexrc)
+vector<CitationStyle> const & TextClass::getCiteStyles(
+       CiteEngineType const & type) const
+{
+       static vector<CitationStyle> empty;
+       map<CiteEngineType, vector<CitationStyle> >::const_iterator it = cite_styles_.find(type);
+       if (it == cite_styles_.end())
+               return empty;
+       return it->second;
+}
+
+
+bool TextClass::readCiteEngine(Lexer & lexrc, ReadType rt, bool const add)
 {
        int const type = readCiteEngineType(lexrc);
-       if (type & ENGINE_TYPE_AUTHORYEAR)
-               cite_styles_[ENGINE_TYPE_AUTHORYEAR].clear();
-       if (type & ENGINE_TYPE_NUMERICAL)
-               cite_styles_[ENGINE_TYPE_NUMERICAL].clear();
-       if (type & ENGINE_TYPE_DEFAULT)
-               cite_styles_[ENGINE_TYPE_DEFAULT].clear();
+       bool authoryear = (type & ENGINE_TYPE_AUTHORYEAR);
+       bool numerical = (type & ENGINE_TYPE_NUMERICAL);
+       bool defce = (type & ENGINE_TYPE_DEFAULT);
+
+       if (rt == CITE_ENGINE) {
+               // The cite engines are not supposed to overwrite
+               // CiteStyle defined by the class or a module.
+               if (authoryear)
+                       authoryear = getCiteStyles(ENGINE_TYPE_AUTHORYEAR).empty();
+               if (numerical)
+                       numerical = getCiteStyles(ENGINE_TYPE_NUMERICAL).empty();
+               if (defce)
+                       defce = getCiteStyles(ENGINE_TYPE_DEFAULT).empty();
+       }
+
+       if (rt != CITE_ENGINE && !add) {
+               // Reset if we defined CiteStyle
+               // from the class or a module
+               if (authoryear)
+                       cite_styles_[ENGINE_TYPE_AUTHORYEAR].clear();
+               if (numerical)
+                       cite_styles_[ENGINE_TYPE_NUMERICAL].clear();
+               if (defce)
+                       cite_styles_[ENGINE_TYPE_DEFAULT].clear();
+       }
+
        string def;
        bool getout = false;
        while (!getout && lexrc.isOK()) {
@@ -1097,6 +1138,8 @@ bool TextClass::readCiteEngine(Lexer & lexrc)
                                latex_cmd += ichar;
                        else if (mode == StarDesc)
                                stardesc += ichar;
+                       else if (ichar == '$')
+                               cs.hasQualifiedList = true;
                        else if (ichar == '*')
                                cs.hasStarredVersion = true;
                        else if (ichar == '[' && cs.textAfter)
@@ -1123,21 +1166,73 @@ bool TextClass::readCiteEngine(Lexer & lexrc)
                        cs.stardesc = stardescs[0];
                if (size > 1)
                        cs.startooltip = stardescs[1];
+               if (add) {
+                       if (authoryear)
+                               class_cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(cs);
+                       if (numerical)
+                               class_cite_styles_[ENGINE_TYPE_NUMERICAL].push_back(cs);
+                       if (defce)
+                               class_cite_styles_[ENGINE_TYPE_DEFAULT].push_back(cs);
+               } else {
+                       if (authoryear)
+                               cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(cs);
+                       if (numerical)
+                               cite_styles_[ENGINE_TYPE_NUMERICAL].push_back(cs);
+                       if (defce)
+                               cite_styles_[ENGINE_TYPE_DEFAULT].push_back(cs);
+               }
+       }
+       // If we do AddToCiteEngine, do not apply yet,
+       // except if we have already a style to add something to
+       bool apply_ay = !add;
+       bool apply_num = !add;
+       bool apply_def = !add;
+       if (add) {
                if (type & ENGINE_TYPE_AUTHORYEAR)
-                       cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(cs);
+                       apply_ay = !getCiteStyles(ENGINE_TYPE_AUTHORYEAR).empty();
                if (type & ENGINE_TYPE_NUMERICAL)
-                       cite_styles_[ENGINE_TYPE_NUMERICAL].push_back(cs);
+                       apply_num = !getCiteStyles(ENGINE_TYPE_NUMERICAL).empty();
                if (type & ENGINE_TYPE_DEFAULT)
-                       cite_styles_[ENGINE_TYPE_DEFAULT].push_back(cs);
+                       apply_def = !getCiteStyles(ENGINE_TYPE_DEFAULT).empty();
+       }
+
+       // Add the styles from AddToCiteEngine to the class' styles
+       // (but only if they are not yet defined)
+       for (auto const cis : class_cite_styles_) {
+               // Only consider the current CiteEngineType
+               if (!(type & cis.first))
+                       continue;
+               for (auto const ciss : cis.second) {
+                       bool defined = false;
+                       // Check if the style "name" is already def'ed
+                       for (auto const av : getCiteStyles(cis.first))
+                               if (av.name == ciss.name)
+                                       defined = true;
+                       if (!defined) {
+                               if (cis.first == ENGINE_TYPE_AUTHORYEAR && apply_ay)
+                                       cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(ciss);
+                               else if (cis.first == ENGINE_TYPE_NUMERICAL && apply_num)
+                                       cite_styles_[ENGINE_TYPE_NUMERICAL].push_back(ciss);
+                               else if (cis.first == ENGINE_TYPE_DEFAULT && apply_def)
+                                       cite_styles_[ENGINE_TYPE_DEFAULT].push_back(ciss);
+                       }
+               }
        }
+       if (type & ENGINE_TYPE_AUTHORYEAR && apply_ay)
+               class_cite_styles_[ENGINE_TYPE_AUTHORYEAR].clear();
+       if (type & ENGINE_TYPE_NUMERICAL && apply_num)
+               class_cite_styles_[ENGINE_TYPE_NUMERICAL].clear();
+       if (type & ENGINE_TYPE_DEFAULT && apply_def)
+               class_cite_styles_[ENGINE_TYPE_DEFAULT].clear();
        return getout;
 }
 
 
 int TextClass::readCiteEngineType(Lexer & lexrc) const
 {
-       LATTEST(ENGINE_TYPE_DEFAULT ==
-               (ENGINE_TYPE_AUTHORYEAR | ENGINE_TYPE_NUMERICAL));
+       static_assert(ENGINE_TYPE_DEFAULT ==
+                                 (ENGINE_TYPE_AUTHORYEAR | ENGINE_TYPE_NUMERICAL),
+                                 "Incorrect default engine type");
        if (!lexrc.next()) {
                lexrc.printError("No cite engine type given for token: `$$Token'.");
                return ENGINE_TYPE_DEFAULT;
@@ -1156,11 +1251,14 @@ int TextClass::readCiteEngineType(Lexer & lexrc) const
 }
 
 
-bool TextClass::readCiteFormat(Lexer & lexrc)
+bool TextClass::readCiteFormat(Lexer & lexrc, ReadType rt)
 {
        int const type = readCiteEngineType(lexrc);
        string etype;
        string definition;
+       // Cite engine definitions do not overwrite existing
+       // definitions from the class or a module
+       bool const overwrite = rt != CITE_ENGINE;
        while (lexrc.isOK()) {
                lexrc.next();
                etype = lexrc.getString();
@@ -1173,20 +1271,40 @@ bool TextClass::readCiteFormat(Lexer & lexrc)
                char initchar = etype[0];
                if (initchar == '#')
                        continue;
-               if (initchar == '!' || initchar == '_') {
-                       if (type & ENGINE_TYPE_AUTHORYEAR)
-                               cite_macros_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
-                       if (type & ENGINE_TYPE_NUMERICAL)
-                               cite_macros_[ENGINE_TYPE_NUMERICAL][etype] = definition;
-                       if (type & ENGINE_TYPE_DEFAULT)
-                               cite_macros_[ENGINE_TYPE_DEFAULT][etype] = definition;
+               if (initchar == '!' || initchar == '_' || prefixIs(etype, "B_")) {
+                       bool defined = false;
+                       // Check if the macro is already def'ed
+                       for (auto const cm : cite_macros_) {
+                               if (!(type & cm.first))
+                                       continue;
+                               if (cm.second.find(etype) != cm.second.end())
+                                       defined = true;
+                       }
+                       if (!defined || overwrite) {
+                               if (type & ENGINE_TYPE_AUTHORYEAR)
+                                       cite_macros_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
+                               if (type & ENGINE_TYPE_NUMERICAL)
+                                       cite_macros_[ENGINE_TYPE_NUMERICAL][etype] = definition;
+                               if (type & ENGINE_TYPE_DEFAULT)
+                                       cite_macros_[ENGINE_TYPE_DEFAULT][etype] = definition;
+                       }
                } else {
-                       if (type & ENGINE_TYPE_AUTHORYEAR)
-                               cite_formats_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
-                       if (type & ENGINE_TYPE_NUMERICAL)
-                               cite_formats_[ENGINE_TYPE_NUMERICAL][etype] = definition;
-                       if (type & ENGINE_TYPE_DEFAULT)
-                               cite_formats_[ENGINE_TYPE_DEFAULT][etype] = definition;
+                       bool defined = false;
+                       // Check if the format is already def'ed
+                       for (auto const cm : cite_formats_) {
+                               if (!(type & cm.first))
+                                       continue;
+                               if (cm.second.find(etype) != cm.second.end())
+                                       defined = true;
+                       }
+                       if (!defined || overwrite){
+                               if (type & ENGINE_TYPE_AUTHORYEAR)
+                                       cite_formats_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
+                               if (type & ENGINE_TYPE_NUMERICAL)
+                                       cite_formats_[ENGINE_TYPE_NUMERICAL][etype] = definition;
+                               if (type & ENGINE_TYPE_DEFAULT)
+                                       cite_formats_[ENGINE_TYPE_DEFAULT][etype] = definition;
+                       }
                }
        }
        return true;
@@ -1416,18 +1534,6 @@ bool TextClass::readOutlinerName(Lexer & lexrc)
 }
 
 
-docstring TextClass::outlinerName(std::string const & type) const
-{
-       std::map<std::string,docstring>::const_iterator const it
-               = outliner_names_.find(type);
-       if (it == outliner_names_.end()) {
-               LYXERR0("Missing OutlinerName for " << type << "!");
-               return translateIfPossible(from_utf8(type));
-       } else
-               return translateIfPossible(it->second);
-}
-
-
 string const & TextClass::prerequisites(string const & sep) const
 {
        if (contains(prerequisites_, ',')) {
@@ -1671,8 +1777,7 @@ Layout TextClass::createBasicLayout(docstring const & name, bool unknown) const
 
 DocumentClassPtr getDocumentClass(
                LayoutFile const & baseClass, LayoutModuleList const & modlist,
-               LayoutModuleList const & celist,
-               bool const clone)
+               string const & cengine, bool const clone)
 {
        DocumentClassPtr doc_class =
            DocumentClassPtr(new DocumentClass(baseClass));
@@ -1711,37 +1816,34 @@ DocumentClassPtr getDocumentClass(
                }
        }
 
-       LayoutModuleList::const_iterator cit = celist.begin();
-       LayoutModuleList::const_iterator cen = celist.end();
-       for (; cit != cen; ++cit) {
-               string const ceName = *cit;
-               LyXCiteEngine * ce = theCiteEnginesList[ceName];
-               if (!ce) {
-                       docstring const msg =
-                                               bformat(_("The cite engine %1$s has been requested by\n"
-                                               "this document but has not been found in the list of\n"
-                                               "available engines. If you recently installed it, you\n"
-                                               "probably need to reconfigure LyX.\n"), from_utf8(ceName));
-                       if (!clone)
-                               frontend::Alert::warning(_("Cite Engine not available"), msg);
-                       continue;
-               }
-               if (!ce->isAvailable() && !clone) {
-                       docstring const prereqs = from_utf8(getStringFromVector(ce->prerequisites(), "\n\t"));
-                       docstring const msg =
-                               bformat(_("The cite engine %1$s requires a package that is not\n"
-                                       "available in your LaTeX installation, or a converter that\n"
-                                       "you have not installed. LaTeX output may not be possible.\n"
-                                       "Missing prerequisites:\n"
-                                               "\t%2$s\n"
-                                       "See section 3.1.2.3 (Modules) of the User's Guide for more information."),
-                               from_utf8(ceName), prereqs);
-                       frontend::Alert::warning(_("Package not available"), msg, true);
-               }
+       if (cengine.empty())
+               return doc_class;
+
+       LyXCiteEngine * ce = theCiteEnginesList[cengine];
+       if (!ce) {
+               docstring const msg =
+                                       bformat(_("The cite engine %1$s has been requested by\n"
+                                       "this document but has not been found in the list of\n"
+                                       "available engines. If you recently installed it, you\n"
+                                       "probably need to reconfigure LyX.\n"), from_utf8(cengine));
+               if (!clone)
+                       frontend::Alert::warning(_("Cite Engine not available"), msg);
+       } else if (!ce->isAvailable() && !clone) {
+               docstring const prereqs = from_utf8(getStringFromVector(ce->prerequisites(), "\n\t"));
+               docstring const msg =
+                       bformat(_("The cite engine %1$s requires a package that is not\n"
+                               "available in your LaTeX installation, or a converter that\n"
+                               "you have not installed. LaTeX output may not be possible.\n"
+                               "Missing prerequisites:\n"
+                                       "\t%2$s\n"
+                               "See section 3.1.2.3 (Modules) of the User's Guide for more information."),
+                       from_utf8(cengine), prereqs);
+               frontend::Alert::warning(_("Package not available"), msg, true);
+       } else {
                FileName layout_file = libFileSearch("citeengines", ce->getFilename());
                if (!doc_class->read(layout_file, TextClass::CITE_ENGINE)) {
                        docstring const msg =
-                                               bformat(_("Error reading cite engine %1$s\n"), from_utf8(ceName));
+                                               bformat(_("Error reading cite engine %1$s\n"), from_utf8(cengine));
                        frontend::Alert::warning(_("Read Error"), msg);
                }
        }
@@ -1794,7 +1896,7 @@ Layout const & DocumentClass::getTOCLayout() const
        for (; lit != len; ++lit) {
                int const level = lit->toclevel;
                // we don't want Part or unnumbered sections
-               if (level == Layout::NOT_IN_TOC || level < 0 
+               if (level == Layout::NOT_IN_TOC || level < 0
                    || level >= minlevel || lit->counter.empty())
                        continue;
                lay = &*lit;