X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxtextclass.C;h=fe35702d0ceeb9ccb06a5d77c461cfd35f14c57f;hb=24f8676130d1e0769db394b7142dae7eeb1d955e;hp=7fdb478d96bb26b6b507b724ba2b70bb59bd7803;hpb=b9288969ec06caa3d7b1e9d4eb7937c1e029b44f;p=lyx.git diff --git a/src/lyxtextclass.C b/src/lyxtextclass.C index 7fdb478d96..fe35702d0c 100644 --- a/src/lyxtextclass.C +++ b/src/lyxtextclass.C @@ -1,23 +1,24 @@ -/* 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 "FloatList.h" #include "support/lstrings.h" #include "support/LAssert.h" @@ -26,17 +27,37 @@ #include +using namespace lyx::support; + using std::endl; using std::find_if; using std::remove_if; using std::ostream; +namespace { // anon + +struct compare_name { + + compare_name(string const & name) + : name_(name) + {} + + bool operator()(boost::shared_ptr const & c) + { + return c->name() == name_; + } + + string name_; + +}; + +} // 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; @@ -49,28 +70,30 @@ LyXTextClass::LyXTextClass(string const & fn, string const & cln, opt_fontsize_ = "10|11|12"; opt_pagestyle_ = "empty|plain|headings|fancy"; provides_ = nothing; + 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)) { // 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; } @@ -80,6 +103,7 @@ enum TextClassTags { TC_INPUT, TC_STYLE, TC_DEFAULTSTYLE, + TC_ENVIRONMENT, TC_NOSTYLE, TC_COLUMNS, TC_SIDES, @@ -91,35 +115,47 @@ enum TextClassTags { 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 }; - // Reads a textclass structure from file. bool LyXTextClass::Read(string const & filename, bool merge) { keyword_item textClassTags[] = { { "classoptions", TC_CLASSOPTIONS }, { "columns", TC_COLUMNS }, + { "counter", TC_COUNTER }, { "defaultfont", TC_DEFAULTFONT }, { "defaultstyle", TC_DEFAULTSTYLE }, + { "environment", TC_ENVIRONMENT }, + { "float", TC_FLOAT }, { "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 } }; @@ -131,37 +167,43 @@ bool LyXTextClass::Read(string const & filename, bool merge) lyxerr[Debug::TCLASS] << "Reading input file " << MakeDisplayPath(filename) << endl; - - LyXLex lexrc(textClassTags, TC_RIGHTMARGIN); + + LyXLex lexrc(textClassTags, + sizeof(textClassTags) / sizeof(textClassTags[0])); bool error = false; - lexrc.setFile(filename); - if (!lexrc.isOK()) error = true; + lexrc.setFile(filename); + if (!lexrc.isOK()) error = true; // 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_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 tmp = LibFileSearch("layouts", + lexrc.getString(), "layout"); - + if (Read(tmp, true)) { lexrc.printError("Error reading input" "file: "+tmp); @@ -177,19 +219,23 @@ bool LyXTextClass::Read(string const & filename, bool merge) defaultlayout_ = name; } break; - + + case TC_ENVIRONMENT: case TC_STYLE: if (lexrc.next()) { string const name = subst(lexrc.getString(), '_', ' '); if (hasLayout(name)) { - LyXLayout & lay = operator[](name); - error = do_readStyle(lexrc, lay); + LyXLayout * lay = operator[](name).get(); + error = do_readStyle(lexrc, *lay); } else { LyXLayout lay; lay.setName(name); + if (le == TC_ENVIRONMENT) + lay.is_environment = true; if (!(error = do_readStyle(lexrc, lay))) - layoutlist.push_back(lay); + layoutlist_.push_back + (boost::shared_ptr(new LyXLayout(lay))); if (defaultlayout_.empty()) { // We do not have a default // layout yet, so we choose @@ -210,7 +256,8 @@ bool LyXTextClass::Read(string const & filename, bool merge) string const style = subst(lexrc.getString(), '_', ' '); if (!delete_layout(style)) - lyxerr << "Cannot delete style `" << style << "'" << endl; + lyxerr << "Cannot delete style `" + << style << '\'' << endl; // lexrc.printError("Cannot delete style" // " `$$Token'"); } @@ -220,7 +267,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()) { @@ -235,23 +282,18 @@ 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; @@ -269,10 +311,10 @@ 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"); @@ -283,6 +325,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; @@ -290,23 +337,42 @@ 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_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 (!merge) { // we are at top level here. - lyxerr[Debug::TCLASS] << "Finished reading textclass " + lyxerr[Debug::TCLASS] << "Finished reading textclass " << MakeDisplayPath(filename) << endl; if (defaultlayout_.empty()) { @@ -315,7 +381,7 @@ bool LyXTextClass::Read(string const & filename, bool merge) error = true; } } else - lyxerr[Debug::TCLASS] << "Finished reading input file " + lyxerr[Debug::TCLASS] << "Finished reading input file " << MakeDisplayPath(filename) << endl; @@ -323,6 +389,33 @@ bool LyXTextClass::Read(string const & filename, bool merge) } +void LyXTextClass::readTitleType(LyXLex & lexrc) +{ + keyword_item titleTypeTags[] = { + { "commandafter", TITLE_COMMAND_AFTER }, + { "environment", TITLE_ENVIRONMENT } + }; + + pushpophelper pph(lexrc, titleTypeTags, TITLE_ENVIRONMENT); + + int le = lexrc.lex(); + switch (le) { + case LyXLex::LEX_UNDEF: + lexrc.printError("Unknown output type `$$Token'"); + return; + case TITLE_COMMAND_AFTER: + case TITLE_ENVIRONMENT: + titletype_ = static_cast(le); + break; + default: + lyxerr << "Unhandled value " << le + << " in LyXTextClass::readTitleType." << endl; + + break; + } +} + + void LyXTextClass::readOutputType(LyXLex & lexrc) { keyword_item outputTypeTags[] = { @@ -384,13 +477,16 @@ void LyXTextClass::readMaxCounter(LyXLex & lexrc) }; pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV); + int le = lexrc.lex(); switch (le) { case LyXLex::LEX_UNDEF: lexrc.printError("Unknown MaxCounter tag `$$Token'"); - return; - default: break; + return; + default: + break; } + switch (static_cast(le)) { case MC_COUNTER_CHAPTER: maxcounter_ = LABEL_COUNTER_CHAPTER; @@ -450,17 +546,17 @@ 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(); @@ -475,6 +571,164 @@ void LyXTextClass::readClassOptions(LyXLex & lexrc) } +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); + + string name; + string 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 = lexrc.getString(); + break; + case CT_WITHIN: + lexrc.next(); + within = lexrc.getString(); + if (within == "none") + within.erase(); + break; + case CT_END: + getout = true; + break; + } + } + + // Here if have a full float if getout == true + if (getout) { + if (within.empty()) { + ctrs_->newCounter(name); + } else { + ctrs_->newCounter(name, within); + } + } + + lexrc.popTable(); +} + + LyXFont const & LyXTextClass::defaultfont() const { return defaultfont_; @@ -496,74 +750,52 @@ string const & LyXTextClass::rightmargin() const bool LyXTextClass::hasLayout(string const & n) const { string const name = (n.empty() ? defaultLayoutName() : n); - - return find_if(layoutlist.begin(), layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)) - != layoutlist.end(); + + return find_if(layoutlist_.begin(), layoutlist_.end(), + compare_name(name)) + != layoutlist_.end(); } -LyXLayout const & LyXTextClass::operator[](string const & n) const + +LyXLayout_ptr const & LyXTextClass::operator[](string const & name) const { - if (n.empty()) - lyxerr << "Operator[] called with empty n" << endl; - - string const name = (n.empty() ? defaultLayoutName() : n); - + Assert(!name.empty()); + LayoutList::const_iterator cit = - find_if(layoutlist.begin(), - layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)); + find_if(layoutlist_.begin(), + layoutlist_.end(), + compare_name(name)); - if (cit == layoutlist.end()) { + 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 - lyx::Assert(false); + Assert(false); } - return *cit; + return (*cit); } -LyXLayout & LyXTextClass::operator[](string const & n) -{ - if (n.empty()) - lyxerr << "Operator[] called with empty n" << endl; - - string const name = (n.empty() ? defaultLayoutName() : n); - - LayoutList::iterator it = - find_if(layoutlist.begin(), - layoutlist.end(), - lyx::compare_memfun(&LyXLayout::name, name)); - - if (it == layoutlist.end()) { - lyxerr << "We failed to find the layout '" << name - << "' in the layout list. You MUST investigate!" - << endl; - - // we require the name to exist - lyx::Assert(false); - } - - 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(), + compare_name(name)); + + LayoutList::iterator end = layoutlist_.end(); bool const ret = (it != end); - layoutlist.erase(it, end); + layoutlist_.erase(it, end); return ret; } @@ -587,24 +819,35 @@ bool LyXTextClass::load() const } loaded = true; return loaded; - } -string const LyXTextClass::defaultLayoutName() const +FloatList & LyXTextClass::floats() { - // This really should come from the actual layout... (Lgb) - return defaultlayout_; + return *floatlist_.get(); } -LyXLayout const & LyXTextClass::defaultLayout() const +FloatList const & LyXTextClass::floats() const { - return operator[](defaultLayoutName()); + return *floatlist_.get(); +} + + +Counters & LyXTextClass::counters() const +{ + return *ctrs_.get(); +} + + +string const & LyXTextClass::defaultLayoutName() const +{ + // This really should come from the actual layout... (Lgb) + return defaultlayout_; } -LyXLayout & LyXTextClass::defaultLayout() +LyXLayout_ptr const & LyXTextClass::defaultLayout() const { return operator[](defaultLayoutName()); } @@ -687,7 +930,7 @@ bool LyXTextClass::provides(LyXTextClass::Provides p) const { return provides_ & p; } - + unsigned int LyXTextClass::columns() const { @@ -701,9 +944,24 @@ int LyXTextClass::maxcounter() const } +LYX_TITLE_LATEX_TYPES LyXTextClass::titletype() const +{ + return titletype_; +} + + +string const & LyXTextClass::titlename() const +{ + return titlename_; +} + + + + + int LyXTextClass::size() const { - return layoutlist.size(); + return layoutlist_.size(); } @@ -711,10 +969,10 @@ 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;