]> git.lyx.org Git - lyx.git/blobdiff - src/Layout.cpp
Fix bug #10320.
[lyx.git] / src / Layout.cpp
index bd4c08bee42fa9884d9f08f0f6a472e22d5e59d7..d6a01c9f7cb12adbd94cef4ffa9352828d532a6f 100644 (file)
@@ -13,7 +13,6 @@
 #include <config.h>
 
 #include "Layout.h"
-#include "Encoding.h"
 #include "FontInfo.h"
 #include "Language.h"
 #include "Lexer.h"
@@ -24,7 +23,6 @@
 #include "support/lassert.h"
 #include "support/lstrings.h"
 #include "support/Messages.h"
-#include "support/regex.h"
 #include "support/textutils.h"
 
 
@@ -41,6 +39,7 @@ const int Layout::NOT_IN_TOC = -1000;
 enum LayoutTags {
        LT_ALIGN = 1,
        LT_ALIGNPOSSIBLE,
+       LT_ARGUMENT,
        LT_MARGIN,
        LT_BOTTOMSEP,
        LT_CATEGORY,
@@ -52,7 +51,9 @@ enum LayoutTags {
        LT_FONT,
        LT_FREE_SPACING,
        LT_PASS_THRU,
+       LT_PASS_THRU_CHARS,
        LT_PARBREAK_IS_NEWLINE,
+       LT_ITEMCOMMAND,
        LT_ITEMSEP,
        LT_KEEPEMPTY,
        LT_LABEL_BOTTOMSEP,
@@ -68,12 +69,13 @@ enum LayoutTags {
        LT_ENDLABELTYPE,
        LT_LATEXNAME,
        LT_LATEXPARAM,
-       LT_OPTARGS,
        LT_LATEXTYPE,
+       LT_LEFTDELIM,
        LT_LEFTMARGIN,
        LT_NEED_PROTECT,
        LT_NEWLINE,
        LT_NEXTNOINDENT,
+       LT_PAR_GROUP,
        LT_PARINDENT,
        LT_PARSEP,
        LT_PARSKIP,
@@ -102,13 +104,19 @@ enum LayoutTags {
        LT_HTMLTITLE,
        LT_SPELLCHECK,
        LT_REFPREFIX,
-       LT_REQARGS,
+       LT_RESETARGS,
+       LT_RIGHTDELIM,
+       LT_FORCELOCAL,
+       LT_TOGGLE_INDENT,
+       LT_ADDTOTOC,
+       LT_ISTOCCAPTION,
        LT_INTITLE // keep this last!
 };
 
 /////////////////////
 
 Layout::Layout()
+       : add_to_toc_(false), is_toc_caption_(false)
 {
        unknown_ = false;
        margintype = MARGIN_STATIC;
@@ -144,17 +152,41 @@ Layout::Layout()
        htmlforcecss_ = false;
        htmltitle_ = false;
        spellcheck = true;
-       optargs = 0;
-       reqargs = 0;
+       forcelocal = 0;
+       itemcommand_ = "item";
+       toggle_indent = ITOGGLE_DOCUMENT_DEFAULT;
+       par_group_ = false;
 }
 
 
 bool Layout::read(Lexer & lex, TextClass const & tclass)
+{
+       // If this is an empty layout, or if no force local version is set,
+       // we know that we will not discard the stuff to read
+       if (forcelocal == 0)
+               return readIgnoreForcelocal(lex, tclass);
+       Layout tmp(*this);
+       tmp.forcelocal = 0;
+       bool const ret = tmp.readIgnoreForcelocal(lex, tclass);
+       // Keep the stuff if
+       // - the read version is higher
+       // - both versions are infinity (arbitrary decision)
+       // - the file did not contain any local version (needed for not
+       //   skipping user defined local layouts)
+       if (tmp.forcelocal <= 0 || tmp.forcelocal > forcelocal)
+               *this = tmp;
+       return ret;
+}
+
+
+bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass)
 {
        // This table is sorted alphabetically [asierra 30March96]
        LexerKeyword layoutTags[] = {
+               { "addtotoc",       LT_ADDTOTOC },
                { "align",          LT_ALIGN },
                { "alignpossible",  LT_ALIGNPOSSIBLE },
+               { "argument",       LT_ARGUMENT },
                { "babelpreamble",  LT_BABELPREAMBLE },
                { "bottomsep",      LT_BOTTOMSEP },
                { "category",       LT_CATEGORY },
@@ -165,6 +197,7 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                { "endlabelstring", LT_ENDLABELSTRING },
                { "endlabeltype",   LT_ENDLABELTYPE },
                { "font",           LT_FONT },
+               { "forcelocal",     LT_FORCELOCAL },
                { "freespacing",    LT_FREE_SPACING },
                { "htmlattr",       LT_HTMLATTR },
                { "htmlforcecss",   LT_HTMLFORCECSS },
@@ -180,6 +213,8 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                { "innertag",       LT_INNERTAG },
                { "inpreamble",     LT_INPREAMBLE },
                { "intitle",        LT_INTITLE },
+               { "istoccaption",   LT_ISTOCCAPTION },
+               { "itemcommand",    LT_ITEMCOMMAND },
                { "itemsep",        LT_ITEMSEP },
                { "itemtag",        LT_ITEMTAG },
                { "keepempty",      LT_KEEPEMPTY },
@@ -196,27 +231,31 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                { "latexname",      LT_LATEXNAME },
                { "latexparam",     LT_LATEXPARAM },
                { "latextype",      LT_LATEXTYPE },
+               { "leftdelim",      LT_LEFTDELIM },
                { "leftmargin",     LT_LEFTMARGIN },
                { "margin",         LT_MARGIN },
                { "needprotect",    LT_NEED_PROTECT },
                { "newline",        LT_NEWLINE },
                { "nextnoindent",   LT_NEXTNOINDENT },
                { "obsoletedby",    LT_OBSOLETEDBY },
-               { "optionalargs",   LT_OPTARGS },
+               { "paragraphgroup", LT_PAR_GROUP },
                { "parbreakisnewline", LT_PARBREAK_IS_NEWLINE },
                { "parindent",      LT_PARINDENT },
                { "parsep",         LT_PARSEP },
                { "parskip",        LT_PARSKIP },
                { "passthru",       LT_PASS_THRU },
+               { "passthruchars",  LT_PASS_THRU_CHARS },
                { "preamble",       LT_PREAMBLE },
                { "refprefix",      LT_REFPREFIX },
-               { "requiredargs",   LT_REQARGS },
                { "requires",       LT_REQUIRES },
+               { "resetargs",      LT_RESETARGS },
+               { "rightdelim",     LT_RIGHTDELIM },
                { "rightmargin",    LT_RIGHTMARGIN },
                { "spacing",        LT_SPACING },
                { "spellcheck",     LT_SPELLCHECK },
                { "textfont",       LT_TEXTFONT },
                { "toclevel",       LT_TOCLEVEL },
+               { "toggleindent",   LT_TOGGLE_INDENT },
                { "topsep",         LT_TOPSEP }
        };
 
@@ -318,12 +357,18 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        lex >> toclevel;
                        break;
 
-               case LT_OPTARGS:
-                       lex >> optargs;
+               case LT_RESETARGS:
+                       bool reset;
+                       lex >> reset;
+                       if (reset) {
+                               latexargs_.clear();
+                               itemargs_.clear();
+                               postcommandargs_.clear();
+                       }
                        break;
 
-               case LT_REQARGS:
-                       lex >> reqargs;
+               case LT_ARGUMENT:
+                       readArgument(lex);
                        break;
 
                case LT_NEED_PROTECT:
@@ -351,6 +396,19 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        lex >> nextnoindent;
                        break;
 
+               case LT_TOGGLE_INDENT: {
+                       string tog;
+                       lex >> tog;
+                       tog = support::ascii_lowercase(tog);
+                       if (tog == "always")
+                               toggle_indent = ITOGGLE_ALWAYS;
+                       else if (tog == "never")
+                               toggle_indent = ITOGGLE_NEVER;
+                       else
+                               toggle_indent = ITOGGLE_DOCUMENT_DEFAULT;
+                       break;
+               }
+
                case LT_COMMANDDEPTH:
                        lex >> commanddepth;
                        break;
@@ -364,6 +422,18 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        latexparam_ = subst(latexparam_, "&quot;", "\"");
                        break;
 
+               case LT_LEFTDELIM:
+                       lex >> leftdelim_;
+                       leftdelim_ = support::subst(leftdelim_, from_ascii("<br/>"),
+                                                   from_ascii("\n"));
+                       break;
+
+               case LT_RIGHTDELIM:
+                       lex >> rightdelim_;
+                       rightdelim_ = support::subst(rightdelim_, from_ascii("<br/>"),
+                                                    from_ascii("\n"));
+                       break;
+
                case LT_INNERTAG:
                        lex >> innertag_;
                        break;
@@ -376,6 +446,10 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        lex >> itemtag_;
                        break;
 
+               case LT_ITEMCOMMAND:
+                       lex >> itemcommand_;
+                       break;
+
                case LT_PREAMBLE:
                        preamble_ = from_utf8(lex.getLongString("EndPreamble"));
                        break;
@@ -454,7 +528,7 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        break;
 
                case LT_LABELSTRING:
-                       // FIXME: this means LT_ENDLABELSTRING may only
+                       // FIXME: this means LT_LABELSTRING_APPENDIX may only
                        // occur after LT_LABELSTRING
                        lex >> labelstring_;
                        labelstring_ = trim(labelstring_);
@@ -476,6 +550,10 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        counter = trim(counter);
                        break;
 
+               case LT_PAR_GROUP:
+                       lex >> par_group_;
+                       break;
+
                case LT_FREE_SPACING:
                        lex >> free_spacing;
                        break;
@@ -484,6 +562,10 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                        lex >> pass_thru;
                        break;
 
+               case LT_PASS_THRU_CHARS:
+                       lex >> pass_thru_chars;
+                       break;
+
                case LT_PARBREAK_IS_NEWLINE:
                        lex >> parbreak_is_newline;
                        break;
@@ -494,8 +576,8 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
 
                case LT_REQUIRES: {
                        lex.eatLine();
-                       vector<string> const req = 
-                               getVectorFromString(lex.getString());
+                       vector<string> const req =
+                               getVectorFromString(lex.getString(true));
                        requires_.insert(req.begin(), req.end());
                        break;
                }
@@ -557,6 +639,20 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
                case LT_SPELLCHECK:
                        lex >> spellcheck;
                        break;
+
+               case LT_FORCELOCAL:
+                       lex >> forcelocal;
+                       break;
+
+               case LT_ADDTOTOC:
+                       lex >> toc_type_;
+                       add_to_toc_ = !toc_type_.empty();
+                       break;
+
+               case LT_ISTOCCAPTION:
+                       lex >> is_toc_caption_;
+                       break;
+
                }
        }
        lex.popTable();
@@ -659,11 +755,10 @@ void Layout::readLabelType(Lexer & lex)
        enum {
                LA_NO_LABEL = 1,
                LA_MANUAL,
-               LA_TOP_ENVIRONMENT,
-               LA_CENTERED_TOP_ENVIRONMENT,
+               LA_ABOVE,
+               LA_CENTERED,
                LA_STATIC,
                LA_SENSITIVE,
-               LA_COUNTER,
                LA_ENUMERATE,
                LA_ITEMIZE,
                LA_BIBLIO
@@ -671,16 +766,15 @@ void Layout::readLabelType(Lexer & lex)
 
 
        LexerKeyword labelTypeTags[] = {
-               { "bibliography",             LA_BIBLIO },
-               { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
-               { "counter",                  LA_COUNTER },
-               { "enumerate",                LA_ENUMERATE },
-               { "itemize",                  LA_ITEMIZE },
-               { "manual",                   LA_MANUAL },
-               { "no_label",                 LA_NO_LABEL },
-               { "sensitive",                LA_SENSITIVE },
-               { "static",                   LA_STATIC },
-               { "top_environment",          LA_TOP_ENVIRONMENT }
+         { "above",        LA_ABOVE },
+               { "bibliography", LA_BIBLIO },
+               { "centered",     LA_CENTERED },
+               { "enumerate",    LA_ENUMERATE },
+               { "itemize",      LA_ITEMIZE },
+               { "manual",       LA_MANUAL },
+               { "no_label",     LA_NO_LABEL },
+               { "sensitive",    LA_SENSITIVE },
+               { "static",       LA_STATIC }
        };
 
        PushPopHelper pph(lex, labelTypeTags);
@@ -698,11 +792,11 @@ void Layout::readLabelType(Lexer & lex)
        case LA_MANUAL:
                labeltype = LABEL_MANUAL;
                break;
-       case LA_TOP_ENVIRONMENT:
-               labeltype = LABEL_TOP_ENVIRONMENT;
+       case LA_ABOVE:
+               labeltype = LABEL_ABOVE;
                break;
-       case LA_CENTERED_TOP_ENVIRONMENT:
-               labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
+       case LA_CENTERED:
+               labeltype = LABEL_CENTERED;
                break;
        case LA_STATIC:
                labeltype = LABEL_STATIC;
@@ -710,9 +804,6 @@ void Layout::readLabelType(Lexer & lex)
        case LA_SENSITIVE:
                labeltype = LABEL_SENSITIVE;
                break;
-       case LA_COUNTER:
-               labeltype = LABEL_COUNTER;
-               break;
        case LA_ENUMERATE:
                labeltype = LABEL_ENUMERATE;
                break;
@@ -728,6 +819,8 @@ void Layout::readLabelType(Lexer & lex)
 
 void Layout::readEndLabelType(Lexer & lex)
 {
+       // this should be const, but can't be because
+       // of PushPopHelper.
        static LexerKeyword endlabelTypeTags[] = {
                { "box",              END_LABEL_BOX },
                { "filled_box", END_LABEL_FILLED_BOX },
@@ -804,12 +897,15 @@ void Layout::readLatexType(Lexer & lex)
                return;
        case LATEX_PARAGRAPH:
        case LATEX_COMMAND:
-       case LATEX_ENVIRONMENT:
        case LATEX_ITEM_ENVIRONMENT:
-       case LATEX_BIB_ENVIRONMENT:
        case LATEX_LIST_ENVIRONMENT:
                latextype = static_cast<LatexType>(le);
                break;
+       case LATEX_ENVIRONMENT:
+       case LATEX_BIB_ENVIRONMENT:
+               latextype = static_cast<LatexType>(le);
+               par_group_ = true;
+               break;
        default:
                LYXERR0("Unhandled value " << le);
                break;
@@ -859,69 +955,480 @@ void Layout::readSpacing(Lexer & lex)
 }
 
 
-namespace {
+void Layout::readArgument(Lexer & lex)
+{
+       latexarg arg;
+       // writeArgument() makes use of these default values
+       arg.mandatory = false;
+       arg.autoinsert = false;
+       arg.insertcotext = false;
+       bool error = false;
+       bool finished = false;
+       arg.font = inherit_font;
+       arg.labelfont = inherit_font;
+       arg.is_toc_caption = false;
+       string id;
+       lex >> id;
+       bool const itemarg = prefixIs(id, "item:");
+       bool const postcmd = prefixIs(id, "post:");
+
+       while (!finished && lex.isOK() && !error) {
+               lex.next();
+               string const tok = ascii_lowercase(lex.getString());
+
+               if (tok.empty()) {
+                       continue;
+               } else if (tok == "endargument") {
+                       finished = true;
+               } else if (tok == "labelstring") {
+                       lex.next();
+                       arg.labelstring = lex.getDocString();
+               } else if (tok == "menustring") {
+                       lex.next();
+                       arg.menustring = lex.getDocString();
+               } else if (tok == "mandatory") {
+                       lex.next();
+                       arg.mandatory = lex.getBool();
+               } else if (tok == "autoinsert") {
+                       lex.next();
+                       arg.autoinsert = lex.getBool();
+               } else if (tok == "insertcotext") {
+                       lex.next();
+                       arg.insertcotext = lex.getBool();
+               } else if (tok == "leftdelim") {
+                       lex.next();
+                       arg.ldelim = lex.getDocString();
+                       arg.ldelim = support::subst(arg.ldelim, from_ascii("<br/>"),
+                                                   from_ascii("\n"));
+               } else if (tok == "rightdelim") {
+                       lex.next();
+                       arg.rdelim = lex.getDocString();
+                       arg.rdelim = support::subst(arg.rdelim, from_ascii("<br/>"),
+                                                   from_ascii("\n"));
+               } else if (tok == "defaultarg") {
+                       lex.next();
+                       arg.defaultarg = lex.getDocString();
+               } else if (tok == "presetarg") {
+                       lex.next();
+                       arg.presetarg = lex.getDocString();
+               } else if (tok == "tooltip") {
+                       lex.next();
+                       arg.tooltip = lex.getDocString();
+               } else if (tok == "requires") {
+                       lex.next();
+                       arg.requires = lex.getString();
+               } else if (tok == "decoration") {
+                       lex.next();
+                       arg.decoration = lex.getString();
+               } else if (tok == "font") {
+                       arg.font = lyxRead(lex, arg.font);
+               } else if (tok == "labelfont") {
+                       arg.labelfont = lyxRead(lex, arg.labelfont);
+               } else if (tok == "passthruchars") {
+                       lex.next();
+                       arg.pass_thru_chars = lex.getDocString();
+               } else if (tok == "istoccaption") {
+                       lex.next();
+                       arg.is_toc_caption = lex.getBool();
+               } else {
+                       lex.printError("Unknown tag");
+                       error = true;
+               }
+       }
+       if (arg.labelstring.empty())
+               LYXERR0("Incomplete Argument definition!");
+       else if (itemarg)
+               itemargs_[id] = arg;
+       else if (postcmd)
+               postcommandargs_[id] = arg;
+       else
+               latexargs_[id] = arg;
+}
 
-docstring const i18npreamble(Language const * lang, Encoding const & enc,
-                            docstring const & templ, bool const polyglossia)
+
+void writeArgument(ostream & os, string const & id, Layout::latexarg const & arg)
 {
-       if (templ.empty())
-               return templ;
-
-       string preamble = polyglossia ?
-               subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
-               subst(to_utf8(templ), "$$lang", lang->babel());
-
-#ifdef TEX2LYX
-       // tex2lyx does not have getMessages()
-       LASSERT(false, /**/);
-       (void)enc;
-#else
-       string const langenc = lang->encoding()->iconvName();
-       string const texenc = lang->encoding()->latexName();
-       string const bufenc = enc.iconvName();
-       // First and second character of plane 15 (Private Use Area)
-       string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
-       string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
-       // FIXME UNICODE
-       // lyx::regex is not unicode-safe.
-       // Should use QRegExp or (boost::u32regex, but that requires ICU)
-       static regex const reg("_\\(([^\\)]+)\\)");
-       smatch sub;
-       while (regex_search(preamble, sub, reg)) {
-               string const key = sub.str(1);
-               docstring const name = lang->translateLayout(key);
-               // Check whether name can be encoded in the buffer encoding
-               bool encodable = true;
-               for (size_t i = 0; i < name.size(); ++i) {
-                       if (!enc.encodable(name[i])) {
-                               encodable = false;
-                               break;
-                       }
+       os << "\tArgument " << id << '\n';
+       if (!arg.labelstring.empty())
+               os << "\t\tLabelString \"" << to_utf8(arg.labelstring) << "\"\n";
+       if (!arg.menustring.empty())
+               os << "\t\tMenuString \"" << to_utf8(arg.menustring) << "\"\n";
+       if (arg.mandatory)
+               os << "\t\tMandatory " << arg.mandatory << '\n';
+       if (arg.autoinsert)
+               os << "\t\tAutoinsert " << arg.autoinsert << '\n';
+       if (arg.insertcotext)
+               os << "\t\tInsertCotext " << arg.insertcotext << '\n';
+       if (!arg.ldelim.empty())
+               os << "\t\tLeftDelim \""
+                  << to_utf8(subst(arg.ldelim, from_ascii("\n"), from_ascii("<br/>")))
+                  << "\"\n";
+       if (!arg.rdelim.empty())
+               os << "\t\tRightDelim \""
+                  << to_utf8(subst(arg.rdelim, from_ascii("\n"), from_ascii("<br/>")))
+                  << "\"\n";
+       if (!arg.defaultarg.empty())
+               os << "\t\tDefaultArg \"" << to_utf8(arg.defaultarg) << "\"\n";
+       if (!arg.presetarg.empty())
+               os << "\t\tPresetArg \"" << to_utf8(arg.presetarg) << "\"\n";
+       if (!arg.tooltip.empty())
+               os << "\t\tToolTip \"" << to_utf8(arg.tooltip) << "\"\n";
+       if (!arg.requires.empty())
+               os << "\t\tRequires \"" << arg.requires << "\"\n";
+       if (!arg.decoration.empty())
+               os << "\t\tDecoration \"" << arg.decoration << "\"\n";
+       if (arg.font != inherit_font)
+               lyxWrite(os, arg.font, "Font", 2);
+       if (arg.labelfont != inherit_font)
+               lyxWrite(os, arg.labelfont, "LabelFont", 2);
+       if (!arg.pass_thru_chars.empty())
+               os << "\t\tPassThruChars \"" << to_utf8(arg.pass_thru_chars) << "\"\n";
+       os << "\tEndArgument\n";
+}
+
+
+void Layout::write(ostream & os) const
+{
+       os << "Style \"" << to_utf8(name_) << "\"\n";
+       if (!category_.empty() && obsoleted_by_.empty())
+               os << "\tCategory \"" << to_utf8(category_) << "\"\n";
+       // Can't deduce Copystyle here :-(
+       if (!obsoleted_by_.empty()) {
+               os << "\tObsoletedBy \"" << to_utf8(obsoleted_by_)
+                  << "\"\nEnd\n";
+               return;
+       }
+       if (!depends_on_.empty())
+               os << "\tDependsOn " << to_utf8(depends_on_) << '\n';
+       switch (margintype) {
+               case MARGIN_DYNAMIC:
+                       os << "\tMargin Dynamic\n";
+                       break;
+               case MARGIN_FIRST_DYNAMIC:
+                       os << "\tMargin First_Dynamic\n";
+                       break;
+               case MARGIN_MANUAL:
+                       os << "\tMargin Manual\n";
+                       break;
+               case MARGIN_RIGHT_ADDRESS_BOX:
+                       os << "\tMargin Right_Address_Box\n";
+                       break;
+               case MARGIN_STATIC:
+                       os << "\tMargin Static\n";
+                       break;
+       }
+       switch (latextype) {
+               case LATEX_BIB_ENVIRONMENT:
+                       os << "\tLatexType Bib_Environment\n";
+                       break;
+               case LATEX_COMMAND:
+                       os << "\tLatexType Command\n";
+                       break;
+               case LATEX_ENVIRONMENT:
+                       os << "\tLatexType Environment\n";
+                       break;
+               case LATEX_ITEM_ENVIRONMENT:
+                       os << "\tLatexType Item_Environment\n";
+                       break;
+               case LATEX_LIST_ENVIRONMENT:
+                       os << "\tLatexType List_Environment\n";
+                       break;
+               case LATEX_PARAGRAPH:
+                       os << "\tLatexType Paragraph\n";
+                       break;
+       }
+       os << "\tInTitle " << intitle << "\n"
+             "\tInPreamble " << inpreamble << "\n"
+             "\tTocLevel " << toclevel << '\n';
+       // ResetArgs does not make sense here
+       for (LaTeXArgMap::const_iterator it = latexargs_.begin();
+            it != latexargs_.end(); ++it)
+               writeArgument(os, it->first, it->second);
+       for (LaTeXArgMap::const_iterator it = itemargs_.begin();
+            it != itemargs_.end(); ++it)
+               writeArgument(os, it->first, it->second);
+       for (LaTeXArgMap::const_iterator it = postcommandargs_.begin();
+            it != postcommandargs_.end(); ++it)
+               writeArgument(os, it->first, it->second);
+       os << "\tNeedProtect " << needprotect << "\n"
+             "\tKeepEmpty " << keepempty << '\n';
+       if (labelfont == font)
+               lyxWrite(os, font, "Font", 1);
+       else {
+               lyxWrite(os, font, "TextFont", 1);
+               lyxWrite(os, labelfont, "LabelFont", 1);
+       }
+       os << "\tNextNoIndent " << nextnoindent << "\n"
+             "\tCommandDepth " << commanddepth << '\n';
+       if (!latexname_.empty())
+               os << "\tLatexName \"" << latexname_ << "\"\n";
+       if (!latexparam_.empty())
+               os << "\tLatexParam \"" << subst(latexparam_, "\"", "&quot;")
+                  << "\"\n";
+       if (!leftdelim_.empty())
+               os << "\tLeftDelim "
+                  << to_utf8(subst(leftdelim_, from_ascii("\n"), from_ascii("<br/>")))
+                  << '\n';
+       if (!rightdelim_.empty())
+               os << "\tRightDelim "
+                  << to_utf8(subst(rightdelim_, from_ascii("\n"), from_ascii("<br/>")))
+                  << '\n';
+       if (!innertag_.empty())
+               os << "\tInnerTag \"" << innertag_ << "\"\n";
+       if (!labeltag_.empty())
+               os << "\tLabelTag \"" << labeltag_ << "\"\n";
+       if (!itemtag_.empty())
+               os << "\tItemTag \"" << itemtag_ << "\"\n";
+       if (!itemcommand_.empty())
+               os << "\tItemCommand " << itemcommand_ << '\n';
+       if (!preamble_.empty())
+               os << "\tPreamble\n\t"
+                  << to_utf8(subst(rtrim(preamble_, "\n"),
+                                   from_ascii("\n"), from_ascii("\n\t")))
+                  << "\n\tEndPreamble\n";
+       if (!langpreamble_.empty())
+               os << "\tLangPreamble\n\t"
+                  << to_utf8(subst(rtrim(langpreamble_, "\n"),
+                                   from_ascii("\n"), from_ascii("\n\t")))
+                  << "\n\tEndLangPreamble\n";
+       if (!babelpreamble_.empty())
+               os << "\tBabelPreamble\n\t"
+                  << to_utf8(subst(rtrim(babelpreamble_, "\n"),
+                                   from_ascii("\n"), from_ascii("\n\t")))
+                  << "\n\tEndBabelPreamble\n";
+       switch (labeltype) {
+       case LABEL_ABOVE:
+               os << "\tLabelType Above\n";
+               break;
+       case LABEL_BIBLIO:
+               os << "\tLabelType Bibliography\n";
+               break;
+       case LABEL_CENTERED:
+               os << "\tLabelType Centered\n";
+               break;
+       case LABEL_ENUMERATE:
+               os << "\tLabelType Enumerate\n";
+               break;
+       case LABEL_ITEMIZE:
+               os << "\tLabelType Itemize\n";
+               break;
+       case LABEL_MANUAL:
+               os << "\tLabelType Manual\n";
+               break;
+       case LABEL_NO_LABEL:
+               os << "\tLabelType No_Label\n";
+               break;
+       case LABEL_SENSITIVE:
+               os << "\tLabelType Sensitive\n";
+               break;
+       case LABEL_STATIC:
+               os << "\tLabelType Static\n";
+               break;
+       }
+       switch (endlabeltype) {
+       case END_LABEL_BOX:
+               os << "\tEndLabelType Box\n";
+               break;
+       case END_LABEL_FILLED_BOX:
+               os << "\tEndLabelType Filled_Box\n";
+               break;
+       case END_LABEL_NO_LABEL:
+               os << "\tEndLabelType No_Label\n";
+               break;
+       case END_LABEL_STATIC:
+               os << "\tEndLabelType Static\n";
+               break;
+       }
+       os << "\tParagraphGroup \"" << par_group_ << "\"\n";
+       if (!leftmargin.empty())
+               os << "\tLeftMargin \"" << to_utf8(leftmargin) << "\"\n";
+       if (!rightmargin.empty())
+               os << "\tRightMargin \"" << to_utf8(rightmargin) << "\"\n";
+       if (!labelindent.empty())
+               os << "\tLabelIndent " << to_utf8(labelindent) << '\n';
+       if (!parindent.empty())
+               os << "\tParIndent " << to_utf8(parindent) << '\n';
+       os << "\tParSkip " << parskip << "\n"
+             "\tItemSep " << itemsep << "\n"
+             "\tTopSep " << topsep << "\n"
+             "\tBottomSep " << bottomsep << "\n"
+             "\tLabelBottomSep " << labelbottomsep << '\n';
+       if (!labelsep.empty())
+               os << "\tLabelSep " << to_utf8(subst(labelsep, ' ', 'x'))
+                  << '\n';
+       os << "\tParSep " << parsep << "\n"
+             "\tNewLine " << newline_allowed << '\n';
+       switch (align) {
+       case LYX_ALIGN_BLOCK:
+               os << "\tAlign Block\n";
+               break;
+       case LYX_ALIGN_CENTER:
+               os << "\tAlign Center\n";
+               break;
+       case LYX_ALIGN_LAYOUT:
+               os << "\tAlign Layout\n";
+               break;
+       case LYX_ALIGN_LEFT:
+               os << "\tAlign Left\n";
+               break;
+       case LYX_ALIGN_RIGHT:
+               os << "\tAlign Right\n";
+               break;
+       case LYX_ALIGN_DECIMAL:
+       case LYX_ALIGN_SPECIAL:
+       case LYX_ALIGN_NONE:
+               break;
+       }
+       if (alignpossible & (LYX_ALIGN_BLOCK | LYX_ALIGN_CENTER |
+                            LYX_ALIGN_LAYOUT | LYX_ALIGN_LEFT | LYX_ALIGN_RIGHT)) {
+               bool first = true;
+               os << "\tAlignPossible";
+               if (alignpossible & LYX_ALIGN_BLOCK) {
+                       os << " Block";
+                       first = false;
+               }
+               if (alignpossible & LYX_ALIGN_CENTER) {
+                       if (!first)
+                               os << ',';
+                       os << " Center";
+                       first = false;
+               }
+               if (alignpossible & LYX_ALIGN_LAYOUT) {
+                       if (!first)
+                               os << ',';
+                       os << " Layout";
+                       first = false;
                }
-               string const translated = encodable ? to_utf8(name)
-                       : "\\inputencoding{" + texenc + "}"
-                               + s1 + langenc + s2 + to_utf8(name)
-                               + s1 + bufenc + s2;
-               preamble = subst(preamble, sub.str(), translated);
+               if (alignpossible & LYX_ALIGN_LEFT) {
+                       if (!first)
+                               os << ',';
+                       os << " Left";
+                       first = false;
+               }
+               if (alignpossible & LYX_ALIGN_RIGHT) {
+                       if (!first)
+                               os << ',';
+                       os << " Right";
+                       first = false;
+               }
+               os << '\n';
        }
-#endif
-       return from_utf8(preamble);
+       // LabelString must come before LabelStringAppendix
+       if (!labelstring_.empty())
+               os << "\tLabelString \"" << to_utf8(labelstring_) << "\"\n";
+       if (!endlabelstring_.empty())
+               os << "\tEndLabelString \"" << to_utf8(endlabelstring_) << "\"\n";
+       if (!labelstring_appendix_.empty() && labelstring_appendix_ != labelstring_)
+               os << "\tLabelStringAppendix \""
+                  << to_utf8(labelstring_appendix_) << "\"\n";
+       if (!counter.empty())
+               os << "\tLabelCounter \"" << to_utf8(counter) << "\"\n";
+       os << "\tFreeSpacing " << free_spacing << '\n';
+       os << "\tPassThru " << pass_thru << '\n';
+       if (!pass_thru_chars.empty())
+               os << "\tPassThruChars " << to_utf8(pass_thru_chars) << '\n';
+       os << "\tParbreakIsNewline " << parbreak_is_newline << '\n';
+       switch (spacing.getSpace()) {
+       case Spacing::Double:
+               os << "\tSpacing Double\n";
+               break;
+       case Spacing::Onehalf:
+               os << "\tSpacing Onehalf\n";
+               break;
+       case Spacing::Other:
+               os << "\tSpacing Other " << spacing.getValueAsString() << '\n';
+               break;
+       case Spacing::Single:
+               os << "\tSpacing Single\n";
+               break;
+       case Spacing::Default:
+               break;
+       }
+       if (!requires_.empty()) {
+               os << "\tRequires ";
+               for (set<string>::const_iterator it = requires_.begin();
+                    it != requires_.end(); ++it) {
+                       if (it != requires_.begin())
+                               os << ',';
+                       os << *it;
+               }
+               os << '\n';
+       }
+       if (refprefix.empty())
+               os << "\tRefPrefix OFF\n";
+       else
+               os << "\tRefPrefix " << to_utf8(refprefix) << '\n';
+       if (!htmltag_.empty())
+               os << "\tHTMLTag " << htmltag_ << '\n';
+       if (!htmlattr_.empty())
+               os << "\tHTMLAttr " << htmlattr_ << '\n';
+       if (!htmlitemtag_.empty())
+               os << "\tHTMLItem " << htmlitemtag_ << '\n';
+       if (!htmlitemattr_.empty())
+               os << "\tHTMLItemAttr " << htmlitemattr_ << '\n';
+       if (!htmllabeltag_.empty())
+               os << "\tHTMLLabel " << htmllabeltag_ << '\n';
+       if (!htmllabelattr_.empty())
+               os << "\tHTMLLabelAttr " << htmllabelattr_ << '\n';
+       os << "\tHTMLLabelFirst " << htmllabelfirst_ << '\n';
+       if (!htmlstyle_.empty())
+               os << "\tHTMLStyle\n"
+                  << to_utf8(rtrim(htmlstyle_, "\n"))
+                  << "\n\tEndHTMLStyle\n";
+       os << "\tHTMLForceCSS " << htmlforcecss_ << '\n';
+       if (!htmlpreamble_.empty())
+               os << "\tHTMLPreamble\n"
+                  << to_utf8(rtrim(htmlpreamble_, "\n"))
+                  << "\n\tEndPreamble\n";
+       os << "\tHTMLTitle " << htmltitle_ << "\n"
+             "\tSpellcheck " << spellcheck << "\n"
+             "\tForceLocal " << forcelocal << "\n"
+             "End\n";
 }
 
+
+Layout::LaTeXArgMap Layout::args() const
+{
+       LaTeXArgMap args = latexargs_;
+       if (!postcommandargs_.empty())
+               args.insert(postcommandargs_.begin(), postcommandargs_.end());
+       if (!itemargs_.empty())
+               args.insert(itemargs_.begin(), itemargs_.end());
+       return args;
 }
 
 
-docstring const Layout::langpreamble(Language const * lang,
-                       Encoding const & enc, bool const polyglossia) const
+int Layout::optArgs() const
 {
-       return i18npreamble(lang, enc, langpreamble_, polyglossia);
+       int nr = 0;
+       LaTeXArgMap::const_iterator it = latexargs_.begin();
+       for (; it != latexargs_.end(); ++it) {
+               if (!(*it).second.mandatory)
+                       ++nr;
+       }
+       LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
+       for (; iit != postcommandargs_.end(); ++iit) {
+               if (!(*iit).second.mandatory)
+                       ++nr;
+       }
+       return nr;
 }
 
 
-docstring const Layout::babelpreamble(Language const * lang,
-                       Encoding const & enc, bool const polyglossia) const
+int Layout::requiredArgs() const
 {
-       return i18npreamble(lang, enc, babelpreamble_, polyglossia);
+       int nr = 0;
+       LaTeXArgMap::const_iterator it = latexargs_.begin();
+       for (; it != latexargs_.end(); ++it) {
+               if ((*it).second.mandatory)
+                       ++nr;
+       }
+       LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
+       for (; iit != postcommandargs_.end(); ++iit) {
+               if (!(*iit).second.mandatory)
+                       ++nr;
+       }
+       return nr;
 }
 
 
@@ -960,8 +1467,8 @@ string const & Layout::htmlitemattr() const
 string const & Layout::htmllabeltag() const 
 { 
        if (htmllabeltag_.empty()) {
-               if (labeltype != LABEL_TOP_ENVIRONMENT &&
-                   labeltype != LABEL_CENTERED_TOP_ENVIRONMENT)
+               if (labeltype != LABEL_ABOVE &&
+                   labeltype != LABEL_CENTERED)
                        htmllabeltag_ = "span";
                else
                        htmllabeltag_ = "div";
@@ -978,7 +1485,8 @@ string const & Layout::htmllabelattr() const
 }
 
 
-docstring Layout::htmlstyle() const {
+docstring Layout::htmlstyle() const
+{
        if (!htmlstyle_.empty() && !htmlforcecss_)
                return htmlstyle_;
        if (htmldefaultstyle_.empty()) 
@@ -1006,7 +1514,7 @@ string Layout::defaultCSSClass() const
                                d = from_ascii("lyx_");
                        else
                                d += '_';
-               } else if (islower(c))
+               } else if (isLower(c))
                        d += c;
                else
                        // this is slow, so do it only if necessary
@@ -1018,15 +1526,19 @@ string Layout::defaultCSSClass() const
 
 
 namespace {
-       string makeMarginValue(char const * side, double d) {
-               ostringstream os;
-               os << "margin-" << side << ": " << d << "ex;\n";
-               return os.str();
-       }
+
+string makeMarginValue(char const * side, double d)
+{
+       ostringstream os;
+       os << "margin-" << side << ": " << d << "ex;\n";
+       return os.str();
+}
+
 }
 
 
-void Layout::makeDefaultCSS() const {
+void Layout::makeDefaultCSS() const
+{
        // this never needs to be redone, since reloading layouts will
        // wipe out what we did before.
        if (!htmldefaultstyle_.empty()) 
@@ -1058,15 +1570,12 @@ void Layout::makeDefaultCSS() const {
                htmldefaultstyle_ += from_ascii(tmp);
        }
 
-// tex2lyx does not see output_xhtml.cpp
-#ifndef TEX2LYX
        // alignment
        string where = alignmentToCSS(align);
        if (!where.empty()) {
                htmldefaultstyle_ += from_ascii("text-align: " + where + ";\n");
        }
-#endif
-       
+
        // wrap up what we have, if anything
        if (!htmldefaultstyle_.empty())
                htmldefaultstyle_ = 
@@ -1081,7 +1590,7 @@ void Layout::makeDefaultCSS() const {
        // label font
        if (labelfont != font)
                labelCSS = labelfont.asCSS() + from_ascii("\n");
-       if (labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)
+       if (labeltype == LABEL_CENTERED)
                labelCSS += from_ascii("text-align: center;\n");
        
        if (!labelCSS.empty())