lyx_mirror/src/Layout.cpp

1737 lines
40 KiB
C++
Raw Normal View History

/**
* \file Layout.cpp
* 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 André Pönitz
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "Layout.h"
#include "FontInfo.h"
#include "Language.h"
#include "Lexer.h"
#include "output_xhtml.h"
#include "TextClass.h"
#include "support/debug.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/Messages.h"
#include "support/textutils.h"
using namespace std;
using namespace lyx::support;
namespace lyx {
/// Special value of toclevel for layouts that to not belong in a TOC
const int Layout::NOT_IN_TOC = -1000;
// The order of the LayoutTags enum is no more important. [asierra300396]
// Tags indexes.
enum LayoutTags {
LT_ALIGN = 1,
LT_ALIGNPOSSIBLE,
LT_ARGUMENT,
LT_AUTONESTS,
LT_AUTONESTEDBY,
LT_MARGIN,
LT_BOTTOMSEP,
LT_CATEGORY,
LT_COMMANDDEPTH,
LT_COPYSTYLE,
LT_DEPENDSON,
LT_OBSOLETEDBY,
LT_END,
LT_FONT,
LT_FREE_SPACING,
LT_PASS_THRU,
2015-04-20 16:13:49 +00:00
LT_PASS_THRU_CHARS,
LT_PARBREAK_IS_NEWLINE,
LT_ITEMCOMMAND,
LT_ITEMSEP,
LT_KEEPEMPTY,
LT_LABEL_BOTTOMSEP,
LT_LABELFONT,
LT_TEXTFONT,
LT_LABELINDENT,
LT_LABELSEP,
LT_LABELSTRING,
LT_LABELSTRING_APPENDIX,
LT_LABELCOUNTER,
LT_LABELTYPE,
LT_ENDLABELSTRING,
LT_ENDLABELTYPE,
LT_LATEXNAME,
LT_LATEXPARAM,
LT_LATEXTYPE,
LT_LEFTDELIM,
LT_LEFTMARGIN,
LT_NEED_CPROTECT,
LT_NEED_MBOXPROTECT,
LT_NEED_PROTECT,
LT_NEWLINE,
LT_NEXTNOINDENT,
LT_PAR_GROUP,
LT_PARINDENT,
LT_PARSEP,
LT_PARSKIP,
LT_PREAMBLE,
LT_LANGPREAMBLE,
LT_BABELPREAMBLE,
LT_REQUIRES,
LT_RIGHTMARGIN,
LT_SPACING,
LT_TOPSEP,
LT_TOCLEVEL,
LT_INNERTAG,
LT_LABELTAG,
LT_ITEMTAG,
LT_HTMLTAG,
LT_HTMLATTR,
LT_HTMLITEM,
LT_HTMLITEMATTR,
LT_HTMLLABEL,
2017-07-03 17:53:14 +00:00
LT_HTMLLABELATTR,
LT_HTMLLABELFIRST,
LT_HTMLPREAMBLE,
LT_HTMLSTYLE,
LT_HTMLFORCECSS,
LT_INPREAMBLE,
LT_HTMLTITLE,
LT_SPELLCHECK,
LT_REFPREFIX,
LT_RESETARGS,
LT_RESUMECOUNTER,
LT_STEPMASTERCOUNTER,
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_(true)
{
unknown_ = false;
margintype = MARGIN_STATIC;
latextype = LATEX_PARAGRAPH;
resumecounter = false;
stepmastercounter = false;
intitle = false;
inpreamble = false;
needprotect = false;
needcprotect = false;
needmboxprotect = false;
keepempty = false;
font = inherit_font;
labelfont = inherit_font;
resfont = sane_font;
reslabelfont = sane_font;
nextnoindent = false;
parskip = 0.0;
itemsep = 0;
topsep = 0.0;
bottomsep = 0.0;
labelbottomsep = 0.0;
parsep = 0;
align = LYX_ALIGN_BLOCK;
alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
labeltype = LABEL_NO_LABEL;
endlabeltype = END_LABEL_NO_LABEL;
// Should or should not. That is the question.
// spacing.set(Spacing::OneHalf);
newline_allowed = true;
free_spacing = false;
pass_thru = false;
parbreak_is_newline = false;
toclevel = NOT_IN_TOC;
commanddepth = 0;
htmllabelfirst_ = false;
htmlforcecss_ = false;
htmltitle_ = false;
spellcheck = true;
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 },
{ "autonests", LT_AUTONESTS },
{ "babelpreamble", LT_BABELPREAMBLE },
{ "bottomsep", LT_BOTTOMSEP },
{ "category", LT_CATEGORY },
{ "commanddepth", LT_COMMANDDEPTH },
{ "copystyle", LT_COPYSTYLE },
{ "dependson", LT_DEPENDSON },
{ "end", LT_END },
{ "endlabelstring", LT_ENDLABELSTRING },
{ "endlabeltype", LT_ENDLABELTYPE },
{ "font", LT_FONT },
{ "forcelocal", LT_FORCELOCAL },
{ "freespacing", LT_FREE_SPACING },
{ "htmlattr", LT_HTMLATTR },
{ "htmlforcecss", LT_HTMLFORCECSS },
{ "htmlitem", LT_HTMLITEM },
{ "htmlitemattr", LT_HTMLITEMATTR },
{ "htmllabel", LT_HTMLLABEL },
{ "htmllabelattr", LT_HTMLLABELATTR },
{ "htmllabelfirst", LT_HTMLLABELFIRST },
{ "htmlpreamble", LT_HTMLPREAMBLE },
{ "htmlstyle", LT_HTMLSTYLE },
{ "htmltag", LT_HTMLTAG },
{ "htmltitle", LT_HTMLTITLE },
{ "innertag", LT_INNERTAG },
{ "inpreamble", LT_INPREAMBLE },
{ "intitle", LT_INTITLE },
{ "isautonestedby", LT_AUTONESTEDBY },
{ "istoccaption", LT_ISTOCCAPTION },
{ "itemcommand", LT_ITEMCOMMAND },
{ "itemsep", LT_ITEMSEP },
{ "itemtag", LT_ITEMTAG },
{ "keepempty", LT_KEEPEMPTY },
{ "labelbottomsep", LT_LABEL_BOTTOMSEP },
{ "labelcounter", LT_LABELCOUNTER },
{ "labelfont", LT_LABELFONT },
{ "labelindent", LT_LABELINDENT },
{ "labelsep", LT_LABELSEP },
{ "labelstring", LT_LABELSTRING },
{ "labelstringappendix", LT_LABELSTRING_APPENDIX },
{ "labeltag", LT_LABELTAG },
{ "labeltype", LT_LABELTYPE },
{ "langpreamble", LT_LANGPREAMBLE },
{ "latexname", LT_LATEXNAME },
{ "latexparam", LT_LATEXPARAM },
{ "latextype", LT_LATEXTYPE },
{ "leftdelim", LT_LEFTDELIM },
{ "leftmargin", LT_LEFTMARGIN },
{ "margin", LT_MARGIN },
{ "needcprotect", LT_NEED_CPROTECT },
{ "needmboxprotect", LT_NEED_MBOXPROTECT },
{ "needprotect", LT_NEED_PROTECT },
{ "newline", LT_NEWLINE },
{ "nextnoindent", LT_NEXTNOINDENT },
{ "obsoletedby", LT_OBSOLETEDBY },
{ "paragraphgroup", LT_PAR_GROUP },
{ "parbreakisnewline", LT_PARBREAK_IS_NEWLINE },
{ "parindent", LT_PARINDENT },
{ "parsep", LT_PARSEP },
{ "parskip", LT_PARSKIP },
{ "passthru", LT_PASS_THRU },
2015-04-20 16:13:49 +00:00
{ "passthruchars", LT_PASS_THRU_CHARS },
{ "preamble", LT_PREAMBLE },
{ "refprefix", LT_REFPREFIX },
{ "requires", LT_REQUIRES },
{ "resetargs", LT_RESETARGS },
{ "resumecounter", LT_RESUMECOUNTER },
{ "rightdelim", LT_RIGHTDELIM },
{ "rightmargin", LT_RIGHTMARGIN },
{ "spacing", LT_SPACING },
{ "spellcheck", LT_SPELLCHECK },
{ "stepmastercounter", LT_STEPMASTERCOUNTER },
{ "textfont", LT_TEXTFONT },
{ "toclevel", LT_TOCLEVEL },
{ "toggleindent", LT_TOGGLE_INDENT },
{ "topsep", LT_TOPSEP }
};
bool error = false;
bool finished = false;
lex.pushTable(layoutTags);
// parse style section
while (!finished && lex.isOK() && !error) {
int le = lex.lex();
// See comment in LyXRC.cpp.
switch (le) {
case Lexer::LEX_FEOF:
continue;
case Lexer::LEX_UNDEF:
// parse error
lex.printError("Unknown layout tag `$$Token'");
error = true;
continue;
2017-07-03 17:53:14 +00:00
default:
break;
}
switch (static_cast<LayoutTags>(le)) {
case LT_END:
finished = true;
break;
case LT_CATEGORY:
lex >> category_;
break;
case LT_COPYSTYLE: {
docstring style;
lex >> style;
style = subst(style, '_', ' ');
if (tclass.hasLayout(style)) {
docstring const tmpname = name_;
this->operator=(tclass[style]);
name_ = tmpname;
} else {
LYXERR0("Cannot copy unknown style `"
<< style << "'\n"
<< "All layouts so far:");
DocumentClass::const_iterator lit = tclass.begin();
DocumentClass::const_iterator len = tclass.end();
for (; lit != len; ++lit)
LYXERR0(lit->name());
}
break;
}
case LT_OBSOLETEDBY: {
docstring style;
lex >> style;
style = subst(style, '_', ' ');
if (tclass.hasLayout(style)) {
docstring const tmpname = name_;
this->operator=(tclass[style]);
name_ = tmpname;
if (obsoleted_by().empty())
obsoleted_by_ = style;
} else {
2017-07-03 17:53:14 +00:00
LYXERR0("Cannot replace with unknown style `"
<< style << '\'');
//lex.printError("Cannot replace with"
// " unknown style "
// "`$$Token'");
}
break;
}
case LT_DEPENDSON:
lex >> depends_on_;
depends_on_ = subst(depends_on_, '_', ' ');
break;
case LT_MARGIN:
readMargin(lex);
break;
case LT_LATEXTYPE:
readLatexType(lex);
break;
case LT_INTITLE:
lex >> intitle;
break;
case LT_INPREAMBLE:
lex >> inpreamble;
break;
case LT_TOCLEVEL:
lex >> toclevel;
break;
case LT_RESETARGS:
bool reset;
lex >> reset;
2012-11-29 14:34:20 +00:00
if (reset) {
latexargs_.clear();
2012-11-29 14:34:20 +00:00
itemargs_.clear();
postcommandargs_.clear();
listpreamble_.clear();
2012-11-29 14:34:20 +00:00
}
break;
case LT_RESUMECOUNTER:
lex >> resumecounter;
break;
case LT_STEPMASTERCOUNTER:
lex >> stepmastercounter;
break;
case LT_ARGUMENT:
readArgument(lex);
break;
case LT_NEED_PROTECT:
lex >> needprotect;
break;
case LT_NEED_CPROTECT:
lex >> needcprotect;
break;
case LT_NEED_MBOXPROTECT:
lex >> needmboxprotect;
break;
case LT_KEEPEMPTY:
lex >> keepempty;
break;
case LT_FONT:
font = lyxRead(lex, font);
labelfont = font;
break;
case LT_TEXTFONT:
font = lyxRead(lex, font);
break;
case LT_LABELFONT:
labelfont = lyxRead(lex, labelfont);
break;
case LT_NEXTNOINDENT:
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;
case LT_LATEXNAME:
lex >> latexname_;
break;
case LT_LATEXPARAM:
lex >> latexparam_;
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;
case LT_LABELTAG:
lex >> labeltag_;
break;
case LT_ITEMTAG:
lex >> itemtag_;
break;
case LT_ITEMCOMMAND:
lex >> itemcommand_;
break;
case LT_PREAMBLE:
preamble_ = lex.getLongString(from_ascii("EndPreamble"));
break;
case LT_LANGPREAMBLE:
langpreamble_ = lex.getLongString(from_ascii("EndLangPreamble"));
break;
case LT_BABELPREAMBLE:
babelpreamble_ = lex.getLongString(from_ascii("EndBabelPreamble"));
break;
case LT_LABELTYPE:
readLabelType(lex);
break;
case LT_ENDLABELTYPE:
readEndLabelType(lex);
break;
case LT_LEFTMARGIN:
lex >> leftmargin;
break;
case LT_RIGHTMARGIN:
lex >> rightmargin;
break;
case LT_LABELINDENT:
lex >> labelindent;
break;
case LT_PARINDENT:
lex >> parindent;
break;
case LT_PARSKIP:
lex >> parskip;
break;
case LT_ITEMSEP:
lex >> itemsep;
break;
case LT_TOPSEP:
lex >> topsep;
break;
case LT_BOTTOMSEP:
lex >> bottomsep;
break;
case LT_LABEL_BOTTOMSEP:
lex >> labelbottomsep;
break;
case LT_LABELSEP:
lex >> labelsep;
labelsep = subst(labelsep, 'x', ' ');
break;
case LT_PARSEP:
lex >> parsep;
break;
case LT_NEWLINE:
lex >> newline_allowed;
break;
case LT_ALIGN:
readAlign(lex);
break;
2017-07-03 17:53:14 +00:00
case LT_ALIGNPOSSIBLE:
readAlignPossible(lex);
break;
case LT_LABELSTRING:
// FIXME: this means LT_LABELSTRING_APPENDIX may only
// occur after LT_LABELSTRING
lex >> labelstring_;
labelstring_appendix_ = labelstring_;
break;
case LT_ENDLABELSTRING:
2017-07-03 17:53:14 +00:00
lex >> endlabelstring_;
break;
case LT_LABELSTRING_APPENDIX:
2017-07-03 17:53:14 +00:00
lex >> labelstring_appendix_;
break;
case LT_LABELCOUNTER:
2017-07-03 17:53:14 +00:00
lex >> counter;
break;
case LT_PAR_GROUP:
lex >> par_group_;
break;
case LT_FREE_SPACING:
lex >> free_spacing;
break;
case LT_PASS_THRU:
lex >> pass_thru;
break;
2015-04-20 16:13:49 +00:00
case LT_PASS_THRU_CHARS:
lex >> pass_thru_chars;
break;
case LT_PARBREAK_IS_NEWLINE:
lex >> parbreak_is_newline;
break;
case LT_SPACING:
readSpacing(lex);
break;
case LT_REQUIRES: {
lex.eatLine();
vector<string> const req =
getVectorFromString(lex.getString(true));
requires_.insert(req.begin(), req.end());
break;
}
2017-07-03 17:53:14 +00:00
case LT_AUTONESTS: {
docstring autonest = lex.getLongString(from_ascii("EndAutoNests"));
autonest = subst(autonest, from_ascii("\n"), docstring());
autonest = subst(autonest, from_ascii("\t"), docstring());
autonest = subst(autonest, from_ascii("\""), docstring());
autonest = subst(autonest, '_', ' ');
vector<docstring> const autonests =
getVectorFromString(autonest, from_ascii(","), false, true);
autonests_.insert(autonests.begin(), autonests.end());
break;
}
case LT_AUTONESTEDBY: {
docstring autonest = lex.getLongString(from_ascii("EndIsAutoNestedBy"));
autonest = subst(autonest, from_ascii("\n"), docstring());
autonest = subst(autonest, from_ascii("\t"), docstring());
autonest = subst(autonest, from_ascii("\""), docstring());
autonest = subst(autonest, '_', ' ');
vector<docstring> const autonests =
getVectorFromString(autonest, from_ascii(","), false, true);
autonested_by_.insert(autonests.begin(), autonests.end());
break;
}
case LT_REFPREFIX: {
docstring arg;
lex >> arg;
if (arg == "OFF")
refprefix.clear();
else
refprefix = arg;
break;
}
case LT_HTMLTAG:
lex >> htmltag_;
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLATTR:
lex >> htmlattr_;
break;
case LT_HTMLITEM:
lex >> htmlitemtag_;
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLITEMATTR:
lex >> htmlitemattr_;
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLLABEL:
lex >> htmllabeltag_;
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLLABELATTR:
lex >> htmllabelattr_;
break;
case LT_HTMLLABELFIRST:
lex >> htmllabelfirst_;
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLSTYLE:
htmlstyle_ = lex.getLongString(from_ascii("EndHTMLStyle"));
break;
case LT_HTMLFORCECSS:
lex >> htmlforcecss_;
break;
case LT_HTMLPREAMBLE:
htmlpreamble_ = lex.getLongString(from_ascii("EndPreamble"));
break;
2017-07-03 17:53:14 +00:00
case LT_HTMLTITLE:
lex >> htmltitle_;
break;
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();
// make sure we only have inpreamble = true for commands
if (inpreamble && latextype != LATEX_COMMAND && latextype != LATEX_PARAGRAPH) {
LYXERR0("InPreamble not permitted except with command and paragraph layouts.");
LYXERR0("Layout name: " << name());
inpreamble = false;
}
return finished && !error;
}
enum {
AT_BLOCK = 1,
AT_LEFT,
AT_RIGHT,
AT_CENTER,
AT_LAYOUT
};
LexerKeyword alignTags[] = {
{ "block", AT_BLOCK },
{ "center", AT_CENTER },
{ "layout", AT_LAYOUT },
{ "left", AT_LEFT },
{ "right", AT_RIGHT }
};
void Layout::readAlign(Lexer & lex)
{
PushPopHelper pph(lex, alignTags);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown alignment `$$Token'");
return;
default: break;
};
switch (le) {
case AT_BLOCK:
align = LYX_ALIGN_BLOCK;
break;
case AT_LEFT:
align = LYX_ALIGN_LEFT;
break;
case AT_RIGHT:
align = LYX_ALIGN_RIGHT;
break;
case AT_CENTER:
align = LYX_ALIGN_CENTER;
break;
case AT_LAYOUT:
align = LYX_ALIGN_LAYOUT;
break;
}
}
void Layout::readAlignPossible(Lexer & lex)
{
lex.pushTable(alignTags);
alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
int lineno = lex.lineNumber();
do {
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown alignment `$$Token'");
continue;
default: break;
};
switch (le) {
case AT_BLOCK:
alignpossible |= LYX_ALIGN_BLOCK;
break;
case AT_LEFT:
alignpossible |= LYX_ALIGN_LEFT;
break;
case AT_RIGHT:
alignpossible |= LYX_ALIGN_RIGHT;
break;
case AT_CENTER:
alignpossible |= LYX_ALIGN_CENTER;
break;
case AT_LAYOUT:
alignpossible |= LYX_ALIGN_LAYOUT;
break;
}
} while (lineno == lex.lineNumber());
lex.popTable();
}
void Layout::readLabelType(Lexer & lex)
{
enum {
LA_NO_LABEL = 1,
LA_MANUAL,
LA_ABOVE,
LA_CENTERED,
LA_STATIC,
LA_SENSITIVE,
LA_ENUMERATE,
LA_ITEMIZE,
LA_BIBLIO
};
LexerKeyword labelTypeTags[] = {
{ "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);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown labeltype tag `$$Token'");
return;
default: break;
}
switch (le) {
case LA_NO_LABEL:
labeltype = LABEL_NO_LABEL;
break;
case LA_MANUAL:
labeltype = LABEL_MANUAL;
break;
case LA_ABOVE:
labeltype = LABEL_ABOVE;
break;
case LA_CENTERED:
labeltype = LABEL_CENTERED;
break;
case LA_STATIC:
labeltype = LABEL_STATIC;
break;
case LA_SENSITIVE:
labeltype = LABEL_SENSITIVE;
break;
case LA_ENUMERATE:
labeltype = LABEL_ENUMERATE;
break;
case LA_ITEMIZE:
labeltype = LABEL_ITEMIZE;
break;
case LA_BIBLIO:
labeltype = LABEL_BIBLIO;
break;
}
}
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 },
{ "no_label", END_LABEL_NO_LABEL },
{ "static", END_LABEL_STATIC }
};
PushPopHelper pph(lex, endlabelTypeTags);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown labeltype tag `$$Token'");
break;
case END_LABEL_STATIC:
case END_LABEL_BOX:
case END_LABEL_FILLED_BOX:
case END_LABEL_NO_LABEL:
endlabeltype = static_cast<EndLabelType>(le);
break;
default:
LYXERR0("Unhandled value " << le);
break;
}
}
void Layout::readMargin(Lexer & lex)
{
LexerKeyword marginTags[] = {
{ "dynamic", MARGIN_DYNAMIC },
{ "first_dynamic", MARGIN_FIRST_DYNAMIC },
{ "manual", MARGIN_MANUAL },
{ "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
{ "static", MARGIN_STATIC }
};
PushPopHelper pph(lex, marginTags);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown margin type tag `$$Token'");
return;
case MARGIN_STATIC:
case MARGIN_MANUAL:
case MARGIN_DYNAMIC:
case MARGIN_FIRST_DYNAMIC:
case MARGIN_RIGHT_ADDRESS_BOX:
margintype = static_cast<MarginType>(le);
break;
default:
LYXERR0("Unhandled value " << le);
break;
}
}
void Layout::readLatexType(Lexer & lex)
{
LexerKeyword latexTypeTags[] = {
{ "bib_environment", LATEX_BIB_ENVIRONMENT },
{ "command", LATEX_COMMAND },
{ "environment", LATEX_ENVIRONMENT },
{ "item_environment", LATEX_ITEM_ENVIRONMENT },
{ "list_environment", LATEX_LIST_ENVIRONMENT },
{ "paragraph", LATEX_PARAGRAPH }
};
PushPopHelper pph(lex, latexTypeTags);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown latextype tag `$$Token'");
return;
case LATEX_PARAGRAPH:
case LATEX_COMMAND:
case LATEX_ITEM_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;
}
}
void Layout::readSpacing(Lexer & lex)
{
enum {
ST_SPACING_SINGLE = 1,
ST_SPACING_ONEHALF,
ST_SPACING_DOUBLE,
ST_OTHER
};
LexerKeyword spacingTags[] = {
{"double", ST_SPACING_DOUBLE },
{"onehalf", ST_SPACING_ONEHALF },
{"other", ST_OTHER },
{"single", ST_SPACING_SINGLE }
};
PushPopHelper pph(lex, spacingTags);
int le = lex.lex();
switch (le) {
case Lexer::LEX_UNDEF:
lex.printError("Unknown spacing token `$$Token'");
return;
default: break;
}
switch (le) {
case ST_SPACING_SINGLE:
spacing.set(Spacing::Single);
break;
case ST_SPACING_ONEHALF:
spacing.set(Spacing::Onehalf);
break;
case ST_SPACING_DOUBLE:
spacing.set(Spacing::Double);
break;
case ST_OTHER:
lex.next();
spacing.set(Spacing::Other, lex.getString());
break;
}
}
void Layout::readArgument(Lexer & lex)
{
latexarg arg;
// writeArgument() makes use of these default values
arg.mandatory = false;
arg.nodelims = false;
arg.autoinsert = false;
arg.insertcotext = false;
arg.insertonnewline = false;
bool error = false;
bool finished = false;
arg.font = inherit_font;
arg.labelfont = inherit_font;
arg.is_toc_caption = false;
arg.passthru = PT_INHERITED;
2019-06-02 14:33:06 +00:00
arg.free_spacing = false;
2012-11-29 14:34:20 +00:00
string id;
lex >> id;
bool const itemarg = prefixIs(id, "item:");
bool const postcmd = prefixIs(id, "post:");
bool const listpreamble = prefixIs(id, "listpreamble:");
2012-11-29 14:34:20 +00:00
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 == "newlinecmd") {
lex.next();
arg.newlinecmd = 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 == "passthru") {
lex.next();
docstring value = lex.getDocString();
if (value == "true" || value == "1")
arg.passthru = PT_TRUE;
else if (value == "false" || value == "0")
arg.passthru = PT_FALSE;
else
arg.passthru = PT_INHERITED;
} else if (tok == "istoccaption") {
lex.next();
arg.is_toc_caption = lex.getBool();
2019-06-02 14:33:06 +00:00
} else if (tok == "freespacing") {
lex.next();
arg.free_spacing = lex.getBool();
} else {
lex.printError("Unknown tag");
error = true;
}
}
if (arg.labelstring.empty())
LYXERR0("Incomplete Argument definition!");
2012-11-29 14:34:20 +00:00
else if (itemarg)
itemargs_[id] = arg;
else if (postcmd)
postcommandargs_[id] = arg;
else if (listpreamble) {
// list preamble has no delimiters by default
arg.nodelims = true;
listpreamble_[id] = arg;
} else
2012-11-29 14:34:20 +00:00
latexargs_[id] = arg;
}
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.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.newlinecmd.empty())
os << "\t\tNewlineCmd \"" << arg.newlinecmd << "\"\n";
if (arg.font != inherit_font)
lyxWrite(os, arg.font, "Font", 2);
if (arg.labelfont != inherit_font)
lyxWrite(os, arg.labelfont, "LabelFont", 2);
switch (arg.passthru) {
case PT_TRUE:
os << "\t\tPassThru true\n";
break;
case PT_FALSE:
os << "\t\tPassThru false\n";
break;
case PT_INHERITED:
os << "\t\tPassThru inherited\n";
break;
}
2015-05-08 07:51:09 +00:00
if (!arg.pass_thru_chars.empty())
os << "\t\tPassThruChars \"" << to_utf8(arg.pass_thru_chars) << "\"\n";
2019-06-02 14:55:11 +00:00
if (arg.free_spacing)
os << "\t\tFreeSpacing " << arg.free_spacing << "\n";
os << "\tEndArgument\n";
}
void Layout::write(ostream & os) const
{
os << "Style \"" << to_utf8(name_) << "\"\n";
2013-03-31 16:17:40 +00:00
if (!category_.empty() && obsoleted_by_.empty())
os << "\tCategory \"" << to_utf8(category_) << "\"\n";
// Can't deduce Copystyle here :-(
2013-03-31 16:17:40 +00:00
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"
"\tResumeCounter " << resumecounter << "\n"
"\tStepMasterCounter " << stepmastercounter << '\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);
for (LaTeXArgMap::const_iterator it = listpreamble_.begin();
it != listpreamble_.end(); ++it)
writeArgument(os, it->first, it->second);
os << "\tNeedProtect " << needprotect << "\n"
"\tNeedCProtect " << needcprotect << "\n"
"\tNeedMBoxProtect " << needmboxprotect << "\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())
2013-03-31 16:17:40 +00:00
os << "\tLatexName \"" << latexname_ << "\"\n";
if (!latexparam_.empty())
2013-03-31 16:17:40 +00:00
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())
2013-03-31 16:17:40 +00:00
os << "\tInnerTag \"" << innertag_ << "\"\n";
if (!labeltag_.empty())
2013-03-31 16:17:40 +00:00
os << "\tLabelTag \"" << labeltag_ << "\"\n";
if (!itemtag_.empty())
2013-03-31 16:17:40 +00:00
os << "\tItemTag \"" << itemtag_ << "\"\n";
if (!itemcommand_.empty())
os << "\tItemCommand " << itemcommand_ << '\n';
if (!preamble_.empty())
2013-03-31 16:17:40 +00:00
os << "\tPreamble\n\t"
<< to_utf8(subst(rtrim(preamble_, "\n"),
from_ascii("\n"), from_ascii("\n\t")))
<< "\n\tEndPreamble\n";
if (!langpreamble_.empty())
2013-03-31 16:17:40 +00:00
os << "\tLangPreamble\n\t"
<< to_utf8(subst(rtrim(langpreamble_, "\n"),
from_ascii("\n"), from_ascii("\n\t")))
<< "\n\tEndLangPreamble\n";
if (!babelpreamble_.empty())
2013-03-31 16:17:40 +00:00
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())
2013-03-31 16:17:40 +00:00
os << "\tLeftMargin \"" << to_utf8(leftmargin) << "\"\n";
if (!rightmargin.empty())
2013-03-31 16:17:40 +00:00
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;
}
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';
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 (!autonests_.empty()) {
os << "\tAutoNests\n\t";
for (set<docstring>::const_iterator it = autonests_.begin();
it != autonests_.end(); ++it) {
if (it != autonests_.begin())
os << ',';
os << to_utf8(*it);
}
os << "\n\tEndAutoNests\n";
}
if (!autonested_by_.empty()) {
os << "\tIsAutoNestedBy\n\t\t";
for (set<docstring>::const_iterator it = autonested_by_.begin();
it != autonested_by_.end(); ++it) {
if (it != autonested_by_.begin())
os << ',';
os << to_utf8(*it);
}
os << "\n\tEndIsAutoNestedBy\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";
}
bool Layout::hasArgs() const
{
return !latexargs_.empty() || !postcommandargs_.empty() ||
!itemargs_.empty() || !listpreamble_.empty();
}
Layout::LaTeXArgMap Layout::args() const
{
LaTeXArgMap args = latexargs_;
if (!postcommandargs_.empty())
args.insert(postcommandargs_.begin(), postcommandargs_.end());
if (!listpreamble_.empty())
args.insert(listpreamble_.begin(), listpreamble_.end());
if (!itemargs_.empty())
args.insert(itemargs_.begin(), itemargs_.end());
return args;
}
int Layout::optArgs() const
{
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;
}
int Layout::requiredArgs() const
{
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;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmltag() const
{
if (htmltag_.empty())
htmltag_ = "div";
return htmltag_;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmlattr() const
{
if (htmlattr_.empty())
htmlattr_ = "class=\"" + defaultCSSClass() + "\"";
2017-07-03 17:53:14 +00:00
return htmlattr_;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmlitemtag() const
{
if (htmlitemtag_.empty())
htmlitemtag_ = "div";
2017-07-03 17:53:14 +00:00
return htmlitemtag_;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmlitemattr() const
{
if (htmlitemattr_.empty())
htmlitemattr_ = "class=\"" + defaultCSSItemClass() + "\"";
2017-07-03 17:53:14 +00:00
return htmlitemattr_;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmllabeltag() const
{
if (htmllabeltag_.empty())
htmllabeltag_ = "span";
2017-07-03 17:53:14 +00:00
return htmllabeltag_;
}
2017-07-03 17:53:14 +00:00
string const & Layout::htmllabelattr() const
{
if (htmllabelattr_.empty())
htmllabelattr_ = "class=\"" + defaultCSSLabelClass() + "\"";
2017-07-03 17:53:14 +00:00
return htmllabelattr_;
}
docstring Layout::htmlstyle() const
{
if (!htmlstyle_.empty() && !htmlforcecss_)
return htmlstyle_;
2017-07-03 17:53:14 +00:00
if (htmldefaultstyle_.empty())
makeDefaultCSS();
docstring retval = htmldefaultstyle_;
if (!htmlstyle_.empty())
retval += '\n' + htmlstyle_;
return retval;
}
string Layout::defaultCSSClass() const
2017-07-03 17:53:14 +00:00
{
if (!defaultcssclass_.empty())
return defaultcssclass_;
docstring d;
docstring::const_iterator it = name().begin();
docstring::const_iterator en = name().end();
for (; it != en; ++it) {
char_type const c = *it;
if (!isAlphaASCII(c)) {
if (d.empty())
// make sure we don't start with an underscore,
// as that sometimes causes problems.
d = from_ascii("lyx_");
else
d += '_';
} else if (isLower(c))
d += c;
else
// this is slow, so do it only if necessary
d += lowercase(c);
}
defaultcssclass_ = to_utf8(d);
return defaultcssclass_;
}
namespace {
string makeMarginValue(char const * side, double d)
{
ostringstream os;
os << "margin-" << side << ": " << d << "ex;\n";
return os.str();
}
Bulk cleanup/fix incorrect annotation at the end of namespaces. This commit does a bulk fix of incorrect annotations (comments) at the end of namespaces. The commit was generated by initially running clang-format, and then from the diff of the result extracting the hunks corresponding to fixes of namespace comments. The changes being applied and all the results have been manually reviewed. The source code successfully builds on macOS. Further details on the steps below, in case they're of interest to someone else in the future. 1. Checkout a fresh and up to date version of src/ git pull && git checkout -- src && git status src 2. Ensure there's a suitable .clang-format in place, i.e. with options to fix the comment at the end of namespaces, including: FixNamespaceComments: true SpacesBeforeTrailingComments: 1 and that clang-format is >= 5.0.0, by doing e.g.: clang-format -dump-config | grep Comments: clang-format --version 3. Apply clang-format to the source: clang-format -i $(find src -name "*.cpp" -or -name "*.h") 4. Create and filter out hunks related to fixing the namespace git diff -U0 src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace.patch 5. Filter out hunks corresponding to simple fixes into to a separate patch: pcregrep -M -e '^diff[^\n]+\nindex[^\n]+\n--- [^\n]+\n\+\+\+ [^\n]+\n' \ -e '^@@ -[0-9]+ \+[0-9]+ @@[^\n]*\n-\}[^\n]*\n\+\}[^\n]*\n' \ fix_namespace.patch > fix_namespace_simple.patch 6. Manually review the simple patch and then apply it, after first restoring the source. git checkout -- src patch -p1 < fix_namespace_simple.path 7. Manually review the (simple) changes and then stage the changes git diff src git add src 8. Again apply clang-format and filter out hunks related to any remaining fixes to the namespace, this time filter with more context. There will be fewer hunks as all the simple cases have already been handled: clang-format -i $(find src -name "*.cpp" -or -name "*.h") git diff src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace2.patch 9. Manually review/edit the resulting patch file to remove hunks for files which need to be dealt with manually, noting the file names and line numbers. Then restore files to as before applying clang-format and apply the patch: git checkout src patch -p1 < fix_namespace2.patch 10. Manually fix the files noted in the previous step. Stage files, review changes and commit.
2017-07-23 11:11:54 +00:00
} // namespace
void Layout::makeDefaultCSS() const
{
// this never needs to be redone, since reloading layouts will
// wipe out what we did before.
2017-07-03 17:53:14 +00:00
if (!htmldefaultstyle_.empty())
return;
2017-07-03 17:53:14 +00:00
// main font
htmldefaultstyle_ = font.asCSS();
2017-07-03 17:53:14 +00:00
// bottom margins
string tmp;
if (topsep > 0)
tmp += makeMarginValue("top", topsep);
if (bottomsep > 0)
tmp += makeMarginValue("bottom", bottomsep);
if (!leftmargin.empty()) {
2017-07-03 17:53:14 +00:00
// we can't really do what LyX does with the margin, so
// we'll just figure out how many characters it is
int const len = leftmargin.length();
tmp += makeMarginValue("left", len);
}
if (!rightmargin.empty()) {
int const len = rightmargin.length();
tmp += makeMarginValue("right", len);
}
2017-07-03 17:53:14 +00:00
if (!tmp.empty()) {
if (!htmldefaultstyle_.empty())
htmldefaultstyle_ += from_ascii("\n");
htmldefaultstyle_ += from_ascii(tmp);
}
// alignment
string where = alignmentToCSS(align);
if (!where.empty()) {
htmldefaultstyle_ += from_ascii("text-align: " + where + ";\n");
}
// wrap up what we have, if anything
if (!htmldefaultstyle_.empty())
2017-07-03 17:53:14 +00:00
htmldefaultstyle_ =
from_ascii(htmltag() + "." + defaultCSSClass() + " {\n") +
htmldefaultstyle_ + from_ascii("\n}\n");
2017-07-03 17:53:14 +00:00
if (labeltype == LABEL_NO_LABEL || htmllabeltag() == "NONE")
return;
2017-07-03 17:53:14 +00:00
docstring labelCSS;
2017-07-03 17:53:14 +00:00
// label font
if (labelfont != font)
labelCSS = labelfont.asCSS() + from_ascii("\n");
if (labeltype == LABEL_CENTERED)
labelCSS += from_ascii("text-align: center;\n");
2017-07-03 17:53:14 +00:00
if (!labelCSS.empty())
htmldefaultstyle_ +=
from_ascii(htmllabeltag() + "." + defaultCSSLabelClass() + " {\n") +
labelCSS + from_ascii("\n}\n");
}
bool Layout::operator==(Layout const & rhs) const
{
// This is enough for the applications we actually make,
// at least at the moment. But we could check more.
return name() == rhs.name()
&& latexname() == rhs.latexname()
&& latextype == rhs.latextype;
}
} // namespace lyx