/// name of the file the buffer is associated with.
string filename;
- /// The path to the document file.
- string filepath;
-
boost::scoped_ptr<Messages> messages;
/** Set to true only when the file is fully loaded.
Buffer::Impl::Impl(Buffer & parent, string const & file, bool readonly_)
: lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_),
- filename(file), filepath(onlyPath(file)), file_fully_loaded(false),
+ filename(file), file_fully_loaded(false),
inset(params)
{
inset.setAutoBreakRows(true);
lyxvc.buffer(&parent);
temppath = createBufferTmpDir();
+ params.filepath = onlyPath(file);
// FIXME: And now do something if temppath == string(), because we
// assume from now on that temppath points to a valid temp dir.
// See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg67406.html
void Buffer::setFileName(string const & newfile)
{
pimpl_->filename = makeAbsPath(newfile);
- pimpl_->filepath = onlyPath(pimpl_->filename);
+ params().filepath = onlyPath(pimpl_->filename);
setReadonly(fs::is_readonly(pimpl_->filename));
updateTitles();
}
BOOST_ASSERT(paragraphs().empty());
readHeader(lex);
- if (!params().getLyXTextClass().load()) {
+ if (!params().getLyXTextClass().load(filePath())) {
string theclass = params().getLyXTextClass().name();
Alert::error(_("Can't load document class"), bformat(
"Using the default document class, because the "
string const & Buffer::filePath() const
{
- return pimpl_->filepath;
+ return params().filepath;
}
if (pp.first) {
textclass = pp.second;
} else {
- textclass = 0;
- return classname;
+ // if text class does not exist, try to load it from filepath
+ pp = textclasslist.addTextClass(classname, filepath);
+ if (pp.first) {
+ textclass = pp.second;
+ } else {
+ textclass = 0;
+ return classname;
+ }
}
+ // FIXME: isTeXClassAvailable will try to load the layout file, but will
+ // fail because of the lack of path info. Warnings will be given although
+ // the layout file will be correctly loaded later.
if (!getLyXTextClass().isTeXClassAvailable()) {
string const msg =
bformat(_("The document uses a missing "
std::string const paperSizeName() const;
///
std::string const babelCall(std::string const & lang_opts) const;
+ /// path of the current buffer
+ std::string filepath;
private:
/** Use the Pimpl idiom to hide those member variables that would otherwise
#include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/filetools.h"
+#include <boost/filesystem/operations.hpp>
+namespace fs = boost::filesystem;
#include <sstream>
// Load textclass info if not loaded yet
-bool LyXTextClass::load() const
+bool LyXTextClass::load(string const & path) const
{
if (loaded_)
return true;
- // Read style-file
- string const real_file = libFileSearch("layouts", name_, "layout");
+ // Read style-file, current directory is searched before system ones
+ string real_file = path + "/" + name_ + ".layout";
+ if (!fs::exists(real_file))
+ real_file = libFileSearch("layouts", name_, "layout");
loaded_ = const_cast<LyXTextClass*>(this)->read(real_file) == 0;
if (!loaded_) {
LyXLayout_ptr const & operator[](std::string const & vname) const;
/// Sees to that the textclass structure has been loaded
- bool load() const;
+ bool load(std::string const & path=".") const;
/// Has this layout file been loaded yet?
bool loaded() const { return loaded_; }
#include "support/filetools.h"
#include <boost/bind.hpp>
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <fstream>
+namespace fs = boost::filesystem;
using lyx::textclass_type;
using lyx::support::makeDisplayPath;
using boost::bind;
+using boost::regex;
+using boost::smatch;
#ifndef CXX_GLOBAL_CSTD
using std::exit;
using std::sort;
using std::string;
using std::pair;
+using std::ifstream;
// Gets textclass number from name
}
+std::pair<bool, lyx::textclass_type> const
+LyXTextClassList::addTextClass(std::string const & textclass, std::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
+ string layout_file = path + "/" + textclass + ".layout";
+ if (fs::exists(layout_file)) {
+ lyxerr[Debug::TCLASS] << "Adding class " << textclass << " from directory " << path << endl;
+ // Read .layout file and get description, real latex classname etc
+ //
+ // This is a C++ version of function processLayoutFile in configure.py,
+ // which uses the following regex
+ // \Declare(LaTeX|DocBook|LinuxDoc)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}
+ ifstream ifs(layout_file.c_str());
+ static regex const reg("^#\\s*\\\\Declare(LaTeX|DocBook|LinuxDoc)Class\\s*"
+ "(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*");
+ string line;
+ while (getline(ifs, line)) {
+ // look for the \DeclareXXXClass line
+ smatch sub;
+ 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.
+ LyXTextClass tmpl(textclass, sub.str(2)==""?textclass:sub.str(2),
+ sub.str(3) + " <" + path + ">", true);
+ if (lyxerr.debugging(Debug::TCLASS))
+ tmpl.load(path);
+ classlist_.push_back(tmpl);
+ 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));
+}
+
+
// Global variable: textclass table.
LyXTextClassList textclasslist;
/// Read textclass list. Returns false if this fails.
bool read();
+
+ /// add a textclass from user local directory.
+ /// Return ture/false, and textclass number
+ std::pair<bool, lyx::textclass_type> const
+ addTextClass(std::string const & textclass, std::string const & path);
+
private:
///
mutable ClassList classlist_;