]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/controllers/biblio.C
fix crash due to invalidated iterator
[lyx.git] / src / frontends / controllers / biblio.C
index 2ba7e9c7bb84bed733e37765f14609a1d3910c54..32d4f8af3610f172bc9b250fe5d6afe14d716add 100644 (file)
 
 #include "biblio.h"
 
-#include "support/std_sstream.h"
-#include "gettext.h" // for _()
+#include "buffer.h"
+#include "bufferparams.h"
+#include "gettext.h"
 
 #include "support/lstrings.h"
 
 #include <boost/regex.hpp>
 
 #include <algorithm>
-
-using lyx::support::ascii_lowercase;
-using lyx::support::bformat;
-using lyx::support::compare_ascii_no_case;
-using lyx::support::contains;
-using lyx::support::getVectorFromString;
-using lyx::support::ltrim;
-using lyx::support::rtrim;
-using lyx::support::split;
-using lyx::support::subst;
-using lyx::support::token;
-using lyx::support::trim;
+#include <sstream>
 
 using std::string;
 using std::ostringstream;
 using std::vector;
 
 
+namespace lyx {
+
+using support::ascii_lowercase;
+using support::bformat;
+using support::compare_ascii_no_case;
+using support::contains;
+using support::getVectorFromString;
+using support::ltrim;
+using support::prefixIs;
+using support::rtrim;
+using support::split;
+using support::subst;
+using support::token;
+using support::trim;
+
 namespace biblio {
 
+namespace {
+
+vector<string> const init_possible_cite_commands()
+{
+       char const * const pos[] = {
+               "cite",
+               "citet", "citep", "citealt", "citealp",
+               "citeauthor", "citeyear", "citeyearpar",
+               "citet*", "citep*", "citealt*", "citealp*", "citeauthor*",
+               "Citet",  "Citep",  "Citealt",  "Citealp",  "Citeauthor",
+               "Citet*", "Citep*", "Citealt*", "Citealp*", "Citeauthor*",
+               "fullcite",
+               "footcite", "footcitet", "footcitep", "footcitealt",
+               "footcitealp", "footciteauthor", "footciteyear",
+               "footciteyearpar",
+               "citefield",
+               "citetitle",
+               "cite*"
+       };
+       size_t const size_pos = sizeof(pos) / sizeof(pos[0]);
+
+       return vector<string>(pos, pos + size_pos);
+}
+
+
+vector<string> const & possible_cite_commands()
+{
+       static vector<string> const pos = init_possible_cite_commands();
+       return pos;
+}
+
+
+bool is_possible_cite_command(string const & input)
+{
+       vector<string> const & possibles = possible_cite_commands();
+       vector<string>::const_iterator const end = possibles.end();
+       return std::find(possibles.begin(), end, input) != end;
+}
+
+
+string const default_cite_command(CiteEngine engine)
+{
+       string str;
+       switch (engine) {
+       case ENGINE_BASIC:
+               str = "cite";
+               break;
+       case ENGINE_NATBIB_AUTHORYEAR:
+               str = "citet";
+               break;
+       case ENGINE_NATBIB_NUMERICAL:
+               str = "citep";
+               break;
+       case ENGINE_JURABIB:
+               str = "cite";
+               break;
+       }
+       return str;
+}
+
+} // namespace anon
+
+
+string const asValidLatexCommand(string const & input,
+                                CiteEngine_enum const & engine)
+{
+       string const default_str = default_cite_command(engine);
+       if (!is_possible_cite_command(input))
+               return default_str;
+
+       string output;
+       switch (engine) {
+       case ENGINE_BASIC:
+               output = default_str;
+               break;
+
+       case ENGINE_NATBIB_AUTHORYEAR:
+       case ENGINE_NATBIB_NUMERICAL:
+               if (input == "cite" || input == "citefield" ||
+                   input == "citetitle" || input == "cite*")
+                       output = default_str;
+               else if (prefixIs(input, "foot"))
+                       output = input.substr(4);
+               else
+                       output = input;
+               break;
+
+       case ENGINE_JURABIB: {
+               // Jurabib does not support the 'uppercase' natbib style.
+               if (input[0] == 'C')
+                       output = string(1, 'c') + input.substr(1);
+               else
+                       output = input;
+
+               // Jurabib does not support the 'full' natbib style.
+               string::size_type const n = output.size() - 1;
+               if (output != "cite*" && output[n] == '*')
+                       output = output.substr(0, n);
+
+               break;
+       }
+       }
+
+       return output;
+}
+
+
 string const familyName(string const & name)
 {
        // Very simple parser
@@ -157,8 +269,9 @@ string const getYear(InfoMap const & map, string const & key)
 namespace {
 
 // A functor for use with std::sort, leading to case insensitive sorting
-struct compareNoCase: public std::binary_function<string, string, bool>
+class compareNoCase: public std::binary_function<string, string, bool>
 {
+public:
        bool operator()(string const & s1, string const & s2) const {
                return compare_ascii_no_case(s1, s2) < 0;
        }
@@ -211,6 +324,7 @@ string const getInfo(InfoMap const & map, string const & key)
        string number     = parseBibTeX(data, "number");
        string volume     = parseBibTeX(data, "volume");
        string pages      = parseBibTeX(data, "pages");
+       string annote     = parseBibTeX(data, "annote");
 
        string media      = parseBibTeX(data, "journal");
        if (media.empty())
@@ -239,6 +353,8 @@ string const getInfo(InfoMap const & map, string const & key)
                result << ", pp. " << pages;
        if (!year.empty())
                result << ", " << year;
+       if (!annote.empty())
+               result << "\n\n" << annote;
 
        string const result_str = rtrim(result.str());
        if (!result_str.empty())
@@ -272,8 +388,9 @@ string const escape_special_chars(string const & expr)
 
 // A functor for use with std::find_if, used to ascertain whether a
 // data entry matches the required regex_
-struct RegexMatch : public std::unary_function<string, bool>
+class RegexMatch : public std::unary_function<string, bool>
 {
+public:
        // re and icase are used to construct an instance of boost::RegEx.
        // if icase is true, then matching is insensitive to case
        RegexMatch(InfoMap const & m, string const & re, bool icase)
@@ -366,7 +483,11 @@ string const parseBibTeX(string data, string const & findkey)
                string::size_type const idx =
                        dummy.empty() ? string::npos : dummy.find('%');
                if (idx != string::npos)
-                       dummy.erase(idx, string::npos);
+                       // Check if this is really a comment or just "\%"
+                       if (idx == 0 || dummy[idx - 1] != '\\')
+                               dummy.erase(idx, string::npos);
+                       else  //  This is "\%", so just erase the '\'
+                               dummy.erase(idx - 1, 1);
                // do we have a new token or a new line of
                // the same one? In the first case we ignore
                // the \n and in the second we replace it
@@ -511,21 +632,21 @@ unsigned int const nCiteStylesUCase =
 } // namespace anon
 
 
-CitationStyle const getCitationStyle(string const & command)
+CitationStyle::CitationStyle(string const & command)
+       : style(CITE), full(false), forceUCase(false)
 {
-       if (command.empty()) return CitationStyle();
+       if (command.empty())
+               return;
 
-       CitationStyle cs;
        string cmd = command;
-
        if (cmd[0] == 'C') {
-               cs.forceUCase = true;
+               forceUCase = true;
                cmd[0] = 'c';
        }
 
-       size_t n = cmd.size() - 1;
-       if (cmd[n] == '*') {
-               cs.full = true;
+       string::size_type const n = cmd.size() - 1;
+       if (cmd != "cite" && cmd[n] == '*') {
+               full = true;
                cmd = cmd.substr(0,n);
        }
 
@@ -534,25 +655,23 @@ CitationStyle const getCitationStyle(string const & command)
 
        if (ptr != last) {
                size_t idx = ptr - citeCommands;
-               cs.style = citeStyles[idx];
+               style = citeStyles[idx];
        }
-
-       return cs;
 }
 
 
-string const getCiteCommand(CiteStyle command, bool full, bool forceUCase)
+string const CitationStyle::asLatexStr() const
 {
-       string cite = citeCommands[command];
+       string cite = citeCommands[style];
        if (full) {
                CiteStyle const * last = citeStylesFull + nCiteStylesFull;
-               if (std::find(citeStylesFull, last, command) != last)
+               if (std::find(citeStylesFull, last, style) != last)
                        cite += '*';
        }
 
        if (forceUCase) {
                CiteStyle const * last = citeStylesUCase + nCiteStylesUCase;
-               if (std::find(citeStylesUCase, last, command) != last)
+               if (std::find(citeStylesUCase, last, style) != last)
                        cite[0] = 'C';
        }
 
@@ -560,24 +679,40 @@ string const getCiteCommand(CiteStyle command, bool full, bool forceUCase)
 }
 
 
-vector<CiteStyle> const getCiteStyles(bool usingNatbib, bool usingJurabib)
+CiteEngine_enum getEngine(Buffer const & buffer)
+{
+       return buffer.params().cite_engine;
+}
+
+
+vector<CiteStyle> const getCiteStyles(CiteEngine_enum const & engine)
 {
-       unsigned int nStyles = 1;
+       unsigned int nStyles = 0;
        unsigned int start = 0;
-       if (usingNatbib) {
+
+       switch (engine) {
+       case ENGINE_BASIC:
+               nStyles = 1;
+               start = 0;
+               break;
+       case ENGINE_NATBIB_AUTHORYEAR:
+       case ENGINE_NATBIB_NUMERICAL:
                nStyles = nCiteStyles - 1;
                start = 1;
-       }
-       if (usingJurabib)
+               break;
+       case ENGINE_JURABIB:
                nStyles = nCiteStyles;
+               start = 0;
+               break;
+       }
 
-       vector<CiteStyle> styles(nStyles);
+       typedef vector<CiteStyle> cite_vec;
 
-       vector<CiteStyle>::size_type i = 0;
+       cite_vec styles(nStyles);
+       cite_vec::size_type i = 0;
        int j = start;
-       for (; i != styles.size(); ++i, ++j) {
+       for (; i != styles.size(); ++i, ++j)
                styles[i] = citeStyles[j];
-       }
 
        return styles;
 }
@@ -698,3 +833,4 @@ getAuthorYearStrings(string const & key,
 }
 
 } // namespace biblio
+} // namespace lyx