X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLayoutFile.cpp;h=ccf2838d119ba2bbbcba9061ebf7a562639ae2cf;hb=b4fad55fd732c097ac44cf7a3428281376cc5dcc;hp=4337956170496b3c3715f58945377657b4d96fe7;hpb=f18af303fe2f9dca05beae7852f3904ac4bfddba;p=lyx.git diff --git a/src/LayoutFile.cpp b/src/LayoutFile.cpp index 4337956170..ccf2838d11 100644 --- a/src/LayoutFile.cpp +++ b/src/LayoutFile.cpp @@ -27,8 +27,8 @@ #include "support/lassert.h" #include "support/lstrings.h" -#include "support/bind.h" #include "support/regex.h" +#include "support/TempFile.h" #include @@ -43,7 +43,8 @@ LayoutFile::LayoutFile(string const & fn, string const & cln, string const & desc, string const & prereq, string const & category, bool texclassavail) { - name_ = fn; + name_ = onlyFileName(fn); + path_ = fn.rfind('/') == string::npos ? string() : onlyPath(fn); latexname_ = cln; description_ = desc; prerequisites_ = prereq; @@ -83,14 +84,16 @@ bool LayoutFileList::haveClass(string const & classname) const LayoutFile const & LayoutFileList::operator[](string const & classname) const { - LASSERT(haveClass(classname), /**/); + LATTEST(haveClass(classname)); + // safe to continue, since we will make an empty LayoutFile return *classmap_[classname]; } LayoutFile & LayoutFileList::operator[](string const & classname) { - LASSERT(haveClass(classname), /**/); + LATTEST(haveClass(classname)); + // safe to continue, since we will make an empty LayoutFile return *classmap_[classname]; } @@ -182,8 +185,10 @@ std::vector LayoutFileList::classList() const } -void LayoutFileList::reset(LayoutFileIndex const & classname) { - LASSERT(haveClass(classname), /**/); +void LayoutFileList::reset(LayoutFileIndex const & classname) +{ + LATTEST(haveClass(classname)); + // safe to continue, since we will make an empty LayoutFile LayoutFile * tc = classmap_[classname]; LayoutFile * tmpl = new LayoutFile(tc->name(), tc->latexname(), tc->description(), @@ -216,9 +221,13 @@ string layoutpost = } + LayoutFileIndex LayoutFileList::addEmptyClass(string const & textclass) { - FileName const tempLayout = FileName::tempName("basic_layout"); + // FIXME This could be simplified a bit to call TextClass::read(string, ReadType). + + TempFile tempfile("basicXXXXXX.layout"); + FileName const tempLayout = tempfile.name(); ofstream ofs(tempLayout.toFilesystemEncoding().c_str()); // This writes a very basic class, but it also attempts to include // stdclass.inc. That would give us something moderately usable. @@ -247,8 +256,9 @@ LayoutFileIndex LayoutFileList::addEmptyClass(string const & textclass) << layoutpost; ofs2.close(); if (!tc->load(tempLayout.absFileName())) { - // This can only happen if the hardcoded file above is wrong. - LASSERT(false, /* */); + // This can only happen if the hardcoded file above is wrong + // or there is some weird filesystem error. + LATTEST(false); // We will get an empty layout or something. } } @@ -257,8 +267,8 @@ LayoutFileIndex LayoutFileList::addEmptyClass(string const & textclass) } -LayoutFileIndex - LayoutFileList::addLocalLayout(string const & textclass, string const & path) +LayoutFileIndex LayoutFileList::addLocalLayout( + string const & textclass, string const & path, string const & oldpath) { // FIXME There is a bug here: 4593 // @@ -267,62 +277,81 @@ LayoutFileIndex // different from textclass string fullName = addName(path, textclass + ".layout"); - FileName const layout_file(fullName); - 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, - // which uses the following regex - // \Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)} - ifstream ifs(layout_file.toFilesystemEncoding().c_str()); - static regex const reg("^#\\s*\\\\Declare(LaTeX|DocBook)Class\\s*" - "(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*"); - static regex const catreg("^#\\s*\\\\DeclareCategory\\{(.*)\\}"); - string line; - string class_name; - string class_prereq; - string category; - bool have_declaration = false; - while (getline(ifs, line)) { - // look for the \DeclareXXXClass line - smatch sub; - if (regex_match(line, sub, reg)) { - // returns: whole string, classtype (not used here), class name, description - LASSERT(sub.size() == 4, /**/); - // now, create a TextClass with description containing path information - class_name = (sub.str(2) == "" ? textclass : sub.str(2)); - class_prereq = class_name + ".cls"; - have_declaration = true; - } - else if (regex_match(line, sub, catreg)) { - category = sub.str(1); - } - if (have_declaration && !category.empty()) - break; + FileName layout_file(fullName); + bool moved = false; + + if (!layout_file.exists()) { + if (oldpath.empty()) + return string(); + // The document has been moved to a different directory. + // However, oldpath always points to the right spot, unless + // the user also moved the layout file. + fullName = addName(oldpath, textclass + ".layout"); + layout_file.set(fullName); + layout_file.refresh(); + if (!layout_file.exists()) + return string(); + moved = true; + } + + 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, + // which uses the following regex + // \Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)} + ifstream ifs(layout_file.toFilesystemEncoding().c_str()); + static regex const reg("^\\s*#\\s*\\\\Declare(LaTeX|DocBook)Class\\s*" + "(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*"); + static regex const catreg("^\\s*#\\s*\\\\DeclareCategory\\{(.*)\\}\\s*"); + string line; + string class_name; + string class_prereq; + string category; + bool have_declaration = false; + while (getline(ifs, line)) { + // look for the \DeclareXXXClass line + smatch sub; + if (regex_match(line, sub, reg)) { + // returns: whole string, classtype (not used here), class name, description + // LASSERT: Why would this fail? + LASSERT(sub.size() == 4, /**/); + // now, create a TextClass with description containing path information + class_name = (sub.str(2) == "" ? textclass : sub.str(2)); + class_prereq = class_name + ".cls"; + have_declaration = true; } - if (have_declaration) { - LayoutFile * tmpl = - new LayoutFile(textclass, class_name, textclass, class_prereq, category, true); - //FIXME: The prerequisites are available from the layout file and - // can be extracted from the above regex, but for now this - // field is simply set to class_name + ".cls" - // 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. - tmpl->load(path); - // There will be only one textclass with this name, even if different - // layout files are loaded from different directories. - if (haveClass(textclass)) { - LYXERR0("Existing textclass " << textclass << " is redefined by " << fullName); - delete classmap_[textclass]; - } - classmap_[textclass] = tmpl; - return textclass; + else if (regex_match(line, sub, catreg)) { + category = sub.str(1); } + if (have_declaration && !category.empty()) + break; + } + + if (!have_declaration) + return string(); + + LayoutFile * tmpl = + new LayoutFile(addName(moved ? oldpath : path, textclass), + class_name, textclass, class_prereq, category, true); + //FIXME: The prerequisites are available from the layout file and + // can be extracted from the above regex, but for now this + // field is simply set to class_name + ".cls" + // 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. + tmpl->load(moved ? oldpath : path); + // There will be only one textclass with this name, even if different + // layout files are loaded from different directories. + if (haveClass(textclass)) { + // Unconditionally issuing the warning may be confusing when + // saving the document with a different name, as it is exactly + // the same textclass that is being re-established. + LYXERR(Debug::TCLASS, "Existing textclass " << textclass << " is redefined by " << fullName); + delete classmap_[textclass]; } - // If .layout is not in local directory, or an invalid layout is found, return null - return string(); + classmap_[textclass] = tmpl; + return removeExtension(fullName); }