]> git.lyx.org Git - lyx.git/blobdiff - src/TextClassList.cpp
Load local textclass in addTextClass(), reload local layout correctly in LFUN_TEXTCLA...
[lyx.git] / src / TextClassList.cpp
index aee1144668182f85c9e28504738a433817de6bae..8a2f86923917a652dc0a9bf2e5f6c55ace7f2f4a 100644 (file)
 
 #include "TextClassList.h"
 #include "TextClass.h"
-#include "debug.h"
 #include "Lexer.h"
 
+#include "support/debug.h"
+#include "support/FileName.h"
 #include "support/filetools.h"
 
 #include <boost/bind.hpp>
 #include <boost/regex.hpp>
-#include <boost/filesystem/operations.hpp>
+
 #include <fstream>
 
+using namespace std;
+using namespace lyx::support;
 
 namespace lyx {
-namespace fs = boost::filesystem;
-
-using support::FileName;
-using support::addName;
-using support::libFileSearch;
-using support::makeDisplayPath;
 
 using boost::bind;
 using boost::regex;
 using boost::smatch;
 
-using std::endl;
-using std::equal_to;
-using std::find_if;
-using std::make_pair;
-using std::sort;
-using std::string;
-using std::pair;
-using std::ifstream;
-
-
 // Gets textclass number from name
-pair<bool, textclass_type> const
+pair<bool, TextClassIndex> const
 TextClassList::numberOfClass(string const & textclass) const
 {
        ClassList::const_iterator cit =
@@ -57,26 +44,37 @@ TextClassList::numberOfClass(string const & textclass) const
                             textclass));
 
        return cit != classlist_.end() ?
-               make_pair(true, textclass_type(cit - classlist_.begin())) :
-               make_pair(false, textclass_type(0));
+               make_pair(true, TextClassIndex(cit - classlist_.begin())) :
+               make_pair(false, TextClassIndex(0));
 }
 
 
 // Gets a textclass structure from number
 TextClass const &
-TextClassList::operator[](textclass_type textclass) const
+TextClassList::operator[](TextClassIndex textclass) const
 {
+       if (textclass >= classlist_.size())
+               return classlist_[0];
+       
+       //FIXME I don't believe the following line is actually necessary (rgh)
        classlist_[textclass].load();
-       if (textclass < classlist_.size())
-               return classlist_[textclass];
-       else
+       return classlist_[textclass];
+}
+
+TextClass & TextClassList::at(TextClassIndex textclass)
+{
+       if (textclass >= classlist_.size())
                return classlist_[0];
+       
+       //FIXME I don't believe the following line is actually necessary (rgh)
+       classlist_[textclass].load();
+       return classlist_[textclass];
 }
 
 
 // used when sorting the textclass list.
 class less_textclass_avail_desc
