]> git.lyx.org Git - lyx.git/blobdiff - src/Author.cpp
Account for old versions of Pygments
[lyx.git] / src / Author.cpp
index 0ad9b898ead7c64fe6112bebd2048a0612bf37f5..03025a38aa9910f8695039fa6b3d56a497f31c4f 100644 (file)
 
 #include "Author.h"
 
-#include "support/lstrings.h"
-
+#include "support/convert.h"
+#include "support/gettext.h"
 #include "support/lassert.h"
+#include "support/lstrings.h"
 
 #include <algorithm>
 #include <istream>
@@ -24,6 +25,45 @@ using namespace lyx::support;
 
 namespace lyx {
 
+static int computeHash(docstring const & name,
+       docstring const & email)
+{
+       string const full_author_string = to_utf8(name + email);
+       // Bernstein's hash function
+       unsigned int hash = 5381;
+       for (unsigned int i = 0; i < full_author_string.length(); ++i)
+               hash = ((hash << 5) + hash) + (unsigned int)(full_author_string[i]);
+       return int(hash);
+}
+
+
+Author::Author(docstring const & name, docstring const & email)
+       : name_(name), email_(email), used_(true),
+         buffer_id_(computeHash(name, email))
+{}
+
+
+Author::Author(int buffer_id)
+       : name_(convert<docstring>(buffer_id)), email_(docstring()), used_(false),
+         buffer_id_(buffer_id)
+{}
+
+
+docstring Author::nameAndEmail() const
+{
+       if (email().empty())
+               return name();
+       else
+               return bformat(_("%1$s[[name]] (%2$s[[email]])"), name(), email());
+}
+
+
+bool Author::valid() const
+{
+       //this cannot be equal if the buffer_id was produced by the hash function.
+       return name_ != convert<docstring>(buffer_id_);
+}
+
 
 bool operator==(Author const & l, Author const & r)
 {
@@ -34,12 +74,14 @@ bool operator==(Author const & l, Author const & r)
 ostream & operator<<(ostream & os, Author const & a)
 {
        // FIXME UNICODE
-       os << a.buffer_id() << " \"" << to_utf8(a.name())
-                       << "\" " << to_utf8(a.email());
-               
+       os << a.buffer_id_ << " \"" << to_utf8(a.name_) << "\"";
+       if (!a.email_.empty())
+               os << " " << to_utf8(a.email_);
+
        return os;
 }
 
+
 istream & operator>>(istream & is, Author & a)
 {
        string s;
@@ -52,47 +94,63 @@ istream & operator>>(istream & is, Author & a)
 }
 
 
-bool author_smaller(Author const & lhs, Author const & rhs) {
-       return lhs.buffer_id() < rhs.buffer_id();
+bool author_smaller(Author const & lhs, Author const & rhs)
+{
+       return lhs.bufferId() < rhs.bufferId();
 }
 
 
 AuthorList::AuthorList()
-       : last_id_(0)
-{
-}
+{}
 
 
 int AuthorList::record(Author const & a)
 {
-       Authors::const_iterator it(authors_.begin());
-       Authors::const_iterator itend(authors_.end());
-
-       for (int i = 0;  it != itend; ++it, ++i) {
-               if (*it == a) {
-                       if (it->buffer_id() == 0)
-                               // The current author is internally represented as 
-                               // author 0, but it appears he has already an id.
-                               it->setBufferId(a.buffer_id());
-                       return i;
+       bool const valid = a.valid();
+       // If we record an author which equals the current
+       // author, we copy the buffer_id, so that it will
+       // keep the same id in the file.
+       if (valid && !authors_.empty() && a == authors_[0])
+               authors_[0].setBufferId(a.bufferId());
+
+       Authors::const_iterator it = authors_.begin();
+       Authors::const_iterator const beg = it;
+       Authors::const_iterator const end = authors_.end();
+       for (; it != end; ++it) {
+               if (valid && *it == a)
+                       return it - beg;
+               if (it->bufferId() == a.bufferId()) {
+                       int id = it - beg;
+                       if (!it->valid())
+                               // we need to handle the case of a valid author being registred
+                               // after an invalid one. For instance, because "buffer-reload"
+                               // does not clear the buffer's author list.
+                               record(id, a);
+                       return id;
                }
        }
        authors_.push_back(a);
-       return last_id_++;
+       return authors_.size() - 1;
 }
 
 
 void AuthorList::record(int id, Author const & a)
 {
-       LASSERT(unsigned(id) < authors_.size(), /**/);
-
+       LBUFERR(unsigned(id) < authors_.size());
        authors_[id] = a;
 }
 
 
+void AuthorList::recordCurrentAuthor(Author const & a)
+{
+       // current author has id 0
+       record(0, a);
+}
+
+
 Author const & AuthorList::get(int id) const
 {
-       LASSERT(id < (int)authors_.size() , /**/);
+       LASSERT(id < (int)authors_.size() , return authors_[0]);
        return authors_[id];
 }
 
@@ -109,39 +167,23 @@ AuthorList::Authors::const_iterator AuthorList::end() const
 }
 
 
-void AuthorList::sort() {
+void AuthorList::sort()
+{
        std::sort(authors_.begin(), authors_.end(), author_smaller);
 }
 
 
-ostream & operator<<(ostream & os, AuthorList const & a) {
+ostream & operator<<(ostream & os, AuthorList const & a)
+{
        // Copy the authorlist, because we don't want to sort the original
        AuthorList sorted = a;
        sorted.sort();
 
        AuthorList::Authors::const_iterator a_it = sorted.begin();
-       AuthorList::Authors::const_iterator a_end = sorted.end();
-
-       // Find the buffer id for the current author (internal id 0),
-       // if he doesn't have a buffer_id yet.
-       if (sorted.get(0).buffer_id() == 0) {
-               unsigned int cur_id = 1;
-               for (; a_it != a_end; ++a_it) {
-                       if (a_it->buffer_id() == cur_id)
-                               ++cur_id;
-                       else if (a_it->buffer_id() > cur_id) {
-                               break;
-                       }
-               }
-               // Set the id in both the original authorlist, 
-               // as in the copy.
-               a.get(0).setBufferId(cur_id);
-               sorted.get(0).setBufferId(cur_id);
-               sorted.sort();
-       }
-       
-       for (a_it = sorted.begin(); a_it != a_end; ++a_it) {
-               if (a_it->used())
+       AuthorList::Authors::const_iterator const a_end = sorted.end();
+
+       for (; a_it != a_end; ++a_it) {
+               if (a_it->used() && a_it->valid())
                        os << "\\author " << *a_it << "\n";     
        }
        return os;