X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxtextclass.C;h=cdda271a71d942a40660e246fcc891867197cc9d;hb=b01a9dc187d9cd396a57463ad27511379dcdc9cd;hp=6a5d6fc688905b737601c43169ccc504d8e5cae5;hpb=a9cd48f40e48a0e7c00f2bf9d33f01f19a0d83db;p=lyx.git diff --git a/src/lyxtextclass.C b/src/lyxtextclass.C index 6a5d6fc688..cdda271a71 100644 --- a/src/lyxtextclass.C +++ b/src/lyxtextclass.C @@ -22,12 +22,25 @@ #include "FloatList.h" #include "support/lstrings.h" +#include "support/lyxlib.h" #include "support/filetools.h" +#include "support/os.h" -using lyx::support::LibFileSearch; -using lyx::support::MakeDisplayPath; -using lyx::support::rtrim; -using lyx::support::subst; +#include +namespace fs = boost::filesystem; + +#include + + +namespace lyx { + +using support::FileName; +using support::libFileSearch; +using support::makeDisplayPath; +using support::quoteName; +using support::rtrim; +using support::subst; +using support::addName; using std::endl; using std::find_if; @@ -36,30 +49,60 @@ using std::string; using std::ostream; -namespace { // anon - -struct compare_name { +namespace { - compare_name(string const & name) +class LayoutNamesEqual : public std::unary_function { +public: + LayoutNamesEqual(string const & name) : name_(name) {} - - bool operator()(boost::shared_ptr const & c) + bool operator()(LyXLayout_ptr const & c) const { return c->name() == name_; } - +private: string name_; - }; -} // anon + +int const FORMAT = 3; + + +bool layout2layout(FileName const & filename, FileName const & tempfile) +{ + FileName const script = libFileSearch("scripts", "layout2layout.py"); + if (script.empty()) { + lyxerr << "Could not find layout conversion " + "script layout2layout.py." << endl; + return false; + } + + std::ostringstream command; + command << support::os::python() << ' ' << quoteName(script.toFilesystemEncoding()) + << ' ' << quoteName(filename.toFilesystemEncoding()) + << ' ' << quoteName(tempfile.toFilesystemEncoding()); + string const command_str = command.str(); + + lyxerr[Debug::TCLASS] << "Running `" << command_str << '\'' << endl; + + support::cmd_ret const ret = + support::runCommand(command_str); + if (ret.first != 0) { + lyxerr << "Could not run layout conversion " + "script layout2layout.py." << endl; + return false; + } + return true; +} + +} // namespace anon LyXTextClass::LyXTextClass(string const & fn, string const & cln, string const & desc, bool texClassAvail ) : name_(fn), latexname_(cln), description_(desc), - floatlist_(new FloatList), ctrs_(new Counters), texClassAvail_(texClassAvail) + floatlist_(new FloatList), ctrs_(new Counters), + texClassAvail_(texClassAvail) { outputType_ = LATEX; columns_ = 1; @@ -73,7 +116,7 @@ LyXTextClass::LyXTextClass(string const & fn, string const & cln, provides_ = nothing; titletype_ = TITLE_COMMAND_AFTER; titlename_ = "maketitle"; - loaded = false; + loaded_ = false; } @@ -86,7 +129,7 @@ bool LyXTextClass::isTeXClassAvailable() const bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay) { lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl; - if (!lay.Read(lexrc, *this)) { + if (!lay.read(lexrc, *this)) { // Resolve fonts lay.resfont = lay.font; lay.resfont.realize(defaultfont()); @@ -125,12 +168,20 @@ enum TextClassTags { TC_COUNTER, TC_NOFLOAT, TC_TITLELATEXNAME, - TC_TITLELATEXTYPE + TC_TITLELATEXTYPE, + TC_FORMAT }; + // Reads a textclass structure from file. -bool LyXTextClass::Read(string const & filename, bool merge) +bool LyXTextClass::read(FileName const & filename, bool merge) { + if (!support::isFileReadable(filename)) { + lyxerr << "Cannot read layout file `" << filename << "'." + << endl; + return true; + } + keyword_item textClassTags[] = { { "charstyle", TC_CHARSTYLE }, { "classoptions", TC_CLASSOPTIONS }, @@ -140,6 +191,7 @@ bool LyXTextClass::Read(string const & filename, bool merge) { "defaultstyle", TC_DEFAULTSTYLE }, { "environment", TC_ENVIRONMENT }, { "float", TC_FLOAT }, + { "format", TC_FORMAT }, { "input", TC_INPUT }, { "leftmargin", TC_LEFTMARGIN }, { "nofloat", TC_NOFLOAT }, @@ -162,19 +214,21 @@ bool LyXTextClass::Read(string const & filename, bool merge) if (!merge) lyxerr[Debug::TCLASS] << "Reading textclass " - << MakeDisplayPath(filename) - << endl; + << to_utf8(makeDisplayPath(filename.absFilename())) + << endl; else lyxerr[Debug::TCLASS] << "Reading input file " - << MakeDisplayPath(filename) + << to_utf8(makeDisplayPath(filename.absFilename())) << endl; LyXLex lexrc(textClassTags, sizeof(textClassTags) / sizeof(textClassTags[0])); - bool error = false; lexrc.setFile(filename); - if (!lexrc.isOK()) error = true; + bool error = !lexrc.isOK(); + + // Format of files before the 'Format' tag was introduced + int format = 1; // parsing while (lexrc.isOK() && !error) { @@ -195,19 +249,28 @@ bool LyXTextClass::Read(string const & filename, bool merge) switch (static_cast(le)) { + case TC_FORMAT: + if (lexrc.next()) + format = lexrc.getInteger(); + break; + case TC_OUTPUTTYPE: // output type definition readOutputType(lexrc); break; case TC_INPUT: // Include file if (lexrc.next()) { - string tmp = LibFileSearch("layouts", - lexrc.getString(), + string const inc = lexrc.getString(); + FileName tmp = libFileSearch("layouts", inc, "layout"); - if (Read(tmp, true)) { + if (tmp.empty()) { + lexrc.printError("Could not find input" + "file: " + inc); + error = true; + } else if (read(tmp, true)) { lexrc.printError("Error reading input" - "file: "+tmp); + "file: " + tmp.absFilename()); error = true; } } @@ -234,7 +297,8 @@ bool LyXTextClass::Read(string const & filename, bool merge) lay.setName(name); if (le == TC_ENVIRONMENT) lay.is_environment = true; - if (!(error = do_readStyle(lexrc, lay))) + error = do_readStyle(lexrc, lay); + if (!error) layoutlist_.push_back( boost::shared_ptr(new LyXLayout(lay)) ); @@ -316,7 +380,7 @@ bool LyXTextClass::Read(string const & filename, bool merge) break; case TC_PREAMBLE: - preamble_ = lexrc.getLongString("EndPreamble"); + preamble_ = from_utf8(lexrc.getLongString("EndPreamble")); break; case TC_PROVIDESAMSMATH: @@ -374,20 +438,54 @@ bool LyXTextClass::Read(string const & filename, bool merge) } break; } + if (format != FORMAT) + break; + } + + if (format != FORMAT) { + lyxerr[Debug::TCLASS] << "Converting layout file from format " + << format << " to " << FORMAT << endl; + FileName const tempfile(support::tempName()); + error = !layout2layout(filename, tempfile); + if (!error) + error = read(tempfile, merge); + support::unlink(tempfile); + return error; } if (!merge) { // we are at top level here. lyxerr[Debug::TCLASS] << "Finished reading textclass " - << MakeDisplayPath(filename) + << to_utf8(makeDisplayPath(filename.absFilename())) << endl; if (defaultlayout_.empty()) { lyxerr << "Error: Textclass '" << name_ << "' is missing a defaultstyle." << endl; error = true; } + + min_toclevel_ = LyXLayout::NOT_IN_TOC; + max_toclevel_ = LyXLayout::NOT_IN_TOC; + const_iterator cit = begin(); + const_iterator the_end = end(); + for ( ; cit != the_end ; ++cit) { + int const toclevel = (*cit)->toclevel; + if (toclevel != LyXLayout::NOT_IN_TOC) { + if (min_toclevel_ == LyXLayout::NOT_IN_TOC) + min_toclevel_ = toclevel; + else + min_toclevel_ = std::min(min_toclevel_, + toclevel); + max_toclevel_ = std::max(max_toclevel_, + toclevel); + } + } + lyxerr[Debug::TCLASS] + << "Minimum TocLevel is " << min_toclevel_ + << ", maximum is " << max_toclevel_ <(le); @@ -452,20 +548,6 @@ void LyXTextClass::readOutputType(LyXLex & lexrc) } -enum MaxCounterTags { - MC_COUNTER_CHAPTER = 1, - MC_COUNTER_SECTION, - MC_COUNTER_SUBSECTION, - MC_COUNTER_SUBSUBSECTION, - MC_COUNTER_PARAGRAPH, - MC_COUNTER_SUBPARAGRAPH, - MC_COUNTER_ENUMI, - MC_COUNTER_ENUMII, - MC_COUNTER_ENUMIII, - MC_COUNTER_ENUMIV -}; - - enum ClassOptionsTags { CO_FONTSIZE = 1, CO_PAGESTYLE, @@ -525,6 +607,7 @@ enum CharStyleTags { CS_LABELFONT, CS_LATEXTYPE, CS_LATEXNAME, + CS_LATEXPARAM, CS_PREAMBLE, CS_END }; @@ -537,6 +620,7 @@ void LyXTextClass::readCharStyle(LyXLex & lexrc, string const & name) { "font", CS_FONT }, { "labelfont", CS_LABELFONT }, { "latexname", CS_LATEXNAME }, + { "latexparam", CS_LATEXPARAM }, { "latextype", CS_LATEXTYPE }, { "preamble", CS_PREAMBLE} }; @@ -545,10 +629,11 @@ void LyXTextClass::readCharStyle(LyXLex & lexrc, string const & name) string latextype; string latexname; + string latexparam; LyXFont font(LyXFont::ALL_INHERIT); LyXFont labelfont(LyXFont::ALL_INHERIT); string preamble; - + bool getout = false; while (!getout && lexrc.isOK()) { int le = lexrc.lex(); @@ -567,6 +652,10 @@ void LyXTextClass::readCharStyle(LyXLex & lexrc, string const & name) lexrc.next(); latexname = lexrc.getString(); break; + case CS_LATEXPARAM: + lexrc.next(); + latexparam = subst(lexrc.getString(), """, "\""); + break; case CS_LABELFONT: labelfont.lyxRead(lexrc); break; @@ -590,9 +679,10 @@ void LyXTextClass::readCharStyle(LyXLex & lexrc, string const & name) cs.name = name; cs.latextype = latextype; cs.latexname = latexname; + cs.latexparam = latexparam; cs.font = font; cs.labelfont = labelfont; - cs.preamble = preamble; + cs.preamble = from_utf8(preamble); charstyles().push_back(cs); } @@ -717,8 +807,8 @@ void LyXTextClass::readCounter(LyXLex & lexrc) lexrc.pushTable(counterTags, CT_END); - string name; - string within; + docstring name; + docstring within; bool getout = false; while (!getout && lexrc.isOK()) { @@ -732,11 +822,11 @@ void LyXTextClass::readCounter(LyXLex & lexrc) switch (static_cast(le)) { case CT_NAME: lexrc.next(); - name = lexrc.getString(); + name = from_ascii(lexrc.getString()); break; case CT_WITHIN: lexrc.next(); - within = lexrc.getString(); + within = from_ascii(lexrc.getString()); if (within == "none") within.erase(); break; @@ -748,11 +838,10 @@ void LyXTextClass::readCounter(LyXLex & lexrc) // Here if have a full counter if getout == true if (getout) { - if (within.empty()) { + if (within.empty()) ctrs_->newCounter(name); - } else { + else ctrs_->newCounter(name, within); - } } lexrc.popTable(); @@ -782,7 +871,7 @@ bool LyXTextClass::hasLayout(string const & n) const string const name = (n.empty() ? defaultLayoutName() : n); return find_if(layoutlist_.begin(), layoutlist_.end(), - compare_name(name)) + LayoutNamesEqual(name)) != layoutlist_.end(); } @@ -795,14 +884,14 @@ LyXLayout_ptr const & LyXTextClass::operator[](string const & name) const LayoutList::const_iterator cit = find_if(layoutlist_.begin(), layoutlist_.end(), - compare_name(name)); + LayoutNamesEqual(name)); if (cit == layoutlist_.end()) { lyxerr << "We failed to find the layout '" << name << "' in the layout list. You MUST investigate!" << endl; for (LayoutList::const_iterator it = layoutlist_.begin(); - it != layoutlist_.end(); ++it) + it != layoutlist_.end(); ++it) lyxerr << " " << it->get()->name() << endl; // we require the name to exist @@ -821,7 +910,7 @@ bool LyXTextClass::delete_layout(string const & name) LayoutList::iterator it = remove_if(layoutlist_.begin(), layoutlist_.end(), - compare_name(name)); + LayoutNamesEqual(name)); LayoutList::iterator end = layoutlist_.end(); bool const ret = (it != end); @@ -831,24 +920,28 @@ bool LyXTextClass::delete_layout(string const & name) // Load textclass info if not loaded yet -bool LyXTextClass::load() const +bool LyXTextClass::load(string const & path) const { - if (loaded) + if (loaded_) return true; - // Read style-file - string const real_file = LibFileSearch("layouts", name_, "layout"); + // Read style-file, provided path is searched before the system ones + FileName layout_file; + if (!path.empty()) + layout_file = FileName(addName(path, name_ + ".layout")); + if (layout_file.empty() || !fs::exists(layout_file.toFilesystemEncoding())) + layout_file = libFileSearch("layouts", name_, "layout"); + loaded_ = const_cast(this)->read(layout_file) == 0; - if (const_cast(this)->Read(real_file)) { + if (!loaded_) { lyxerr << "Error reading `" - << MakeDisplayPath(real_file) + << to_utf8(makeDisplayPath(layout_file.absFilename())) << "'\n(Check `" << name_ << "')\nCheck your installation and " "try Options/Reconfigure..." << endl; - loaded = false; } - loaded = true; - return loaded; + + return loaded_; } @@ -944,7 +1037,7 @@ string const & LyXTextClass::pagestyle() const } -string const & LyXTextClass::preamble() const +docstring const & LyXTextClass::preamble() const { return preamble_; } @@ -1004,6 +1097,24 @@ int LyXTextClass::size() const } +int LyXTextClass::min_toclevel() const +{ + return min_toclevel_; +} + + +int LyXTextClass::max_toclevel() const +{ + return max_toclevel_; +} + + +bool LyXTextClass::hasTocLevels() const +{ + return min_toclevel_ != LyXLayout::NOT_IN_TOC; +} + + ostream & operator<<(ostream & os, LyXTextClass::PageSides p) { switch (p) { @@ -1016,3 +1127,6 @@ ostream & operator<<(ostream & os, LyXTextClass::PageSides p) } return os; } + + +} // namespace lyx