-       : public std::binary_function<TextClass, TextClass, int>
+       : public binary_function<TextClass, TextClass, int>
 {
 public:
        int operator()(TextClass const & tc1,
@@ -97,9 +95,8 @@ public:
 bool TextClassList::read()
 {
        Lexer lex(0, 0);
-       support::FileName const real_file = libFileSearch("", "textclass.lst");
-       LYXERR(Debug::TCLASS) << "Reading textclasses from `"
-                             << real_file << '\'' << endl;
+       FileName const real_file = libFileSearch("", "textclass.lst");
+       LYXERR(Debug::TCLASS, "Reading textclasses from `" << real_file << '\'');
 
        if (real_file.empty()) {
                lyxerr << "TextClassList::Read: unable to find "
@@ -131,29 +128,31 @@ bool TextClassList::read()
 
        bool finished = false;
        // Parse config-file
-       LYXERR(Debug::TCLASS) << "Starting parsing of textclass.lst" << endl;
+       LYXERR(Debug::TCLASS, "Starting parsing of textclass.lst");
        while (lex.isOK() && !finished) {
-               LYXERR(Debug::TCLASS) << "\tline by line" << endl;
+               LYXERR(Debug::TCLASS, "\tline by line");
                switch (lex.lex()) {
                case Lexer::LEX_FEOF:
                        finished = true;
                        break;
                default:
                        string const fname = lex.getString();
-                       LYXERR(Debug::TCLASS) << "Fname: " << fname << endl;
+                       LYXERR(Debug::TCLASS, "Fname: " << fname);
                        if (lex.next()) {
                                string const clname = lex.getString();
-                               LYXERR(Debug::TCLASS) << "Clname: " << clname << endl;
+                               LYXERR(Debug::TCLASS, "Clname: " << clname);
                                if (lex.next()) {
                                        string const desc = lex.getString();
-                                       LYXERR(Debug::TCLASS) << "Desc: " << desc << endl;
+                                       LYXERR(Debug::TCLASS, "Desc: " << desc);
                                        if (lex.next()) {
                                                bool avail = lex.getBool();
-                                               LYXERR(Debug::TCLASS) << "Avail: " << avail << endl;
+                                               LYXERR(Debug::TCLASS, "Avail: " << avail);
                                                // This code is run when we have
                                                // fname, clname, desc, and avail
                                                TextClass tmpl(fname, clname, desc, avail);
                                                if (lyxerr.debugging(Debug::TCLASS)) {
+                                                       // only system layout files are loaded here so no
+                                                       // buffer path is needed.
                                                        tmpl.load();
                                                }
                                                classlist_.push_back(tmpl);
@@ -162,27 +161,40 @@ bool TextClassList::read()
                        }
                }
        }
-       LYXERR(Debug::TCLASS) << "End of parsing of textclass.lst" << endl;
+       LYXERR(Debug::TCLASS, "End of parsing of textclass.lst");
 
-       if (classlist_.empty()) {
+       // lyx will start with an empty classlist_, but only reconfigure is allowed
+       // in this case. This gives users a second chance to configure lyx if
+       // initial configuration fails. (c.f. bug 2829)
+       if (classlist_.empty())
                lyxerr << "TextClassList::Read: no textclasses found!"
                       << endl;
-               return false;
-       }
-       // Ok everything loaded ok, now sort the list.
-       sort(classlist_.begin(), classlist_.end(), less_textclass_avail_desc());
+       else 
+               // Ok everything loaded ok, now sort the list.
+               sort(classlist_.begin(), classlist_.end(), less_textclass_avail_desc());
        return true;
 }
 
 
-std::pair<bool, textclass_type> const
-TextClassList::addTextClass(std::string const & textclass, std::string const & path)
+void TextClassList::reset(TextClassIndex const & textclass)
+{
+       if (textclass >= classlist_.size())
+               return;
+       TextClass const & tc = classlist_[textclass];
+       TextClass tmpl(tc.name(), tc.latexname(), tc.description(), 
+                      tc.isTeXClassAvailable());
+       classlist_[textclass] = tmpl;
+}
+
+
+pair<bool, TextClassIndex> const
+TextClassList::addTextClass(string const & textclass, string const & path)
 {
        // only check for textclass.layout file, .cls can be anywhere in $TEXINPUTS
        // NOTE: latex class name is defined in textclass.layout, which can be different from textclass
        FileName const layout_file(addName(path, textclass + ".layout"));
-       if (fs::exists(layout_file.toFilesystemEncoding())) {
-               LYXERR(Debug::TCLASS) << "Adding class " << textclass << " from directory " << path << endl;
+       if (layout_file.exists()) {
+               LYXERR(Debug::TCLASS, "Adding class " << textclass << " from directory " << path);
                // Read .layout file and get description, real latex classname etc
                //
                // This is a C++ version of function processLayoutFile in configure.py,
@@ -198,18 +210,29 @@ TextClassList::addTextClass(std::string const & textclass, std::string const & p
                        if (regex_match(line, sub, reg)) {
                                // returns: whole string, classtype (not used here), first option, description
                                BOOST_ASSERT(sub.size()==4);
-                               // now, add the layout to textclass.
+                               // now, create a TextClass with description containing path information
                                TextClass tmpl(textclass, sub.str(2)==""?textclass:sub.str(2),
                                        sub.str(3) + " <" + path + ">", true);
                                if (lyxerr.debugging(Debug::TCLASS))
                                        tmpl.load(path);
+                               // Do not add this local TextClass to classlist_ if it has
+                               // already been loaded by, for example, a master buffer.
+                               pair<bool, lyx::TextClassIndex> pp =
+                                       textclasslist.numberOfClass(textclass);
+                               // only layouts from the same directory are considered to be identical.
+                               if (pp.first && classlist_[pp.second].description() == tmpl.description())
+                                       return pp;
                                classlist_.push_back(tmpl);
+                               // This textclass is added on request so it will definitely be
+                               // used. Load it now because other load() calls may fail if they
+                               // are called in a context without buffer path information.
+                               classlist_.back().load(path);
                                return make_pair(true, classlist_.size() - 1);
                        }
                }
        }
        // If .layout is not in local directory, or an invalid layout is found, return false
-       return make_pair(false, textclass_type(0));
+       return make_pair(false, TextClassIndex(0));
 }
 
 
@@ -217,18 +240,29 @@ TextClassList::addTextClass(std::string const & textclass, std::string const & p
 TextClassList textclasslist;
 
 
+TextClassIndex defaultTextclass()
+{
+       // We want to return the article class. if `first' is
+       // true in the returned pair, then `second' is the textclass
+       // number; if it is false, second is 0. In both cases, second
+       // is what we want.
+       return textclasslist.numberOfClass("article").second;
+}
+
+
+
 // Reads the style files
 bool LyXSetStyle()
 {
-       LYXERR(Debug::TCLASS) << "LyXSetStyle: parsing configuration..." << endl;
+       LYXERR(Debug::TCLASS, "LyXSetStyle: parsing configuration...");
 
        if (!textclasslist.read()) {
-               LYXERR(Debug::TCLASS) << "LyXSetStyle: an error occured "
-                       "during parsing.\n             Exiting." << endl;
+               LYXERR(Debug::TCLASS, "LyXSetStyle: an error occured "
+                       "during parsing.\n             Exiting.");
                return false;
        }
 
-       LYXERR(Debug::TCLASS) << "LyXSetStyle: configuration parsed." << endl;
+       LYXERR(Debug::TCLASS, "LyXSetStyle: configuration parsed.");
        return true;
 }