]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/controllers/biblio.C
Add the missing template instatiations!
[lyx.git] / src / frontends / controllers / biblio.C
index c768434cf178e5683f6d1b4af650658a6806e75e..9a6a8fabb4c20f1e2ae74fd06a302518f6510f03 100644 (file)
@@ -1,4 +1,3 @@
-// -*- C++ -*-
 /* This file is part of
  * ====================================================== 
  *
@@ -23,6 +22,7 @@
 
 #include "LString.h"
 #include "biblio.h"
+#include "gettext.h" // for _()
 #include "helper_funcs.h"
 #include "support/lstrings.h"
 #include "support/LAssert.h"
@@ -36,102 +36,38 @@ using std::sort;
 namespace biblio 
 {
 
+namespace {
 
-// A functor for use with std::sort, leading to case insensitive sorting
-struct compareNoCase: public std::binary_function<string, string, bool> 
-{
-       bool operator()(string const & s1, string const & s2) const {
-               return compare_no_case(s1, s2) < 0;
-       }
-};
-
-vector<string> const getKeys(InfoMap const & map)
-{
-       vector<string> bibkeys;
-
-       for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
-               bibkeys.push_back(it->first);
-       }
+using namespace biblio;
+    
+char const * const citeCommands[] = {
+       "cite", "citet", "citep", "citealt", "citealp", "citeauthor", 
+       "citeyear", "citeyearpar" };
 
-       sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
-       return bibkeys;
-}
+unsigned int const nCiteCommands =
+       sizeof(citeCommands) / sizeof(char *);
 
+CiteStyle const citeStyles[] = {
+       CITE, CITET, CITEP, CITEALT, CITEALP,
+       CITEAUTHOR, CITEYEAR, CITEYEARPAR };
 
-string const getInfo(InfoMap const & map, string const & key)
-{
-       lyx::Assert(!map.empty());
+unsigned int const nCiteStyles =
+       sizeof(citeStyles) / sizeof(CiteStyle);
 
-       string result;
+CiteStyle const citeStylesFull[] = {
+       CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
 
-               InfoMap::const_iterator it = map.find(key);
-       if (it != map.end()) {
-               // Search for all possible "required" keys
-               string author = parseBibTeX(it->second, "author");
-               if (author.empty())
-                       author = parseBibTeX(it->second, "editor");
+unsigned int const nCiteStylesFull =
+       sizeof(citeStylesFull) / sizeof(CiteStyle);
 
-               string year       = parseBibTeX(it->second, "year");
-               string title      = parseBibTeX(it->second, "title");
-               string booktitle  = parseBibTeX(it->second, "booktitle");
-               string chapter    = parseBibTeX(it->second, "chapter");
-               string pages      = parseBibTeX(it->second, "pages");
-
-               string media      = parseBibTeX(it->second, "journal");
-               if (media.empty())
-                       media = parseBibTeX(it->second, "publisher");
-               if (media.empty())
-                       media = parseBibTeX(it->second, "school");
-               if (media.empty())
-                       media = parseBibTeX(it->second, "institution");
-
-               result = author;
-               if (!year.empty())
-                       result += ", " + year;
-               if (!title.empty())
-                       result += ", " + title;
-               if (!booktitle.empty())
-                       result += ", in " + booktitle;
-               if (!chapter.empty())
-                       result += ", Ch. " + chapter;
-               if (!media.empty())
-                       result += ", " + media;
-               if (!pages.empty())
-                       result += ", pp. " + pages;
-
-               if (result.empty()) // not a BibTeX record
-                       result = it->second;
-       }
+CiteStyle const citeStylesUCase[] = {
+       CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
 
-       return result;
-}
+unsigned int const nCiteStylesUCase =
+       sizeof(citeStylesUCase) / sizeof(CiteStyle);
  
 
-vector<string>::const_iterator
-searchKeys(InfoMap const & theMap,
-          vector<string> const & keys,
-          string const & expr,
-          vector<string>::const_iterator start,
-          Search type,
-          Direction dir,
-          bool caseSensitive)
-{
-       // Preliminary checks
-       if(start < keys.begin() || start >= keys.end())
-               return keys.end();
-       
-       string search_expr = frontStrip(strip(expr));
-       if (search_expr.empty())
-               return keys.end();
-
-       if (type == SIMPLE)
-               return simpleSearch(theMap, keys, search_expr, start, dir,
-                                   caseSensitive);
-
-       return regexSearch(theMap, keys, search_expr, start, dir);
-}
-
-
+// The functions doing the dirty work for the search.
 vector<string>::const_iterator
 simpleSearch(InfoMap const & theMap,
             vector<string> const & keys,
@@ -154,7 +90,7 @@ simpleSearch(InfoMap const & theMap,
             (dir == FORWARD) ? (++it) : (--it)) {
 
                string data = (*it);
-               biblio::InfoMap::const_iterator info = theMap.find(*it);
+               InfoMap::const_iterator info = theMap.find(*it);
                if (info != theMap.end())
                        data += " " + info->second;
                if (!caseSensitive)
@@ -177,7 +113,7 @@ simpleSearch(InfoMap const & theMap,
        return keys.end();
 }
 
-
 vector<string>::const_iterator
 regexSearch(InfoMap const & theMap,
            vector<string> const & keys,
@@ -194,7 +130,7 @@ regexSearch(InfoMap const & theMap,
             (dir == FORWARD) ? (++it) : (--it)) {
 
                string data = (*it);
-               biblio::InfoMap::const_iterator info = theMap.find(*it);
+               InfoMap::const_iterator info = theMap.find(*it);
                if (info != theMap.end())
                        data += " " + info->second;
 
@@ -205,6 +141,181 @@ regexSearch(InfoMap const & theMap,
        return keys.end();
 }
 
+string const familyName(string const & name)
+{
+       // Very simple parser
+       string fname = name;
+
+       string::size_type idx = fname.rfind(".");
+       if (idx != string::npos)
+               fname = frontStrip(fname.substr(idx+1));
+
+       return fname;
+}
+
+
+string const getAbbreviatedAuthor(InfoMap const & map, string const & key)
+{
+       lyx::Assert(!map.empty());
+
+               InfoMap::const_iterator it = map.find(key);
+
+       string author;
+       if (it != map.end()) {
+               author = parseBibTeX(it->second, "author");
+               if (author.empty())
+                       author = parseBibTeX(it->second, "editor");
+
+               vector<string> authors = getVectorFromString(author, "and");
+
+               if (!authors.empty()) {
+                       author.erase();
+
+                       for (vector<string>::iterator it = authors.begin();
+                            it != authors.end(); ++it) {
+                               *it = familyName(strip(*it));
+                       }
+
+                       author = authors[0];
+                       if (authors.size() == 2)
+                               author += _(" and ") + authors[1];
+                       else if (authors.size() > 2)
+                               author += _(" et al.");
+               }
+       }
+
+       if (author.empty())
+               author = _("Caesar et al.");
+
+       return author;
+}
+
+
+string const getYear(InfoMap const & map, string const & key)
+{
+       lyx::Assert(!map.empty());
+
+               InfoMap::const_iterator it = map.find(key);
+
+       string year;
+
+       if (it != map.end())
+               year = parseBibTeX(it->second, "year");
+
+       if (year.empty())
+               year = "50BC";
+
+       return year;
+}
+
+} // namespace anon 
+
+
+
+
+
+
+
+// A functor for use with std::sort, leading to case insensitive sorting
+struct compareNoCase: public std::binary_function<string, string, bool> 
+{
+       bool operator()(string const & s1, string const & s2) const {
+               return compare_no_case(s1, s2) < 0;
+       }
+};
+
+vector<string> const getKeys(InfoMap const & map)
+{
+       vector<string> bibkeys;
+
+       for (InfoMap::const_iterator it = map.begin(); it != map.end(); ++it) {
+               bibkeys.push_back(it->first);
+       }
+
+       sort(bibkeys.begin(), bibkeys.end(), compareNoCase());
+       return bibkeys;
+}
+
+
+string const getInfo(InfoMap const & map, string const & key)
+{
+       lyx::Assert(!map.empty());
+
+               InfoMap::const_iterator it = map.find(key);
+       if (it == map.end()) return string();
+
+       // Search for all possible "required" keys
+       string author = parseBibTeX(it->second, "author");
+       if (author.empty())
+               author = parseBibTeX(it->second, "editor");
+
+       string year       = parseBibTeX(it->second, "year");
+       string title      = parseBibTeX(it->second, "title");
+       string booktitle  = parseBibTeX(it->second, "booktitle");
+       string chapter    = parseBibTeX(it->second, "chapter");
+       string number     = parseBibTeX(it->second, "number");
+       string volume     = parseBibTeX(it->second, "volume");
+       string pages      = parseBibTeX(it->second, "pages");
+
+       string media      = parseBibTeX(it->second, "journal");
+       if (media.empty())
+               media = parseBibTeX(it->second, "publisher");
+       if (media.empty())
+               media = parseBibTeX(it->second, "school");
+       if (media.empty())
+               media = parseBibTeX(it->second, "institution");
+
+       ostringstream result;
+       result << author;
+       if (!title.empty())
+               result << ", " << title;
+       if (!booktitle.empty())
+               result << ", in " << booktitle;
+       if (!chapter.empty())
+               result << ", Ch. " << chapter;
+       if (!media.empty())
+               result << ", " << media;
+       if (!volume.empty())
+               result << ", vol. " << volume;
+       if (!number.empty())
+               result << ", no. " << number;
+       if (!pages.empty())
+               result << ", pp. " << pages;
+       if (!year.empty())
+               result << ", " << year;
+
+       if (result.str().empty()) // not a BibTeX record
+               result << it->second;
+
+       return result.str().c_str();
+}
+
+vector<string>::const_iterator
+searchKeys(InfoMap const & theMap,
+          vector<string> const & keys,
+          string const & expr,
+          vector<string>::const_iterator start,
+          Search type,
+          Direction dir,
+          bool caseSensitive)
+{
+       // Preliminary checks
+       if(start < keys.begin() || start >= keys.end())
+               return keys.end();
+       
+       string search_expr = frontStrip(strip(expr));
+       if (search_expr.empty())
+               return keys.end();
+
+       if (type == SIMPLE)
+               return simpleSearch(theMap, keys, search_expr, start, dir,
+                                   caseSensitive);
+
+       return regexSearch(theMap, keys, search_expr, start, dir);
+}
+
+
 string const parseBibTeX(string data, string const & findkey)
 {
        string keyvalue;
@@ -306,5 +417,185 @@ string const parseBibTeX(string data, string const & findkey)
 }
 
 
-} // namespace biblio 
+CitationStyle const getCitationStyle(string const & command)
+{
+       if (command.empty()) return CitationStyle();
+    
+       CitationStyle cs;
+       string cmd = command;
+
+       if (cmd[0] == 'C') {
+               cs.forceUCase = true;
+               cmd[0] = 'c';
+       }
+
+       size_t n = cmd.size()-1;
+       if (cmd[n] == '*') {
+               cs.full = true;
+               cmd = cmd.substr(0,n);
+       }
+
+       char const * const * const last = citeCommands + nCiteCommands;
+       char const * const * const ptr = std::find(citeCommands, last, cmd);
+
+       if (ptr != last) {
+               size_t idx = ptr - citeCommands;
+               cs.style = citeStyles[idx];
+       }
+
+       return cs;
+}
+
+
+string const getCiteCommand(CiteStyle command, bool full, bool forceUCase)
+{
+       string cite = citeCommands[command];
+       if (full) {
+               CiteStyle const * last = citeStylesFull + nCiteStylesFull;
+               if (std::find(citeStylesFull, last, command) != last)
+                       cite += "*";
+       }
+
+       if (forceUCase) {
+               CiteStyle const * last = citeStylesUCase + nCiteStylesUCase;
+               if (std::find(citeStylesUCase, last, command) != last)
+                       cite[0] = 'C';
+       }
+
+       return cite;
+}
+
+       
+vector<CiteStyle> const getCiteStyles(bool usingNatbib)
+{
+       unsigned int nStyles = 1;
+       unsigned int start = 0;
+       if (usingNatbib) {
+               nStyles = nCiteStyles - 1;
+               start = 1;
+       }
+
+       vector<CiteStyle> styles(nStyles);
+
+       vector<CiteStyle>::size_type i = 0;
+       int j = start;
+       for (; i != styles.size(); ++i, ++j) {
+               styles[i] = citeStyles[j];
+       }
+
+       return styles;
+}
 
+
+vector<string> const
+getNumericalStrings(string const & key,
+                   InfoMap const & map, vector<CiteStyle> const & styles)
+{
+       if (map.empty()) {
+               vector<string> vec(1);
+               vec[0] = _("No database");
+               return vec;
+       }
+       
+       vector<string> vec(styles.size());
+
+       string const author = getAbbreviatedAuthor(map, key);
+       string const year   = getYear(map, key);
+       
+       for (vector<string>::size_type i = 0; i != vec.size(); ++i) {
+               string str;
+
+               switch (styles[i]) {
+               case CITE:
+               case CITEP:
+                       str = "[#ID]";
+                       break;
+                       
+               case CITET:
+                       str = author + " [#ID]";
+                       break;
+                       
+               case CITEALT:
+                       str = author + " #ID";
+                       break;
+                       
+               case CITEALP:
+                       str = "#ID";
+                       break;
+                       
+               case CITEAUTHOR:
+                       str = author;
+                       break;
+                       
+               case CITEYEAR:
+                       str = year;
+                       break;
+                       
+               case CITEYEARPAR:
+                       str = "(" + year + ")";
+                       break;
+               }
+
+               vec[i] = str;
+       }
+       
+       return vec;
+}
+
+
+vector<string> const
+getAuthorYearStrings(string const & key,
+                   InfoMap const & map, vector<CiteStyle> const & styles)
+{
+       if (map.empty()) {
+               vector<string> vec(1);
+               vec[0] = _("No database");
+               return vec;
+       }
+       
+       vector<string> vec(styles.size());
+
+       string const author = getAbbreviatedAuthor(map, key);
+       string const year   = getYear(map, key);
+       
+       for (vector<string>::size_type i = 0; i != vec.size(); ++i) {
+               string str;
+
+               switch (styles[i]) {
+               case CITET:
+                       str = author + " (" + year + ")";
+                       break;
+                       
+               case CITE:
+               case CITEP:
+                       str = "(" + author + ", " + year + ")";
+                       break;
+                       
+               case CITEALT:
+                       str = author + " " + year ;
+                       break;
+                       
+               case CITEALP:
+                       str = author + ", " + year ;
+                       break;
+                       
+               case CITEAUTHOR:
+                       str = author;
+                       break;
+                       
+               case CITEYEAR:
+                       str = year;
+                       break;
+                       
+               case CITEYEARPAR:
+                       str = "(" + year + ")";
+                       break;
+               }
+
+               vec[i] = str;
+       }
+       
+       return vec;
+}
+
+} // namespace biblio