#include "Layout.h"
#include "Lexer.h"
#include "Font.h"
+#include "ModuleList.h"
#include "frontends/alert.h"
#include <fstream>
#include <sstream>
+#ifdef ERROR
+#undef ERROR
+#endif
+
using namespace std;
using namespace lyx::support;
docstring name_;
};
-
-int const FORMAT = 11;
+// Keep the changes documented in the Customization manual.
+int const FORMAT = 20;
bool layout2layout(FileName const & filename, FileName const & tempfile)
TextClass::TextClass()
{
outputType_ = LATEX;
+ outputFormat_ = "latex";
columns_ = 1;
sides_ = OneSide;
secnumdepth_ = 3;
enum TextClassTags {
TC_OUTPUTTYPE = 1,
+ TC_OUTPUTFORMAT,
TC_INPUT,
TC_STYLE,
+ TC_IFSTYLE,
TC_DEFAULTSTYLE,
TC_INSETLAYOUT,
TC_NOSTYLE,
TC_TOCDEPTH,
TC_CLASSOPTIONS,
TC_PREAMBLE,
+ TC_HTMLPREAMBLE,
TC_PROVIDES,
TC_REQUIRES,
TC_LEFTMARGIN,
TC_RIGHTMARGIN,
TC_FLOAT,
TC_COUNTER,
+ TC_IFCOUNTER,
TC_NOFLOAT,
TC_TITLELATEXNAME,
TC_TITLELATEXTYPE,
TC_FORMAT,
TC_ADDTOPREAMBLE,
+ TC_ADDTOHTMLPREAMBLE,
TC_DEFAULTMODULE,
TC_PROVIDESMODULE,
TC_EXCLUDESMODULE
namespace {
LexerKeyword textClassTags[] = {
- { "addtopreamble", TC_ADDTOPREAMBLE },
- { "classoptions", TC_CLASSOPTIONS },
- { "columns", TC_COLUMNS },
- { "counter", TC_COUNTER },
- { "defaultfont", TC_DEFAULTFONT },
- { "defaultmodule", TC_DEFAULTMODULE },
- { "defaultstyle", TC_DEFAULTSTYLE },
- { "excludesmodule", TC_EXCLUDESMODULE },
- { "float", TC_FLOAT },
- { "format", TC_FORMAT },
- { "input", TC_INPUT },
- { "insetlayout", TC_INSETLAYOUT },
- { "leftmargin", TC_LEFTMARGIN },
- { "nofloat", TC_NOFLOAT },
- { "nostyle", TC_NOSTYLE },
- { "outputtype", TC_OUTPUTTYPE },
- { "pagestyle", TC_PAGESTYLE },
- { "preamble", TC_PREAMBLE },
- { "provides", TC_PROVIDES },
- { "providesmodule", TC_PROVIDESMODULE },
- { "requires", TC_REQUIRES },
- { "rightmargin", TC_RIGHTMARGIN },
- { "secnumdepth", TC_SECNUMDEPTH },
- { "sides", TC_SIDES },
- { "style", TC_STYLE },
- { "titlelatexname", TC_TITLELATEXNAME },
- { "titlelatextype", TC_TITLELATEXTYPE },
- { "tocdepth", TC_TOCDEPTH }
+ { "addtohtmlpreamble", TC_ADDTOHTMLPREAMBLE },
+ { "addtopreamble", TC_ADDTOPREAMBLE },
+ { "classoptions", TC_CLASSOPTIONS },
+ { "columns", TC_COLUMNS },
+ { "counter", TC_COUNTER },
+ { "defaultfont", TC_DEFAULTFONT },
+ { "defaultmodule", TC_DEFAULTMODULE },
+ { "defaultstyle", TC_DEFAULTSTYLE },
+ { "excludesmodule", TC_EXCLUDESMODULE },
+ { "float", TC_FLOAT },
+ { "format", TC_FORMAT },
+ { "htmlpreamble", TC_HTMLPREAMBLE },
+ { "ifcounter", TC_IFCOUNTER },
+ { "ifstyle", TC_IFSTYLE },
+ { "input", TC_INPUT },
+ { "insetlayout", TC_INSETLAYOUT },
+ { "leftmargin", TC_LEFTMARGIN },
+ { "nofloat", TC_NOFLOAT },
+ { "nostyle", TC_NOSTYLE },
+ { "outputformat", TC_OUTPUTFORMAT },
+ { "outputtype", TC_OUTPUTTYPE },
+ { "pagestyle", TC_PAGESTYLE },
+ { "preamble", TC_PREAMBLE },
+ { "provides", TC_PROVIDES },
+ { "providesmodule", TC_PROVIDESMODULE },
+ { "requires", TC_REQUIRES },
+ { "rightmargin", TC_RIGHTMARGIN },
+ { "secnumdepth", TC_SECNUMDEPTH },
+ { "sides", TC_SIDES },
+ { "style", TC_STYLE },
+ { "titlelatexname", TC_TITLELATEXNAME },
+ { "titlelatextype", TC_TITLELATEXTYPE },
+ { "tocdepth", TC_TOCDEPTH }
};
} //namespace anon
FileName const tempfile = FileName::tempName("convert_layout");
bool success = layout2layout(filename, tempfile);
if (success)
- success = read(tempfile, rt);
+ success = readWithoutConv(tempfile, rt) == OK;
tempfile.removeFile();
return success;
}
-bool TextClass::read(FileName const & filename, ReadType rt)
+
+TextClass::ReturnValues TextClass::readWithoutConv(FileName const & filename, ReadType rt)
{
if (!filename.isReadableFile()) {
lyxerr << "Cannot read layout file `" << filename << "'."
<< endl;
- return false;
+ return ERROR;
}
LYXERR(Debug::TCLASS, "Reading " + translateRT(rt) + ": " +
LYXERR(Debug::TCLASS, "Finished reading " + translateRT(rt) + ": " +
to_utf8(makeDisplayPath(filename.absFilename())));
-
- if (retval != FORMAT_MISMATCH)
+
+ return retval;
+}
+
+
+bool TextClass::read(FileName const & filename, ReadType rt)
+{
+ ReturnValues const retval = readWithoutConv(filename, rt);
+ if (retval != FORMAT_MISMATCH)
return retval == OK;
-
+
bool const worx = convertLayoutFormat(filename, rt);
if (!worx) {
LYXERR0 ("Unable to convert " << filename <<
break;
}
+ // used below to track whether we are in an IfStyle or IfCounter tag.
+ bool ifstyle = false;
+ bool ifcounter = false;
+
switch (static_cast<TextClassTags>(le)) {
case TC_FORMAT:
format = lexrc.getInteger();
break;
- case TC_OUTPUTTYPE: // output type definition
+ case TC_OUTPUTFORMAT:
+ if (lexrc.next())
+ outputFormat_ = lexrc.getString();
+ break;
+
+ case TC_OUTPUTTYPE:
readOutputType(lexrc);
+ switch(outputType_) {
+ case LATEX:
+ outputFormat_ = "latex";
+ break;
+ case DOCBOOK:
+ outputFormat_ = "docbook";
+ break;
+ case LITERATE:
+ outputFormat_ = "literate";
+ break;
+ }
break;
case TC_INPUT: // Include file
}
break;
+ case TC_IFSTYLE:
+ ifstyle = true;
+ // fall through
case TC_STYLE: {
if (!lexrc.next()) {
lexrc.printError("No name given for style: `$$Token'.");
} else if (hasLayout(name)) {
Layout & lay = operator[](name);
error = !readStyle(lexrc, lay);
- } else {
+ } else if (!ifstyle) {
Layout layout;
layout.setName(name);
error = !readStyle(lexrc, layout);
defaultlayout_ = name;
}
}
+ else {
+ // scan the rest and discard it
+ Layout lay;
+ readStyle(lexrc, lay);
+ error = false;
+ }
+
+ // reset flag
+ ifstyle = false;
break;
}
preamble_ = from_utf8(lexrc.getLongString("EndPreamble"));
break;
+ case TC_HTMLPREAMBLE:
+ htmlpreamble_ = from_utf8(lexrc.getLongString("EndPreamble"));
+ break;
+
case TC_ADDTOPREAMBLE:
preamble_ += from_utf8(lexrc.getLongString("EndPreamble"));
break;
+ case TC_ADDTOHTMLPREAMBLE:
+ htmlpreamble_ += from_utf8(lexrc.getLongString("EndPreamble"));
+ break;
+
case TC_PROVIDES: {
lexrc.next();
string const feature = lexrc.getString();
rightmargin_ = lexrc.getDocString();
break;
- case TC_INSETLAYOUT:
- if (lexrc.next()) {
+ case TC_INSETLAYOUT: {
+ if (!lexrc.next()) {
+ lexrc.printError("No name given for InsetLayout: `$$Token'.");
+ error = true;
+ break;
+ }
+ docstring const name = subst(lexrc.getDocString(), '_', ' ');
+ if (name.empty()) {
+ string s = "Could not read name for InsetLayout: `$$Token' "
+ + lexrc.getString() + " is probably not valid UTF-8!";
+ lexrc.printError(s.c_str());
InsetLayout il;
- if (il.read(lexrc, *this))
- insetlayoutlist_[il.name()] = il;
- // else there was an error, so forget it
+ // Since we couldn't read the name, we just scan the rest
+ // of the style and discard it.
+ il.read(lexrc, *this);
+ error = true;
+ } else if (hasInsetLayout(name)) {
+ InsetLayout & il = insetlayoutlist_[name];
+ error = !il.read(lexrc, *this);
+ } else {
+ InsetLayout il;
+ il.setName(name);
+ error = !il.read(lexrc, *this);
+ if (!error)
+ insetlayoutlist_[name] = il;
}
break;
+ }
case TC_FLOAT:
readFloat(lexrc);
break;
+ case TC_IFCOUNTER:
+ ifcounter = true;
case TC_COUNTER:
if (lexrc.next()) {
docstring const name = lexrc.getDocString();
// and discard it.
c.read(lexrc);
} else
- error = !counters_.read(lexrc, name);
+ error = !counters_.read(lexrc, name, !ifcounter);
}
else {
lexrc.printError("No name given for style: `$$Token'.");
error = true;
}
+ // reset flag
+ ifcounter = false;
break;
case TC_TITLELATEXTYPE:
FT_STYLE,
FT_LISTNAME,
FT_BUILTIN,
+ FT_HTMLSTYLE,
+ FT_HTMLCLASS,
+ FT_HTMLTAG,
FT_END
};
{ "end", FT_END },
{ "extension", FT_EXT },
{ "guiname", FT_NAME },
+ { "htmlclass", FT_HTMLCLASS },
+ { "htmlstyle", FT_HTMLSTYLE },
+ { "htmltag", FT_HTMLTAG },
{ "latexbuiltin", FT_BUILTIN },
{ "listname", FT_LISTNAME },
{ "numberwithin", FT_WITHIN },
lexrc.pushTable(floatTags);
- string type;
- string placement;
string ext;
- string within;
- string style;
- string name;
+ string htmlclass;
+ string htmlstyle;
+ string htmltag;
string listName;
+ string name;
+ string placement;
+ string style;
+ string type;
+ string within;
bool builtin = false;
bool getout = false;
lexrc.next();
builtin = lexrc.getBool();
break;
+ case FT_HTMLCLASS:
+ lexrc.next();
+ htmlclass = lexrc.getString();
+ break;
+ case FT_HTMLSTYLE:
+ lexrc.next();
+ htmlstyle = lexrc.getLongString("EndHTMLStyle");
+ break;
+ case FT_HTMLTAG:
+ lexrc.next();
+ htmltag = lexrc.getString();
+ break;
case FT_END:
getout = true;
break;
// Here if have a full float if getout == true
if (getout) {
- Floating fl(type, placement, ext, within,
- style, name, listName, builtin);
+ Floating fl(type, placement, ext, within, style, name,
+ listName, htmltag, htmlclass, htmlstyle, builtin);
floatlist_.newFloat(fl);
// each float has its own counter
counters_.newCounter(from_ascii(type), from_ascii(within),
}
+bool TextClass::hasInsetLayout(docstring const & n) const
+{
+ if (n.empty())
+ return false;
+ InsetLayouts::const_iterator it = insetlayoutlist_.begin();
+ InsetLayouts::const_iterator en = insetlayoutlist_.end();
+ for (; it != en; ++it)
+ if (n == it->first)
+ return true;
+ return false;
+}
+
+
Layout const & TextClass::operator[](docstring const & name) const
{
LASSERT(!name.empty(), /**/);
}
+DocumentClass & DocumentClassBundle::makeDocumentClass(
+ LayoutFile const & baseClass, LayoutModuleList const & modlist)
+{
+ DocumentClass & doc_class = newClass(baseClass);
+ LayoutModuleList::const_iterator it = modlist.begin();
+ LayoutModuleList::const_iterator en = modlist.end();
+ for (; it != en; it++) {
+ string const modName = *it;
+ LyXModule * lm = theModuleList[modName];
+ if (!lm) {
+ docstring const msg =
+ bformat(_("The module %1$s has been requested by\n"
+ "this document but has not been found in the list of\n"
+ "available modules. If you recently installed it, you\n"
+ "probably need to reconfigure LyX.\n"), from_utf8(modName));
+ ExceptionMessage(WarningException,_("Module not available"),
+ msg + _("Some layouts may not be available."));
+ continue;
+ }
+ if (!lm->isAvailable()) {
+ docstring const msg =
+ bformat(_("The module %1$s requires a package that is\n"
+ "not available in your LaTeX installation. LaTeX output\n"
+ "may not be possible.\n"), from_utf8(modName));
+ ExceptionMessage(WarningException, _("Package not available"), msg);
+ }
+ FileName layout_file = libFileSearch("layouts", lm->getFilename());
+ if (!doc_class.read(layout_file, TextClass::MODULE)) {
+ docstring const msg =
+ bformat(_("Error reading module %1$s\n"), from_utf8(modName));
+ throw ExceptionMessage(WarningException, _("Read Error"), msg);
+ }
+ }
+ return doc_class;
+}
+
+
/////////////////////////////////////////////////////////////////////////
//
// DocumentClass