From 7cf8b9da78d2747e4bba25d7f103da422ae28a6f Mon Sep 17 00:00:00 2001 From: Georg Baum Date: Sun, 31 Mar 2013 15:33:26 +0200 Subject: [PATCH] Implement writing of layouts This will be needed for layout forward compatibility, and could also be used for a layout editor. Writing was only implemented for styles, not for complete layout files (text class). I rarely made use of default values for missing variables which exist in read(), so the output it a bit verbose (but more safe against future changes). Also, some things like CopyStyle are never written for obvious reasons. --- src/FontInfo.cpp | 56 +++++++ src/FontInfo.h | 3 + src/Layout.cpp | 334 +++++++++++++++++++++++++++++++++++++++- src/Layout.h | 2 + src/support/Package.cpp | 2 +- 5 files changed, 394 insertions(+), 3 deletions(-) diff --git a/src/FontInfo.cpp b/src/FontInfo.cpp index 251e509d6b..e611288ff4 100644 --- a/src/FontInfo.cpp +++ b/src/FontInfo.cpp @@ -22,6 +22,9 @@ #include "support/docstring.h" #include "support/lstrings.h" +#include +#include + using namespace std; using namespace lyx::support; @@ -636,4 +639,57 @@ FontInfo lyxRead(Lexer & lex, FontInfo const & fi) } +void lyxWrite(ostream & os, FontInfo const & f, string const & start, int level) +{ + string indent; + for (int i = 0; i < level; ++i) + indent += '\t'; + ostringstream oss; + if (f.family() != INHERIT_FAMILY) + oss << indent << "\tFamily " << LyXFamilyNames[f.family()] + << '\n'; + if (f.series() != INHERIT_SERIES) + oss << indent << "\tSeries " << LyXSeriesNames[f.series()] + << '\n'; + if (f.shape() != INHERIT_SHAPE) + oss << indent << "\tShape " << LyXShapeNames[f.shape()] + << '\n'; + if (f.size() != FONT_SIZE_INHERIT) + oss << indent << "\tSize " << LyXSizeNames[f.size()] + << '\n'; + if (f.underbar() == FONT_ON) + oss << indent << "\tMisc Underbar\n"; + else if (f.underbar() == FONT_OFF) + oss << indent << "\tMisc No_Bar\n"; + if (f.strikeout() == FONT_ON) + oss << indent << "\tMisc Strikeout\n"; + else if (f.strikeout() == FONT_OFF) + oss << indent << "\tMisc No_Strikeout\n"; + if (f.uuline() == FONT_ON) + oss << indent << "\tMisc Uuline\n"; + else if (f.uuline() == FONT_OFF) + oss << indent << "\tMisc No_Uuline\n"; + if (f.uwave() == FONT_ON) + oss << indent << "\tMisc Uwave\n"; + else if (f.uwave() == FONT_OFF) + oss << indent << "\tMisc No_Uwave\n"; + if (f.emph() == FONT_ON) + oss << indent << "\tMisc Emph\n"; + else if (f.emph() == FONT_OFF) + oss << indent << "\tMisc No_Emph\n"; + if (f.noun() == FONT_ON) + oss << indent << "\tMisc Noun\n"; + else if (f.noun() == FONT_OFF) + oss << indent << "\tMisc No_Noun\n"; + if (f.color() != Color_inherit && f.color() != Color_none) + oss << indent << "\tColor " << lcolor.getLyXName(f.color()) + << '\n'; + if (!oss.str().empty()) { + os << indent << start << '\n' + << oss.str() + << indent << "EndFont\n"; + } +} + + } // namespace lyx diff --git a/src/FontInfo.h b/src/FontInfo.h index a083eae2aa..2b639a926c 100644 --- a/src/FontInfo.h +++ b/src/FontInfo.h @@ -221,6 +221,9 @@ FontState setLyXMisc(std::string const &); /// Read a font specification from Lexer. Used for layout files. FontInfo lyxRead(Lexer &, FontInfo const & fi = sane_font); +/// Write a font specification. Used for layout files. +void lyxWrite(std::ostream &, FontInfo const &, std::string const &, int); + } // namespace lyx #endif diff --git a/src/Layout.cpp b/src/Layout.cpp index deec49fdbe..080e41a85d 100644 --- a/src/Layout.cpp +++ b/src/Layout.cpp @@ -479,7 +479,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_); @@ -882,6 +882,7 @@ void Layout::readSpacing(Lexer & lex) void Layout::readArgument(Lexer & lex) { latexarg arg; + // writeArgument() makes use of these default values arg.mandatory = false; arg.autoinsert = false; bool error = false; @@ -958,6 +959,335 @@ void Layout::readArgument(Lexer & lex) } +void writeArgument(ostream & os, string const & id, Layout::latexarg const & arg) +{ + 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.ldelim.empty()) + os << "\t\tLeftDelim \"" + << to_utf8(subst(arg.ldelim, from_ascii("\n"), from_ascii("
"))) + << "\"\n"; + if (!arg.rdelim.empty()) + os << "\t\tRightDelim \"" + << to_utf8(subst(arg.rdelim, from_ascii("\n"), from_ascii("
"))) + << "\"\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); + os << "\tEndArgument\n"; +} + + +void Layout::write(ostream & os) const +{ + os << "Style " << to_utf8(name_) << '\n'; + if (!category_.empty()) + os << "\tCategory " << to_utf8(category_) << '\n'; + // Can't deduce Copystyle here :-( + if (!obsoleted_by_.empty()) + os << "\tObsoletedby " << to_utf8(obsoleted_by_) << '\n'; + 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_, "\"", """) + << '\n'; + if (!leftdelim_.empty()) + os << "\tLeftDelim " + << to_utf8(subst(leftdelim_, from_ascii("\n"), from_ascii("
"))) + << '\n'; + if (!rightdelim_.empty()) + os << "\tRightDelim " + << to_utf8(subst(rightdelim_, from_ascii("\n"), from_ascii("
"))) + << '\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" + << to_utf8(rtrim(preamble_, "\n")) + << "\n\tEndPreamble\n"; + if (!langpreamble_.empty()) + os << "\tLangPreamble\n" + << to_utf8(rtrim(langpreamble_, "\n")) + << "\n\tEndLangPreamble\n"; + if (!babelpreamble_.empty()) + os << "\tBabelPreamble\n" + << to_utf8(rtrim(babelpreamble_, "\n")) + << "\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; + } + 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) { + if (!first) + os << ','; + 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; + } + 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'; + } + // 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'; + 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::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" + "End\n"; +} + + Layout::LaTeXArgMap Layout::args() const { LaTeXArgMap args = latexargs_; @@ -1149,7 +1479,7 @@ void Layout::makeDefaultCSS() const htmldefaultstyle_ += from_ascii("text-align: " + where + ";\n"); } #endif - + // wrap up what we have, if anything if (!htmldefaultstyle_.empty()) htmldefaultstyle_ = diff --git a/src/Layout.h b/src/Layout.h index 88cb9a4edb..3ffd54246b 100644 --- a/src/Layout.h +++ b/src/Layout.h @@ -75,6 +75,8 @@ public: void readSpacing(Lexer &); /// void readArgument(Lexer &); + /// Write a layout definition in utf8 encoding + void write(std::ostream &) const; /// docstring const & name() const { return name_; } /// diff --git a/src/support/Package.cpp b/src/support/Package.cpp index dab008e77c..bd4fcfda24 100644 --- a/src/support/Package.cpp +++ b/src/support/Package.cpp @@ -125,7 +125,7 @@ Package::Package(string const & command_line_arg0, system_support_dir_ = get_system_support_dir(abs_binary, command_line_system_support_dir); - } + } // Find the LyX executable lyx_binary_ = findLyxBinary(abs_binary);