X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxtextclass.C;h=cdda271a71d942a40660e246fcc891867197cc9d;hb=e7f4618bcce770369cf46335c2c7f0164b4b8857;hp=b2ee820c70ecaeb027e7a900a31dffef7b1e90a3;hpb=22c088071d45822551069b9b616e3d87f66666e3;p=lyx.git diff --git a/src/lyxtextclass.C b/src/lyxtextclass.C index b2ee820c70..cdda271a71 100644 --- a/src/lyxtextclass.C +++ b/src/lyxtextclass.C @@ -1,41 +1,108 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. +/** + * \file lyxtextclass.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * ====================================================== + * \author Lars Gullik Bjønnes + * \author Jean-Marc Lasgouttes + * \author Angus Leeming + * \author John Levon + * \author André Pönitz + * + * Full author contact details are available in file CREDITS. */ #include -#ifdef __GNUG__ -#pragma implementation -#endif - #include "lyxtextclass.h" #include "debug.h" #include "lyxlex.h" +#include "counters.h" +#include "Floating.h" +#include "FloatList.h" #include "support/lstrings.h" -#include "support/LAssert.h" -#include "support/lyxfunctional.h" +#include "support/lyxlib.h" #include "support/filetools.h" +#include "support/os.h" + +#include +namespace fs = boost::filesystem; + +#include + + +namespace lyx { -#include +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; using std::remove_if; +using std::string; +using std::ostream; + + +namespace { + +class LayoutNamesEqual : public std::unary_function { +public: + LayoutNamesEqual(string const & name) + : name_(name) + {} + bool operator()(LyXLayout_ptr const & c) const + { + return c->name() == name_; + } +private: + string name_; +}; + + +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) - : name_(fn), latexname_(cln), description_(desc) + string const & desc, bool texClassAvail ) + : name_(fn), latexname_(cln), description_(desc), + floatlist_(new FloatList), ctrs_(new Counters), + texClassAvail_(texClassAvail) { outputType_ = LATEX; columns_ = 1; @@ -43,33 +110,34 @@ LyXTextClass::LyXTextClass(string const & fn, string const & cln, secnumdepth_ = 3; tocdepth_ = 3; pagestyle_ = "default"; - maxcounter_ = LABEL_COUNTER_CHAPTER; defaultfont_ = LyXFont(LyXFont::ALL_SANE); opt_fontsize_ = "10|11|12"; opt_pagestyle_ = "empty|plain|headings|fancy"; provides_ = nothing; - loaded = false; + titletype_ = TITLE_COMMAND_AFTER; + titlename_ = "maketitle"; + loaded_ = false; +} + + +bool LyXTextClass::isTeXClassAvailable() const +{ + return texClassAvail_; } bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay) { lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl; - if (!lay.Read(lexrc, *this)) { - // Reslove fonts + if (!lay.read(lexrc, *this)) { + // Resolve fonts lay.resfont = lay.font; -#ifndef INHERIT_LANGUAGE lay.resfont.realize(defaultfont()); lay.reslabelfont = lay.labelfont; lay.reslabelfont.realize(defaultfont()); -#else - lay.resfont.realize(defaultfont(), default_language); - lay.reslabelfont = lay.labelfont; - lay.reslabelfont.realize(defaultfont(), default_language); -#endif return false; // no errors - } - lyxerr << "Error parsing style `" << lay.name() << "'" << endl; + } + lyxerr << "Error parsing style `" << lay.name() << '\'' << endl; return true; } @@ -78,107 +146,170 @@ enum TextClassTags { TC_OUTPUTTYPE = 1, TC_INPUT, TC_STYLE, + TC_DEFAULTSTYLE, + TC_CHARSTYLE, + TC_ENVIRONMENT, TC_NOSTYLE, TC_COLUMNS, TC_SIDES, TC_PAGESTYLE, TC_DEFAULTFONT, - TC_MAXCOUNTER, TC_SECNUMDEPTH, TC_TOCDEPTH, TC_CLASSOPTIONS, TC_PREAMBLE, TC_PROVIDESAMSMATH, + TC_PROVIDESNATBIB, TC_PROVIDESMAKEIDX, TC_PROVIDESURL, TC_LEFTMARGIN, - TC_RIGHTMARGIN + TC_RIGHTMARGIN, + TC_FLOAT, + TC_COUNTER, + TC_NOFLOAT, + TC_TITLELATEXNAME, + 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 }, { "columns", TC_COLUMNS }, + { "counter", TC_COUNTER }, { "defaultfont", TC_DEFAULTFONT }, + { "defaultstyle", TC_DEFAULTSTYLE }, + { "environment", TC_ENVIRONMENT }, + { "float", TC_FLOAT }, + { "format", TC_FORMAT }, { "input", TC_INPUT }, { "leftmargin", TC_LEFTMARGIN }, - { "maxcounter", TC_MAXCOUNTER }, + { "nofloat", TC_NOFLOAT }, { "nostyle", TC_NOSTYLE }, { "outputtype", TC_OUTPUTTYPE }, { "pagestyle", TC_PAGESTYLE }, { "preamble", TC_PREAMBLE }, { "providesamsmath", TC_PROVIDESAMSMATH }, { "providesmakeidx", TC_PROVIDESMAKEIDX }, + { "providesnatbib", TC_PROVIDESNATBIB }, { "providesurl", TC_PROVIDESURL }, { "rightmargin", TC_RIGHTMARGIN }, { "secnumdepth", TC_SECNUMDEPTH }, { "sides", TC_SIDES }, { "style", TC_STYLE }, + { "titlelatexname", TC_TITLELATEXNAME }, + { "titlelatextype", TC_TITLELATEXTYPE }, { "tocdepth", TC_TOCDEPTH } }; 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, TC_RIGHTMARGIN); - bool error = false; - lexrc.setFile(filename); - if (!lexrc.isOK()) error = true; + LyXLex lexrc(textClassTags, + sizeof(textClassTags) / sizeof(textClassTags[0])); + + lexrc.setFile(filename); + bool error = !lexrc.isOK(); + + // Format of files before the 'Format' tag was introduced + int format = 1; // parsing while (lexrc.isOK() && !error) { int le = lexrc.lex(); + switch (le) { case LyXLex::LEX_FEOF: - continue; + continue; - case LyXLex::LEX_UNDEF: + case LyXLex::LEX_UNDEF: lexrc.printError("Unknown TextClass tag `$$Token'"); error = true; - continue; - default: break; + continue; + + default: + break; } + 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(), + if (lexrc.next()) { + 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; } } break; + case TC_DEFAULTSTYLE: + if (lexrc.next()) { + string const name = subst(lexrc.getString(), + '_', ' '); + defaultlayout_ = name; + } + break; + + case TC_ENVIRONMENT: case TC_STYLE: if (lexrc.next()) { - string name = subst(lexrc.getString(), + string const name = subst(lexrc.getString(), '_', ' '); if (hasLayout(name)) { - LyXLayout & lay = GetLayout(name); - error = do_readStyle(lexrc, lay); + LyXLayout * lay = operator[](name).get(); + error = do_readStyle(lexrc, *lay); } else { LyXLayout lay; lay.setName(name); - if (!(error = do_readStyle(lexrc, lay))) - layoutlist.push_back(lay); + if (le == TC_ENVIRONMENT) + lay.is_environment = true; + error = do_readStyle(lexrc, lay); + if (!error) + layoutlist_.push_back( + boost::shared_ptr(new LyXLayout(lay)) + ); + + if (defaultlayout_.empty()) { + // We do not have a default + // layout yet, so we choose + // the first layout we + // encounter. + defaultlayout_ = name; + } } } else { @@ -192,8 +323,10 @@ bool LyXTextClass::Read(string const & filename, bool merge) string const style = subst(lexrc.getString(), '_', ' '); if (!delete_layout(style)) - lexrc.printError("Cannot delete style" - " `$$Token'"); + lyxerr << "Cannot delete style `" + << style << '\'' << endl; +// lexrc.printError("Cannot delete style" +// " `$$Token'"); } break; @@ -201,7 +334,7 @@ bool LyXTextClass::Read(string const & filename, bool merge) if (lexrc.next()) columns_ = lexrc.getInteger(); break; - + case TC_SIDES: if (lexrc.next()) { switch (lexrc.getInteger()) { @@ -216,30 +349,21 @@ bool LyXTextClass::Read(string const & filename, bool merge) } } break; - + case TC_PAGESTYLE: - lexrc.next(); - pagestyle_ = strip(lexrc.getString()); + lexrc.next(); + pagestyle_ = rtrim(lexrc.getString()); break; - + case TC_DEFAULTFONT: defaultfont_.lyxRead(lexrc); if (!defaultfont_.resolved()) { lexrc.printError("Warning: defaultfont should " "be fully instantiated!"); -#ifndef INHERIT_LANGUAGE defaultfont_.realize(LyXFont(LyXFont::ALL_SANE)); -#else - defaultfont_.realize(LyXFont(LyXFont::ALL_SANE), - default_language); -#endif } break; - case TC_MAXCOUNTER: - readMaxCounter(lexrc); - break; - case TC_SECNUMDEPTH: lexrc.next(); secnumdepth_ = lexrc.getInteger(); @@ -250,13 +374,13 @@ bool LyXTextClass::Read(string const & filename, bool merge) tocdepth_ = lexrc.getInteger(); break; - // First step to support options - case TC_CLASSOPTIONS: + // First step to support options + case TC_CLASSOPTIONS: readClassOptions(lexrc); - break; + break; case TC_PREAMBLE: - preamble_ = lexrc.getLongString("EndPreamble"); + preamble_ = from_utf8(lexrc.getLongString("EndPreamble")); break; case TC_PROVIDESAMSMATH: @@ -264,6 +388,11 @@ bool LyXTextClass::Read(string const & filename, bool merge) provides_ |= amsmath; break; + case TC_PROVIDESNATBIB: + if (lexrc.next() && lexrc.getInteger()) + provides_ |= natbib; + break; + case TC_PROVIDESMAKEIDX: if (lexrc.next() && lexrc.getInteger()) provides_ |= makeidx; @@ -271,132 +400,149 @@ bool LyXTextClass::Read(string const & filename, bool merge) case TC_PROVIDESURL: if (lexrc.next() && lexrc.getInteger()) - provides_ = url; + provides_ |= url; break; case TC_LEFTMARGIN: // left margin type - if (lexrc.next()) + if (lexrc.next()) leftmargin_ = lexrc.getString(); - break; + break; case TC_RIGHTMARGIN: // right margin type if (lexrc.next()) rightmargin_ = lexrc.getString(); break; + case TC_CHARSTYLE: + if (lexrc.next()) { + string const name = subst(lexrc.getString(), '_', ' '); + readCharStyle(lexrc, name); + } + break; + case TC_FLOAT: + readFloat(lexrc); + break; + case TC_COUNTER: + readCounter(lexrc); + break; + case TC_TITLELATEXTYPE: + readTitleType(lexrc); + break; + case TC_TITLELATEXNAME: + if (lexrc.next()) + titlename_ = lexrc.getString(); + break; + case TC_NOFLOAT: + if (lexrc.next()) { + string const nofloat = lexrc.getString(); + floatlist_->erase(nofloat); + } + 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) + lyxerr[Debug::TCLASS] << "Finished reading textclass " + << 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); + case TITLE_COMMAND_AFTER: + case TITLE_ENVIRONMENT: + titletype_ = static_cast(le); break; default: lyxerr << "Unhandled value " << le - << " in LyXTextClass::readOutputType." << endl; + << " in LyXTextClass::readTitleType." << endl; break; } } -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 -}; - - -void LyXTextClass::readMaxCounter(LyXLex & lexrc) +void LyXTextClass::readOutputType(LyXLex & lexrc) { - keyword_item maxCounterTags[] = { - {"counter_chapter", MC_COUNTER_CHAPTER }, - {"counter_enumi", MC_COUNTER_ENUMI }, - {"counter_enumii", MC_COUNTER_ENUMII }, - {"counter_enumiii", MC_COUNTER_ENUMIII }, - {"counter_enumiv", MC_COUNTER_ENUMIV }, - {"counter_paragraph", MC_COUNTER_PARAGRAPH }, - {"counter_section", MC_COUNTER_SECTION }, - {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH }, - {"counter_subsection", MC_COUNTER_SUBSECTION }, - {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION } + keyword_item outputTypeTags[] = { + { "docbook", DOCBOOK }, + { "latex", LATEX }, + { "literate", LITERATE } }; - pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV); + pushpophelper pph(lexrc, outputTypeTags, LITERATE); + int le = lexrc.lex(); switch (le) { case LyXLex::LEX_UNDEF: - lexrc.printError("Unknown MaxCounter tag `$$Token'"); - return; - default: break; - } - switch (static_cast(le)) { - case MC_COUNTER_CHAPTER: - maxcounter_ = LABEL_COUNTER_CHAPTER; - break; - case MC_COUNTER_SECTION: - maxcounter_ = LABEL_COUNTER_SECTION; - break; - case MC_COUNTER_SUBSECTION: - maxcounter_ = LABEL_COUNTER_SUBSECTION; - break; - case MC_COUNTER_SUBSUBSECTION: - maxcounter_ = LABEL_COUNTER_SUBSUBSECTION; - break; - case MC_COUNTER_PARAGRAPH: - maxcounter_ = LABEL_COUNTER_PARAGRAPH; - break; - case MC_COUNTER_SUBPARAGRAPH: - maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH; - break; - case MC_COUNTER_ENUMI: - maxcounter_ = LABEL_COUNTER_ENUMI; - break; - case MC_COUNTER_ENUMII: - maxcounter_ = LABEL_COUNTER_ENUMII; - break; - case MC_COUNTER_ENUMIII: - maxcounter_ = LABEL_COUNTER_ENUMIII; + lexrc.printError("Unknown output type `$$Token'"); + return; + case LATEX: + case DOCBOOK: + case LITERATE: + outputType_ = static_cast(le); break; - case MC_COUNTER_ENUMIV: - maxcounter_ = LABEL_COUNTER_ENUMIV; + default: + lyxerr << "Unhandled value " << le + << " in LyXTextClass::readOutputType." << endl; + break; } } @@ -406,6 +552,7 @@ enum ClassOptionsTags { CO_FONTSIZE = 1, CO_PAGESTYLE, CO_OTHER, + CO_HEADER, CO_END }; @@ -415,6 +562,7 @@ void LyXTextClass::readClassOptions(LyXLex & lexrc) keyword_item classOptionsTags[] = { {"end", CO_END }, {"fontsize", CO_FONTSIZE }, + {"header", CO_HEADER }, {"other", CO_OTHER }, {"pagestyle", CO_PAGESTYLE } }; @@ -426,22 +574,26 @@ void LyXTextClass::readClassOptions(LyXLex & lexrc) switch (le) { case LyXLex::LEX_UNDEF: lexrc.printError("Unknown ClassOption tag `$$Token'"); - continue; + continue; default: break; } switch (static_cast(le)) { case CO_FONTSIZE: lexrc.next(); - opt_fontsize_ = strip(lexrc.getString()); + opt_fontsize_ = rtrim(lexrc.getString()); break; case CO_PAGESTYLE: lexrc.next(); - opt_pagestyle_ = strip(lexrc.getString()); + opt_pagestyle_ = rtrim(lexrc.getString()); break; case CO_OTHER: lexrc.next(); options_ = lexrc.getString(); break; + case CO_HEADER: + lexrc.next(); + class_header_ = subst(lexrc.getString(), """, "\""); + break; case CO_END: getout = true; break; @@ -450,6 +602,251 @@ void LyXTextClass::readClassOptions(LyXLex & lexrc) lexrc.popTable(); } +enum CharStyleTags { + CS_FONT = 1, + CS_LABELFONT, + CS_LATEXTYPE, + CS_LATEXNAME, + CS_LATEXPARAM, + CS_PREAMBLE, + CS_END +}; + + +void LyXTextClass::readCharStyle(LyXLex & lexrc, string const & name) +{ + keyword_item elementTags[] = { + { "end", CS_END }, + { "font", CS_FONT }, + { "labelfont", CS_LABELFONT }, + { "latexname", CS_LATEXNAME }, + { "latexparam", CS_LATEXPARAM }, + { "latextype", CS_LATEXTYPE }, + { "preamble", CS_PREAMBLE} + }; + + lexrc.pushTable(elementTags, CS_END); + + 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(); + switch (le) { + case LyXLex::LEX_UNDEF: + lexrc.printError("Unknown ClassOption tag `$$Token'"); + continue; + default: break; + } + switch (static_cast(le)) { + case CS_LATEXTYPE: + lexrc.next(); + latextype = lexrc.getString(); + break; + case CS_LATEXNAME: + lexrc.next(); + latexname = lexrc.getString(); + break; + case CS_LATEXPARAM: + lexrc.next(); + latexparam = subst(lexrc.getString(), """, "\""); + break; + case CS_LABELFONT: + labelfont.lyxRead(lexrc); + break; + case CS_FONT: + font.lyxRead(lexrc); + labelfont = font; + break; + case CS_PREAMBLE: + preamble = lexrc.getLongString("EndPreamble"); + break; + case CS_END: + getout = true; + break; + } + } + + // + // Here add element to list if getout == true + if (getout) { + CharStyle cs; + cs.name = name; + cs.latextype = latextype; + cs.latexname = latexname; + cs.latexparam = latexparam; + cs.font = font; + cs.labelfont = labelfont; + cs.preamble = from_utf8(preamble); + charstyles().push_back(cs); + } + + lexrc.popTable(); +} + + +enum FloatTags { + FT_TYPE = 1, + FT_NAME, + FT_PLACEMENT, + FT_EXT, + FT_WITHIN, + FT_STYLE, + FT_LISTNAME, + FT_BUILTIN, + FT_END +}; + + +void LyXTextClass::readFloat(LyXLex & lexrc) +{ + keyword_item floatTags[] = { + { "end", FT_END }, + { "extension", FT_EXT }, + { "guiname", FT_NAME }, + { "latexbuiltin", FT_BUILTIN }, + { "listname", FT_LISTNAME }, + { "numberwithin", FT_WITHIN }, + { "placement", FT_PLACEMENT }, + { "style", FT_STYLE }, + { "type", FT_TYPE } + }; + + lexrc.pushTable(floatTags, FT_END); + + string type; + string placement; + string ext; + string within; + string style; + string name; + string listname; + bool builtin = false; + + bool getout = false; + while (!getout && lexrc.isOK()) { + int le = lexrc.lex(); + switch (le) { + case LyXLex::LEX_UNDEF: + lexrc.printError("Unknown ClassOption tag `$$Token'"); + continue; + default: break; + } + switch (static_cast(le)) { + case FT_TYPE: + lexrc.next(); + type = lexrc.getString(); + // Here we could check if this type is already defined + // and modify it with the rest of the vars instead. + break; + case FT_NAME: + lexrc.next(); + name = lexrc.getString(); + break; + case FT_PLACEMENT: + lexrc.next(); + placement = lexrc.getString(); + break; + case FT_EXT: + lexrc.next(); + ext = lexrc.getString(); + break; + case FT_WITHIN: + lexrc.next(); + within = lexrc.getString(); + if (within == "none") + within.erase(); + break; + case FT_STYLE: + lexrc.next(); + style = lexrc.getString(); + break; + case FT_LISTNAME: + lexrc.next(); + listname = lexrc.getString(); + break; + case FT_BUILTIN: + lexrc.next(); + builtin = lexrc.getBool(); + break; + case FT_END: + getout = true; + break; + } + } + + // Here if have a full float if getout == true + if (getout) { + Floating newfloat(type, placement, ext, within, + style, name, listname, builtin); + floatlist_->newFloat(newfloat); + } + + lexrc.popTable(); +} + + +enum CounterTags { + CT_NAME = 1, + CT_WITHIN, + CT_END +}; + +void LyXTextClass::readCounter(LyXLex & lexrc) +{ + keyword_item counterTags[] = { + { "end", CT_END }, + { "name", CT_NAME }, + { "within", CT_WITHIN } + }; + + lexrc.pushTable(counterTags, CT_END); + + docstring name; + docstring within; + + bool getout = false; + while (!getout && lexrc.isOK()) { + int le = lexrc.lex(); + switch (le) { + case LyXLex::LEX_UNDEF: + lexrc.printError("Unknown ClassOption tag `$$Token'"); + continue; + default: break; + } + switch (static_cast(le)) { + case CT_NAME: + lexrc.next(); + name = from_ascii(lexrc.getString()); + break; + case CT_WITHIN: + lexrc.next(); + within = from_ascii(lexrc.getString()); + if (within == "none") + within.erase(); + break; + case CT_END: + getout = true; + break; + } + } + + // Here if have a full counter if getout == true + if (getout) { + if (within.empty()) + ctrs_->newCounter(name); + else + ctrs_->newCounter(name, within); + } + + lexrc.popTable(); +} + LyXFont const & LyXTextClass::defaultfont() const { @@ -469,76 +866,267 @@ string const & LyXTextClass::rightmargin() const } -bool LyXTextClass::hasLayout(string const & name) const +bool LyXTextClass::hasLayout(string const & n) const { - return find_if(layoutlist.begin(), layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)) - != layoutlist.end(); + string const name = (n.empty() ? defaultLayoutName() : n); + + return find_if(layoutlist_.begin(), layoutlist_.end(), + LayoutNamesEqual(name)) + != layoutlist_.end(); } -LyXLayout const & LyXTextClass::GetLayout (string const & name) const + +LyXLayout_ptr const & LyXTextClass::operator[](string const & name) const { + BOOST_ASSERT(!name.empty()); + LayoutList::const_iterator cit = - find_if(layoutlist.begin(), - layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)); - lyx::Assert(cit != layoutlist.end()); // we require the name to exist + find_if(layoutlist_.begin(), + layoutlist_.end(), + 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) + lyxerr << " " << it->get()->name() << endl; + + // we require the name to exist + BOOST_ASSERT(false); + } + return (*cit); } -LyXLayout & LyXTextClass::GetLayout(string const & name) -{ - LayoutList::iterator it = - find_if(layoutlist.begin(), - layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)); - lyx::Assert(it != layoutlist.end()); // we require the name to exist - return (*it); -} - bool LyXTextClass::delete_layout(string const & name) { + if (name == defaultLayoutName()) + return false; + LayoutList::iterator it = - remove_if(layoutlist.begin(), layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)); - LayoutList::iterator end = layoutlist.end(); + remove_if(layoutlist_.begin(), layoutlist_.end(), + LayoutNamesEqual(name)); + + LayoutList::iterator end = layoutlist_.end(); bool const ret = (it != end); - layoutlist.erase(it, end); + layoutlist_.erase(it, end); return ret; } // Load textclass info if not loaded yet -void LyXTextClass::load() +bool LyXTextClass::load(string const & path) const { - if (loaded) return; - - // Read style-file - string const real_file = LibFileSearch("layouts", name_, "layout"); - - if (Read(real_file)) { + if (loaded_) + return true; + + // 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 (!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 = true; + + return loaded_; +} + + +FloatList & LyXTextClass::floats() +{ + return *floatlist_.get(); +} + + +FloatList const & LyXTextClass::floats() const +{ + return *floatlist_.get(); +} + + +Counters & LyXTextClass::counters() const +{ + return *ctrs_.get(); +} + + +CharStyles::iterator LyXTextClass::charstyle(string const & s) const +{ + CharStyles::iterator cs = charstyles().begin(); + CharStyles::iterator csend = charstyles().end(); + for (; cs != csend; ++cs) { + if (cs->name == s) + return cs; + } + return csend; +} + + +string const & LyXTextClass::defaultLayoutName() const +{ + // This really should come from the actual layout... (Lgb) + return defaultlayout_; } -std::ostream & operator<<(std::ostream & os, LyXTextClass::PageSides p) +LyXLayout_ptr const & LyXTextClass::defaultLayout() const +{ + return operator[](defaultLayoutName()); +} + + +string const & LyXTextClass::name() const +{ + return name_; +} + + +string const & LyXTextClass::latexname() const +{ + const_cast(this)->load(); + return latexname_; +} + + +string const & LyXTextClass::description() const +{ + return description_; +} + + +string const & LyXTextClass::opt_fontsize() const +{ + return opt_fontsize_; +} + + +string const & LyXTextClass::opt_pagestyle() const +{ + return opt_pagestyle_; +} + + +string const & LyXTextClass::options() const +{ + return options_; +} + + +string const & LyXTextClass::class_header() const +{ + return class_header_; +} + + +string const & LyXTextClass::pagestyle() const +{ + return pagestyle_; +} + + +docstring const & LyXTextClass::preamble() const +{ + return preamble_; +} + + +LyXTextClass::PageSides LyXTextClass::sides() const +{ + return sides_; +} + + +int LyXTextClass::secnumdepth() const +{ + return secnumdepth_; +} + + +int LyXTextClass::tocdepth() const +{ + return tocdepth_; +} + + +OutputType LyXTextClass::outputType() const +{ + return outputType_; +} + + +bool LyXTextClass::provides(LyXTextClass::Provides p) const +{ + return provides_ & p; +} + + +unsigned int LyXTextClass::columns() const +{ + return columns_; +} + + +LYX_TITLE_LATEX_TYPES LyXTextClass::titletype() const +{ + return titletype_; +} + + +string const & LyXTextClass::titlename() const +{ + return titlename_; +} + + +int LyXTextClass::size() const +{ + return layoutlist_.size(); +} + + +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) { case LyXTextClass::OneSide: - os << "1"; + os << '1'; break; case LyXTextClass::TwoSides: - os << "2"; + os << '2'; break; } return os; } + + +} // namespace lyx