3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Jean-Marc Lasgouttes
10 * Full author contact details are available in file CREDITS.
19 #include "output_xhtml.h"
20 #include "TextClass.h"
22 #include "support/debug.h"
23 #include "support/lassert.h"
24 #include "support/lstrings.h"
25 #include "support/Messages.h"
26 #include "support/textutils.h"
30 using namespace lyx::support;
34 /// Special value of toclevel for layouts that to not belong in a TOC
35 const int Layout::NOT_IN_TOC = -1000;
37 // The order of the LayoutTags enum is no more important. [asierra300396]
54 LT_PARBREAK_IS_NEWLINE,
64 LT_LABELSTRING_APPENDIX,
107 LT_INTITLE // keep this last!
110 /////////////////////
115 margintype = MARGIN_STATIC;
116 latextype = LATEX_PARAGRAPH;
122 labelfont = inherit_font;
124 reslabelfont = sane_font;
125 nextnoindent = false;
130 labelbottomsep = 0.0;
132 align = LYX_ALIGN_BLOCK;
133 alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
134 labeltype = LABEL_NO_LABEL;
135 endlabeltype = END_LABEL_NO_LABEL;
136 // Should or should not. That is the question.
137 // spacing.set(Spacing::OneHalf);
138 newline_allowed = true;
139 free_spacing = false;
141 parbreak_is_newline = false;
142 toclevel = NOT_IN_TOC;
144 htmllabelfirst_ = false;
145 htmlforcecss_ = false;
148 itemcommand_ = "item";
152 bool Layout::read(Lexer & lex, TextClass const & tclass)
154 // This table is sorted alphabetically [asierra 30March96]
155 LexerKeyword layoutTags[] = {
156 { "align", LT_ALIGN },
157 { "alignpossible", LT_ALIGNPOSSIBLE },
158 { "argument", LT_ARGUMENT },
159 { "babelpreamble", LT_BABELPREAMBLE },
160 { "bottomsep", LT_BOTTOMSEP },
161 { "category", LT_CATEGORY },
162 { "commanddepth", LT_COMMANDDEPTH },
163 { "copystyle", LT_COPYSTYLE },
164 { "dependson", LT_DEPENDSON },
166 { "endlabelstring", LT_ENDLABELSTRING },
167 { "endlabeltype", LT_ENDLABELTYPE },
169 { "freespacing", LT_FREE_SPACING },
170 { "htmlattr", LT_HTMLATTR },
171 { "htmlforcecss", LT_HTMLFORCECSS },
172 { "htmlitem", LT_HTMLITEM },
173 { "htmlitemattr", LT_HTMLITEMATTR },
174 { "htmllabel", LT_HTMLLABEL },
175 { "htmllabelattr", LT_HTMLLABELATTR },
176 { "htmllabelfirst", LT_HTMLLABELFIRST },
177 { "htmlpreamble", LT_HTMLPREAMBLE },
178 { "htmlstyle", LT_HTMLSTYLE },
179 { "htmltag", LT_HTMLTAG },
180 { "htmltitle", LT_HTMLTITLE },
181 { "innertag", LT_INNERTAG },
182 { "inpreamble", LT_INPREAMBLE },
183 { "intitle", LT_INTITLE },
184 { "itemcommand", LT_ITEMCOMMAND },
185 { "itemsep", LT_ITEMSEP },
186 { "itemtag", LT_ITEMTAG },
187 { "keepempty", LT_KEEPEMPTY },
188 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
189 { "labelcounter", LT_LABELCOUNTER },
190 { "labelfont", LT_LABELFONT },
191 { "labelindent", LT_LABELINDENT },
192 { "labelsep", LT_LABELSEP },
193 { "labelstring", LT_LABELSTRING },
194 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
195 { "labeltag", LT_LABELTAG },
196 { "labeltype", LT_LABELTYPE },
197 { "langpreamble", LT_LANGPREAMBLE },
198 { "latexname", LT_LATEXNAME },
199 { "latexparam", LT_LATEXPARAM },
200 { "latextype", LT_LATEXTYPE },
201 { "leftdelim", LT_LEFTDELIM },
202 { "leftmargin", LT_LEFTMARGIN },
203 { "margin", LT_MARGIN },
204 { "needprotect", LT_NEED_PROTECT },
205 { "newline", LT_NEWLINE },
206 { "nextnoindent", LT_NEXTNOINDENT },
207 { "obsoletedby", LT_OBSOLETEDBY },
208 { "parbreakisnewline", LT_PARBREAK_IS_NEWLINE },
209 { "parindent", LT_PARINDENT },
210 { "parsep", LT_PARSEP },
211 { "parskip", LT_PARSKIP },
212 { "passthru", LT_PASS_THRU },
213 { "preamble", LT_PREAMBLE },
214 { "refprefix", LT_REFPREFIX },
215 { "requires", LT_REQUIRES },
216 { "resetargs", LT_RESETARGS },
217 { "rightdelim", LT_RIGHTDELIM },
218 { "rightmargin", LT_RIGHTMARGIN },
219 { "spacing", LT_SPACING },
220 { "spellcheck", LT_SPELLCHECK },
221 { "textfont", LT_TEXTFONT },
222 { "toclevel", LT_TOCLEVEL },
223 { "topsep", LT_TOPSEP }
227 bool finished = false;
228 lex.pushTable(layoutTags);
230 // parse style section
231 while (!finished && lex.isOK() && !error) {
233 // See comment in LyXRC.cpp.
235 case Lexer::LEX_FEOF:
238 case Lexer::LEX_UNDEF:
240 lex.printError("Unknown layout tag `$$Token'");
247 switch (static_cast<LayoutTags>(le)) {
259 style = subst(style, '_', ' ');
261 if (tclass.hasLayout(style)) {
262 docstring const tmpname = name_;
263 this->operator=(tclass[style]);
266 LYXERR0("Cannot copy unknown style `"
268 << "All layouts so far:");
269 DocumentClass::const_iterator lit = tclass.begin();
270 DocumentClass::const_iterator len = tclass.end();
271 for (; lit != len; ++lit)
272 LYXERR0(lit->name());
277 case LT_OBSOLETEDBY: {
280 style = subst(style, '_', ' ');
282 if (tclass.hasLayout(style)) {
283 docstring const tmpname = name_;
284 this->operator=(tclass[style]);
286 if (obsoleted_by().empty())
287 obsoleted_by_ = style;
289 LYXERR0("Cannot replace with unknown style `"
292 //lex.printError("Cannot replace with"
301 depends_on_ = subst(depends_on_, '_', ' ');
330 postcommandargs_.clear();
338 case LT_NEED_PROTECT:
347 font = lyxRead(lex, font);
352 font = lyxRead(lex, font);
356 labelfont = lyxRead(lex, labelfont);
359 case LT_NEXTNOINDENT:
363 case LT_COMMANDDEPTH:
373 latexparam_ = subst(latexparam_, """, "\"");
378 leftdelim_ = support::subst(leftdelim_, from_ascii("<br/>"),
384 rightdelim_ = support::subst(rightdelim_, from_ascii("<br/>"),
405 preamble_ = from_utf8(lex.getLongString("EndPreamble"));
408 case LT_LANGPREAMBLE:
409 langpreamble_ = from_utf8(lex.getLongString("EndLangPreamble"));
412 case LT_BABELPREAMBLE:
413 babelpreamble_ = from_utf8(lex.getLongString("EndBabelPreamble"));
420 case LT_ENDLABELTYPE:
421 readEndLabelType(lex);
456 case LT_LABEL_BOTTOMSEP:
457 lex >> labelbottomsep;
462 labelsep = subst(labelsep, 'x', ' ');
470 lex >> newline_allowed;
477 case LT_ALIGNPOSSIBLE:
478 readAlignPossible(lex);
482 // FIXME: this means LT_LABELSTRING_APPENDIX may only
483 // occur after LT_LABELSTRING
485 labelstring_ = trim(labelstring_);
486 labelstring_appendix_ = labelstring_;
489 case LT_ENDLABELSTRING:
490 lex >> endlabelstring_;
491 endlabelstring_ = trim(endlabelstring_);
494 case LT_LABELSTRING_APPENDIX:
495 lex >> labelstring_appendix_;
496 labelstring_appendix_ = trim(labelstring_appendix_);
499 case LT_LABELCOUNTER:
501 counter = trim(counter);
504 case LT_FREE_SPACING:
512 case LT_PARBREAK_IS_NEWLINE:
513 lex >> parbreak_is_newline;
522 vector<string> const req =
523 getVectorFromString(lex.getString());
524 requires_.insert(req.begin(), req.end());
550 case LT_HTMLITEMATTR:
551 lex >> htmlitemattr_;
555 lex >> htmllabeltag_;
558 case LT_HTMLLABELATTR:
559 lex >> htmllabelattr_;
562 case LT_HTMLLABELFIRST:
563 lex >> htmllabelfirst_;
567 htmlstyle_ = from_utf8(lex.getLongString("EndHTMLStyle"));
570 case LT_HTMLFORCECSS:
571 lex >> htmlforcecss_;
574 case LT_HTMLPREAMBLE:
575 htmlpreamble_ = from_utf8(lex.getLongString("EndPreamble"));
588 // make sure we only have inpreamble = true for commands
589 if (inpreamble && latextype != LATEX_COMMAND && latextype != LATEX_PARAGRAPH) {
590 LYXERR0("InPreamble not permitted except with command and paragraph layouts.");
591 LYXERR0("Layout name: " << name());
595 return finished && !error;
608 LexerKeyword alignTags[] = {
609 { "block", AT_BLOCK },
610 { "center", AT_CENTER },
611 { "layout", AT_LAYOUT },
613 { "right", AT_RIGHT }
617 void Layout::readAlign(Lexer & lex)
619 PushPopHelper pph(lex, alignTags);
622 case Lexer::LEX_UNDEF:
623 lex.printError("Unknown alignment `$$Token'");
629 align = LYX_ALIGN_BLOCK;
632 align = LYX_ALIGN_LEFT;
635 align = LYX_ALIGN_RIGHT;
638 align = LYX_ALIGN_CENTER;
641 align = LYX_ALIGN_LAYOUT;
647 void Layout::readAlignPossible(Lexer & lex)
649 lex.pushTable(alignTags);
650 alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
651 int lineno = lex.lineNumber();
655 case Lexer::LEX_UNDEF:
656 lex.printError("Unknown alignment `$$Token'");
662 alignpossible |= LYX_ALIGN_BLOCK;
665 alignpossible |= LYX_ALIGN_LEFT;
668 alignpossible |= LYX_ALIGN_RIGHT;
671 alignpossible |= LYX_ALIGN_CENTER;
674 alignpossible |= LYX_ALIGN_LAYOUT;
677 } while (lineno == lex.lineNumber());
682 void Layout::readLabelType(Lexer & lex)
697 LexerKeyword labelTypeTags[] = {
698 { "above", LA_ABOVE },
699 { "bibliography", LA_BIBLIO },
700 { "centered", LA_CENTERED },
701 { "enumerate", LA_ENUMERATE },
702 { "itemize", LA_ITEMIZE },
703 { "manual", LA_MANUAL },
704 { "no_label", LA_NO_LABEL },
705 { "sensitive", LA_SENSITIVE },
706 { "static", LA_STATIC }
709 PushPopHelper pph(lex, labelTypeTags);
712 case Lexer::LEX_UNDEF:
713 lex.printError("Unknown labeltype tag `$$Token'");
719 labeltype = LABEL_NO_LABEL;
722 labeltype = LABEL_MANUAL;
725 labeltype = LABEL_ABOVE;
728 labeltype = LABEL_CENTERED;
731 labeltype = LABEL_STATIC;
734 labeltype = LABEL_SENSITIVE;
737 labeltype = LABEL_ENUMERATE;
740 labeltype = LABEL_ITEMIZE;
743 labeltype = LABEL_BIBLIO;
749 void Layout::readEndLabelType(Lexer & lex)
751 static LexerKeyword endlabelTypeTags[] = {
752 { "box", END_LABEL_BOX },
753 { "filled_box", END_LABEL_FILLED_BOX },
754 { "no_label", END_LABEL_NO_LABEL },
755 { "static", END_LABEL_STATIC }
758 PushPopHelper pph(lex, endlabelTypeTags);
761 case Lexer::LEX_UNDEF:
762 lex.printError("Unknown labeltype tag `$$Token'");
764 case END_LABEL_STATIC:
766 case END_LABEL_FILLED_BOX:
767 case END_LABEL_NO_LABEL:
768 endlabeltype = static_cast<EndLabelType>(le);
771 LYXERR0("Unhandled value " << le);
777 void Layout::readMargin(Lexer & lex)
779 LexerKeyword marginTags[] = {
780 { "dynamic", MARGIN_DYNAMIC },
781 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
782 { "manual", MARGIN_MANUAL },
783 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
784 { "static", MARGIN_STATIC }
787 PushPopHelper pph(lex, marginTags);
791 case Lexer::LEX_UNDEF:
792 lex.printError("Unknown margin type tag `$$Token'");
797 case MARGIN_FIRST_DYNAMIC:
798 case MARGIN_RIGHT_ADDRESS_BOX:
799 margintype = static_cast<MarginType>(le);
802 LYXERR0("Unhandled value " << le);
808 void Layout::readLatexType(Lexer & lex)
810 LexerKeyword latexTypeTags[] = {
811 { "bib_environment", LATEX_BIB_ENVIRONMENT },
812 { "command", LATEX_COMMAND },
813 { "environment", LATEX_ENVIRONMENT },
814 { "item_environment", LATEX_ITEM_ENVIRONMENT },
815 { "list_environment", LATEX_LIST_ENVIRONMENT },
816 { "paragraph", LATEX_PARAGRAPH }
819 PushPopHelper pph(lex, latexTypeTags);
822 case Lexer::LEX_UNDEF:
823 lex.printError("Unknown latextype tag `$$Token'");
825 case LATEX_PARAGRAPH:
827 case LATEX_ENVIRONMENT:
828 case LATEX_ITEM_ENVIRONMENT:
829 case LATEX_BIB_ENVIRONMENT:
830 case LATEX_LIST_ENVIRONMENT:
831 latextype = static_cast<LatexType>(le);
834 LYXERR0("Unhandled value " << le);
840 void Layout::readSpacing(Lexer & lex)
843 ST_SPACING_SINGLE = 1,
849 LexerKeyword spacingTags[] = {
850 {"double", ST_SPACING_DOUBLE },
851 {"onehalf", ST_SPACING_ONEHALF },
852 {"other", ST_OTHER },
853 {"single", ST_SPACING_SINGLE }
856 PushPopHelper pph(lex, spacingTags);
859 case Lexer::LEX_UNDEF:
860 lex.printError("Unknown spacing token `$$Token'");
865 case ST_SPACING_SINGLE:
866 spacing.set(Spacing::Single);
868 case ST_SPACING_ONEHALF:
869 spacing.set(Spacing::Onehalf);
871 case ST_SPACING_DOUBLE:
872 spacing.set(Spacing::Double);
876 spacing.set(Spacing::Other, lex.getString());
882 void Layout::readArgument(Lexer & lex)
885 // writeArgument() makes use of these default values
886 arg.mandatory = false;
887 arg.autoinsert = false;
889 bool finished = false;
890 arg.font = inherit_font;
891 arg.labelfont = inherit_font;
894 bool const itemarg = prefixIs(id, "item:");
895 bool const postcmd = prefixIs(id, "post:");
897 while (!finished && lex.isOK() && !error) {
899 string const tok = ascii_lowercase(lex.getString());
903 } else if (tok == "endargument") {
905 } else if (tok == "labelstring") {
907 arg.labelstring = lex.getDocString();
908 } else if (tok == "menustring") {
910 arg.menustring = lex.getDocString();
911 } else if (tok == "mandatory") {
913 arg.mandatory = lex.getBool();
914 } else if (tok == "autoinsert") {
916 arg.autoinsert = lex.getBool();
917 } else if (tok == "leftdelim") {
919 arg.ldelim = lex.getDocString();
920 arg.ldelim = support::subst(arg.ldelim, from_ascii("<br/>"),
922 } else if (tok == "rightdelim") {
924 arg.rdelim = lex.getDocString();
925 arg.rdelim = support::subst(arg.rdelim, from_ascii("<br/>"),
927 } else if (tok == "defaultarg") {
929 arg.defaultarg = lex.getDocString();
930 } else if (tok == "presetarg") {
932 arg.presetarg = lex.getDocString();
933 } else if (tok == "tooltip") {
935 arg.tooltip = lex.getDocString();
936 } else if (tok == "requires") {
938 arg.requires = lex.getString();
939 } else if (tok == "decoration") {
941 arg.decoration = lex.getString();
942 } else if (tok == "font") {
943 arg.font = lyxRead(lex, arg.font);
944 } else if (tok == "labelfont") {
945 arg.labelfont = lyxRead(lex, arg.labelfont);
947 lex.printError("Unknown tag");
951 if (arg.labelstring.empty())
952 LYXERR0("Incomplete Argument definition!");
956 postcommandargs_[id] = arg;
958 latexargs_[id] = arg;
962 void writeArgument(ostream & os, string const & id, Layout::latexarg const & arg)
964 os << "\tArgument " << id << '\n';
965 if (!arg.labelstring.empty())
966 os << "\t\tLabelString \"" << to_utf8(arg.labelstring) << "\"\n";
967 if (!arg.menustring.empty())
968 os << "\t\tMenuString \"" << to_utf8(arg.menustring) << "\"\n";
970 os << "\t\tMandatory " << arg.mandatory << '\n';
972 os << "\t\tAutoinsert " << arg.autoinsert << '\n';
973 if (!arg.ldelim.empty())
974 os << "\t\tLeftDelim \""
975 << to_utf8(subst(arg.ldelim, from_ascii("\n"), from_ascii("<br/>")))
977 if (!arg.rdelim.empty())
978 os << "\t\tRightDelim \""
979 << to_utf8(subst(arg.rdelim, from_ascii("\n"), from_ascii("<br/>")))
981 if (!arg.defaultarg.empty())
982 os << "\t\tDefaultArg \"" << to_utf8(arg.defaultarg) << "\"\n";
983 if (!arg.presetarg.empty())
984 os << "\t\tPresetArg \"" << to_utf8(arg.presetarg) << "\"\n";
985 if (!arg.tooltip.empty())
986 os << "\t\tToolTip \"" << to_utf8(arg.tooltip) << "\"\n";
987 if (!arg.requires.empty())
988 os << "\t\tRequires \"" << arg.requires << "\"\n";
989 if (!arg.decoration.empty())
990 os << "\t\tDecoration \"" << arg.decoration << "\"\n";
991 if (arg.font != inherit_font)
992 lyxWrite(os, arg.font, "Font", 2);
993 if (arg.labelfont != inherit_font)
994 lyxWrite(os, arg.labelfont, "LabelFont", 2);
995 os << "\tEndArgument\n";
999 void Layout::write(ostream & os) const
1001 os << "Style " << to_utf8(name_) << '\n';
1002 if (!category_.empty() && obsoleted_by_.empty())
1003 os << "\tCategory \"" << to_utf8(category_) << "\"\n";
1004 // Can't deduce Copystyle here :-(
1005 if (!obsoleted_by_.empty()) {
1006 os << "\tObsoletedBy \"" << to_utf8(obsoleted_by_)
1010 if (!depends_on_.empty())
1011 os << "\tDependsOn " << to_utf8(depends_on_) << '\n';
1012 switch (margintype) {
1013 case MARGIN_DYNAMIC:
1014 os << "\tMargin Dynamic\n";
1016 case MARGIN_FIRST_DYNAMIC:
1017 os << "\tMargin First_Dynamic\n";
1020 os << "\tMargin Manual\n";
1022 case MARGIN_RIGHT_ADDRESS_BOX:
1023 os << "\tMargin Right_Address_Box\n";
1026 os << "\tMargin Static\n";
1029 switch (latextype) {
1030 case LATEX_BIB_ENVIRONMENT:
1031 os << "\tLatexType Bib_Environment\n";
1034 os << "\tLatexType Command\n";
1036 case LATEX_ENVIRONMENT:
1037 os << "\tLatexType Environment\n";
1039 case LATEX_ITEM_ENVIRONMENT:
1040 os << "\tLatexType Item_Environment\n";
1042 case LATEX_LIST_ENVIRONMENT:
1043 os << "\tLatexType List_Environment\n";
1045 case LATEX_PARAGRAPH:
1046 os << "\tLatexType Paragraph\n";
1049 os << "\tInTitle " << intitle << "\n"
1050 "\tInPreamble " << inpreamble << "\n"
1051 "\tTocLevel " << toclevel << '\n';
1052 // ResetArgs does not make sense here
1053 for (LaTeXArgMap::const_iterator it = latexargs_.begin();
1054 it != latexargs_.end(); ++it)
1055 writeArgument(os, it->first, it->second);
1056 for (LaTeXArgMap::const_iterator it = itemargs_.begin();
1057 it != itemargs_.end(); ++it)
1058 writeArgument(os, it->first, it->second);
1059 for (LaTeXArgMap::const_iterator it = postcommandargs_.begin();
1060 it != postcommandargs_.end(); ++it)
1061 writeArgument(os, it->first, it->second);
1062 os << "\tNeedProtect " << needprotect << "\n"
1063 "\tKeepEmpty " << keepempty << '\n';
1064 if (labelfont == font)
1065 lyxWrite(os, font, "Font", 1);
1067 lyxWrite(os, font, "TextFont", 1);
1068 lyxWrite(os, labelfont, "LabelFont", 1);
1070 os << "\tNextNoIndent " << nextnoindent << "\n"
1071 "\tCommandDepth " << commanddepth << '\n';
1072 if (!latexname_.empty())
1073 os << "\tLatexName \"" << latexname_ << "\"\n";
1074 if (!latexparam_.empty())
1075 os << "\tLatexParam \"" << subst(latexparam_, "\"", """)
1077 if (!leftdelim_.empty())
1078 os << "\tLeftDelim "
1079 << to_utf8(subst(leftdelim_, from_ascii("\n"), from_ascii("<br/>")))
1081 if (!rightdelim_.empty())
1082 os << "\tRightDelim "
1083 << to_utf8(subst(rightdelim_, from_ascii("\n"), from_ascii("<br/>")))
1085 if (!innertag_.empty())
1086 os << "\tInnerTag \"" << innertag_ << "\"\n";
1087 if (!labeltag_.empty())
1088 os << "\tLabelTag \"" << labeltag_ << "\"\n";
1089 if (!itemtag_.empty())
1090 os << "\tItemTag \"" << itemtag_ << "\"\n";
1091 if (!itemcommand_.empty())
1092 os << "\tItemCommand " << itemcommand_ << '\n';
1093 if (!preamble_.empty())
1094 os << "\tPreamble\n\t"
1095 << to_utf8(subst(rtrim(preamble_, "\n"),
1096 from_ascii("\n"), from_ascii("\n\t")))
1097 << "\n\tEndPreamble\n";
1098 if (!langpreamble_.empty())
1099 os << "\tLangPreamble\n\t"
1100 << to_utf8(subst(rtrim(langpreamble_, "\n"),
1101 from_ascii("\n"), from_ascii("\n\t")))
1102 << "\n\tEndLangPreamble\n";
1103 if (!babelpreamble_.empty())
1104 os << "\tBabelPreamble\n\t"
1105 << to_utf8(subst(rtrim(babelpreamble_, "\n"),
1106 from_ascii("\n"), from_ascii("\n\t")))
1107 << "\n\tEndBabelPreamble\n";
1108 switch (labeltype) {
1110 os << "\tLabelType Above\n";
1113 os << "\tLabelType Bibliography\n";
1115 case LABEL_CENTERED:
1116 os << "\tLabelType Centered\n";
1118 case LABEL_ENUMERATE:
1119 os << "\tLabelType Enumerate\n";
1122 os << "\tLabelType Itemize\n";
1125 os << "\tLabelType Manual\n";
1127 case LABEL_NO_LABEL:
1128 os << "\tLabelType No_Label\n";
1130 case LABEL_SENSITIVE:
1131 os << "\tLabelType Sensitive\n";
1134 os << "\tLabelType Static\n";
1137 switch (endlabeltype) {
1139 os << "\tEndLabelType Box\n";
1141 case END_LABEL_FILLED_BOX:
1142 os << "\tEndLabelType Filled_Box\n";
1144 case END_LABEL_NO_LABEL:
1145 os << "\tEndLabelType No_Label\n";
1147 case END_LABEL_STATIC:
1148 os << "\tEndLabelType Static\n";
1151 if (!leftmargin.empty())
1152 os << "\tLeftMargin \"" << to_utf8(leftmargin) << "\"\n";
1153 if (!rightmargin.empty())
1154 os << "\tRightMargin \"" << to_utf8(rightmargin) << "\"\n";
1155 if (!labelindent.empty())
1156 os << "\tLabelIndent " << to_utf8(labelindent) << '\n';
1157 if (!parindent.empty())
1158 os << "\tParIndent " << to_utf8(parindent) << '\n';
1159 os << "\tParSkip " << parskip << "\n"
1160 "\tItemSep " << itemsep << "\n"
1161 "\tTopSep " << topsep << "\n"
1162 "\tBottomSep " << bottomsep << "\n"
1163 "\tLabelBottomSep " << labelbottomsep << '\n';
1164 if (!labelsep.empty())
1165 os << "\tLabelSep " << to_utf8(subst(labelsep, ' ', 'x'))
1167 os << "\tParSep " << parsep << "\n"
1168 "\tNewLine " << newline_allowed << '\n';
1170 case LYX_ALIGN_BLOCK:
1171 os << "\tAlign Block\n";
1173 case LYX_ALIGN_CENTER:
1174 os << "\tAlign Center\n";
1176 case LYX_ALIGN_LAYOUT:
1177 os << "\tAlign Layout\n";
1179 case LYX_ALIGN_LEFT:
1180 os << "\tAlign Left\n";
1182 case LYX_ALIGN_RIGHT:
1183 os << "\tAlign Right\n";
1185 case LYX_ALIGN_DECIMAL:
1186 case LYX_ALIGN_SPECIAL:
1187 case LYX_ALIGN_NONE:
1190 if (alignpossible & (LYX_ALIGN_BLOCK | LYX_ALIGN_CENTER |
1191 LYX_ALIGN_LAYOUT | LYX_ALIGN_LEFT | LYX_ALIGN_RIGHT)) {
1193 os << "\tAlignPossible";
1194 if (alignpossible & LYX_ALIGN_BLOCK) {
1200 if (alignpossible & LYX_ALIGN_CENTER) {
1206 if (alignpossible & LYX_ALIGN_LAYOUT) {
1212 if (alignpossible & LYX_ALIGN_LEFT) {
1218 if (alignpossible & LYX_ALIGN_RIGHT) {
1226 // LabelString must come before LabelStringAppendix
1227 if (!labelstring_.empty())
1228 os << "\tLabelString \"" << to_utf8(labelstring_) << "\"\n";
1229 if (!endlabelstring_.empty())
1230 os << "\tEndLabelString \"" << to_utf8(endlabelstring_) << "\"\n";
1231 if (!labelstring_appendix_.empty() && labelstring_appendix_ != labelstring_)
1232 os << "\tLabelStringAppendix \""
1233 << to_utf8(labelstring_appendix_) << "\"\n";
1234 if (!counter.empty())
1235 os << "\tLabelCounter \"" << to_utf8(counter) << "\"\n";
1236 os << "\tFreeSpacing " << free_spacing << '\n';
1237 os << "\tPassThru " << pass_thru << '\n';
1238 os << "\tParbreakIsNewline " << parbreak_is_newline << '\n';
1239 switch (spacing.getSpace()) {
1240 case Spacing::Double:
1241 os << "\tSpacing Double\n";
1243 case Spacing::Onehalf:
1244 os << "\tSpacing Onehalf\n";
1246 case Spacing::Other:
1247 os << "\tSpacing Other " << spacing.getValueAsString() << '\n';
1249 case Spacing::Single:
1250 os << "\tSpacing Single\n";
1252 case Spacing::Default:
1255 if (!requires_.empty()) {
1256 os << "\tRequires ";
1257 for (set<string>::const_iterator it = requires_.begin();
1258 it != requires_.end(); ++it) {
1259 if (it != requires_.begin())
1265 if (refprefix.empty())
1266 os << "\tRefPrefix OFF\n";
1268 os << "\tRefPrefix " << to_utf8(refprefix) << '\n';
1269 if (!htmltag_.empty())
1270 os << "\tHTMLTag " << htmltag_ << '\n';
1271 if (!htmlattr_.empty())
1272 os << "\tHTMLAttr " << htmlattr_ << '\n';
1273 if (!htmlitemtag_.empty())
1274 os << "\tHTMLItem " << htmlitemtag_ << '\n';
1275 if (!htmlitemattr_.empty())
1276 os << "\tHTMLItemAttr " << htmlitemattr_ << '\n';
1277 if (!htmllabeltag_.empty())
1278 os << "\tHTMLLabel " << htmllabeltag_ << '\n';
1279 if (!htmllabelattr_.empty())
1280 os << "\tHTMLLabelAttr " << htmllabelattr_ << '\n';
1281 os << "\tHTMLLabelFirst " << htmllabelfirst_ << '\n';
1282 if (!htmlstyle_.empty())
1283 os << "\tHTMLStyle\n"
1284 << to_utf8(rtrim(htmlstyle_, "\n"))
1285 << "\n\tEndHTMLStyle\n";
1286 os << "\tHTMLForceCSS " << htmlforcecss_ << '\n';
1287 if (!htmlpreamble_.empty())
1288 os << "\tHTMLPreamble\n"
1289 << to_utf8(rtrim(htmlpreamble_, "\n"))
1290 << "\n\tEndPreamble\n";
1291 os << "\tHTMLTitle " << htmltitle_ << "\n"
1292 "\tSpellcheck " << spellcheck << "\n"
1297 Layout::LaTeXArgMap Layout::args() const
1299 LaTeXArgMap args = latexargs_;
1300 if (!postcommandargs_.empty())
1301 args.insert(postcommandargs_.begin(), postcommandargs_.end());
1302 if (!itemargs_.empty())
1303 args.insert(itemargs_.begin(), itemargs_.end());
1308 int Layout::optArgs() const
1311 LaTeXArgMap::const_iterator it = latexargs_.begin();
1312 for (; it != latexargs_.end(); ++it) {
1313 if (!(*it).second.mandatory)
1316 LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
1317 for (; iit != postcommandargs_.end(); ++iit) {
1318 if (!(*iit).second.mandatory)
1325 int Layout::requiredArgs() const
1328 LaTeXArgMap::const_iterator it = latexargs_.begin();
1329 for (; it != latexargs_.end(); ++it) {
1330 if ((*it).second.mandatory)
1333 LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
1334 for (; iit != postcommandargs_.end(); ++iit) {
1335 if (!(*iit).second.mandatory)
1342 string const & Layout::htmltag() const
1344 if (htmltag_.empty())
1350 string const & Layout::htmlattr() const
1352 if (htmlattr_.empty())
1353 htmlattr_ = "class=\"" + defaultCSSClass() + "\"";
1358 string const & Layout::htmlitemtag() const
1360 if (htmlitemtag_.empty())
1361 htmlitemtag_ = "div";
1362 return htmlitemtag_;
1366 string const & Layout::htmlitemattr() const
1368 if (htmlitemattr_.empty())
1369 htmlitemattr_ = "class=\"" + defaultCSSItemClass() + "\"";
1370 return htmlitemattr_;
1374 string const & Layout::htmllabeltag() const
1376 if (htmllabeltag_.empty()) {
1377 if (labeltype != LABEL_ABOVE &&
1378 labeltype != LABEL_CENTERED)
1379 htmllabeltag_ = "span";
1381 htmllabeltag_ = "div";
1383 return htmllabeltag_;
1387 string const & Layout::htmllabelattr() const
1389 if (htmllabelattr_.empty())
1390 htmllabelattr_ = "class=\"" + defaultCSSLabelClass() + "\"";
1391 return htmllabelattr_;
1395 docstring Layout::htmlstyle() const
1397 if (!htmlstyle_.empty() && !htmlforcecss_)
1399 if (htmldefaultstyle_.empty())
1401 docstring retval = htmldefaultstyle_;
1402 if (!htmlstyle_.empty())
1403 retval += '\n' + htmlstyle_;
1408 string Layout::defaultCSSClass() const
1410 if (!defaultcssclass_.empty())
1411 return defaultcssclass_;
1413 docstring::const_iterator it = name().begin();
1414 docstring::const_iterator en = name().end();
1415 for (; it != en; ++it) {
1416 char_type const c = *it;
1417 if (!isAlphaASCII(c)) {
1419 // make sure we don't start with an underscore,
1420 // as that sometimes causes problems.
1421 d = from_ascii("lyx_");
1424 } else if (isLower(c))
1427 // this is slow, so do it only if necessary
1430 defaultcssclass_ = to_utf8(d);
1431 return defaultcssclass_;
1437 string makeMarginValue(char const * side, double d)
1440 os << "margin-" << side << ": " << d << "ex;\n";
1447 void Layout::makeDefaultCSS() const
1449 // this never needs to be redone, since reloading layouts will
1450 // wipe out what we did before.
1451 if (!htmldefaultstyle_.empty())
1455 htmldefaultstyle_ = font.asCSS();
1460 tmp += makeMarginValue("top", topsep);
1462 tmp += makeMarginValue("bottom", bottomsep);
1463 if (!leftmargin.empty()) {
1464 // we can't really do what LyX does with the margin, so
1465 // we'll just figure out how many characters it is
1466 int const len = leftmargin.length();
1467 tmp += makeMarginValue("left", len);
1469 if (!rightmargin.empty()) {
1470 int const len = rightmargin.length();
1471 tmp += makeMarginValue("right", len);
1475 if (!htmldefaultstyle_.empty())
1476 htmldefaultstyle_ += from_ascii("\n");
1477 htmldefaultstyle_ += from_ascii(tmp);
1480 // tex2lyx does not see output_xhtml.cpp
1483 string where = alignmentToCSS(align);
1484 if (!where.empty()) {
1485 htmldefaultstyle_ += from_ascii("text-align: " + where + ";\n");
1489 // wrap up what we have, if anything
1490 if (!htmldefaultstyle_.empty())
1492 from_ascii(htmltag() + "." + defaultCSSClass() + " {\n") +
1493 htmldefaultstyle_ + from_ascii("\n}\n");
1495 if (labeltype == LABEL_NO_LABEL || htmllabeltag() == "NONE")
1501 if (labelfont != font)
1502 labelCSS = labelfont.asCSS() + from_ascii("\n");
1503 if (labeltype == LABEL_CENTERED)
1504 labelCSS += from_ascii("text-align: center;\n");
1506 if (!labelCSS.empty())
1507 htmldefaultstyle_ +=
1508 from_ascii(htmllabeltag() + "." + defaultCSSLabelClass() + " {\n") +
1509 labelCSS + from_ascii("\n}\n");
1513 bool Layout::operator==(Layout const & rhs) const
1515 // This is enough for the applications we actually make,
1516 // at least at the moment. But we could check more.
1517 return name() == rhs.name()
1518 && latexname() == rhs.latexname()
1519 && latextype == rhs.latextype;