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.
16 #include "TextClass.h"
20 #include "support/lstrings.h"
31 /// Special value of toclevel for layouts that to not belong in a TOC
32 const int Layout::NOT_IN_TOC
= -1000;
34 // The order of the LayoutTags enum is no more important. [asierra300396]
47 //LT_ENVIRONMENT_DEFAULT,
64 LT_LABELSTRING_APPENDIX
,
92 LT_INTITLE
// keep this last!
97 // Constructor for layout
100 margintype
= MARGIN_STATIC
;
101 latextype
= LATEX_PARAGRAPH
;
106 font
= Font(Font::ALL_INHERIT
);
107 labelfont
= Font(Font::ALL_INHERIT
);
108 resfont
= Font(Font::ALL_SANE
);
109 reslabelfont
= Font(Font::ALL_SANE
);
110 nextnoindent
= false;
115 labelbottomsep
= 0.0;
117 align
= LYX_ALIGN_BLOCK
;
118 alignpossible
= LYX_ALIGN_BLOCK
;
119 labeltype
= LABEL_NO_LABEL
;
120 endlabeltype
= END_LABEL_NO_LABEL
;
121 // Should or should not. That is the question.
122 // spacing.set(Spacing::OneHalf);
125 newline_allowed
= true;
126 free_spacing
= false;
128 is_environment
= false;
129 toclevel
= NOT_IN_TOC
;
134 // Reads a layout definition from file
135 bool Layout::read(Lexer
& lexrc
, TextClass
const & tclass
)
137 // This table is sorted alphabetically [asierra 30March96]
138 keyword_item layoutTags
[] = {
139 { "align", LT_ALIGN
},
140 { "alignpossible", LT_ALIGNPOSSIBLE
},
141 { "bottomsep", LT_BOTTOMSEP
},
142 { "commanddepth", LT_COMMANDDEPTH
},
143 { "copystyle", LT_COPYSTYLE
},
144 { "dependson", LT_DEPENDSON
},
146 { "endlabelstring", LT_ENDLABELSTRING
},
147 { "endlabeltype", LT_ENDLABELTYPE
},
148 { "fill_bottom", LT_FILL_BOTTOM
},
149 { "fill_top", LT_FILL_TOP
},
151 { "freespacing", LT_FREE_SPACING
},
152 { "innertag", LT_INNERTAG
},
153 { "intitle", LT_INTITLE
},
154 { "itemsep", LT_ITEMSEP
},
155 { "itemtag", LT_ITEMTAG
},
156 { "keepempty", LT_KEEPEMPTY
},
157 { "labelbottomsep", LT_LABEL_BOTTOMSEP
},
158 { "labelcounter", LT_LABELCOUNTER
},
159 { "labelfont", LT_LABELFONT
},
160 { "labelindent", LT_LABELINDENT
},
161 { "labelsep", LT_LABELSEP
},
162 { "labelstring", LT_LABELSTRING
},
163 { "labelstringappendix", LT_LABELSTRING_APPENDIX
},
164 { "labeltag", LT_LABELTAG
},
165 { "labeltype", LT_LABELTYPE
},
166 { "latexfooter", LT_LATEXFOOTER
},
167 { "latexheader", LT_LATEXHEADER
},
168 { "latexname", LT_LATEXNAME
},
169 { "latexparagraph", LT_LATEXPARAGRAPH
},
170 { "latexparam", LT_LATEXPARAM
},
171 { "latextype", LT_LATEXTYPE
},
172 { "leftmargin", LT_LEFTMARGIN
},
173 { "margin", LT_MARGIN
},
174 { "needprotect", LT_NEED_PROTECT
},
175 { "newline", LT_NEWLINE
},
176 { "nextnoindent", LT_NEXTNOINDENT
},
177 { "obsoletedby", LT_OBSOLETEDBY
},
178 { "optionalargs", LT_OPTARGS
},
179 { "parindent", LT_PARINDENT
},
180 { "parsep", LT_PARSEP
},
181 { "parskip", LT_PARSKIP
},
182 { "passthru", LT_PASS_THRU
},
183 { "preamble", LT_PREAMBLE
},
184 { "rightmargin", LT_RIGHTMARGIN
},
185 { "spacing", LT_SPACING
},
186 { "textfont", LT_TEXTFONT
},
187 { "toclevel", LT_TOCLEVEL
},
188 { "topsep", LT_TOPSEP
}
192 bool finished
= false;
193 lexrc
.pushTable(layoutTags
, LT_INTITLE
);
194 // parse style section
195 while (!finished
&& lexrc
.isOK() && !error
) {
196 int le
= lexrc
.lex();
197 // See comment in LyXRC.cpp.
199 case Lexer::LEX_FEOF
:
202 case Lexer::LEX_UNDEF
: // parse error
203 lexrc
.printError("Unknown layout tag `$$Token'");
208 switch (static_cast<LayoutTags
>(le
)) {
209 case LT_END
: // end of structure
213 case LT_COPYSTYLE
: // initialize with a known style
215 docstring
const style
= subst(lexrc
.getDocString(),
218 if (tclass
.hasLayout(style
)) {
219 docstring
const tmpname
= name_
;
220 this->operator=(*tclass
[style
]);
223 lyxerr
<< "Cannot copy unknown style `"
224 << to_utf8(style
) << "'\n"
225 << "All layouts so far:"
227 TextClass::const_iterator it
=
229 TextClass::const_iterator end
=
231 for (; it
!= end
; ++it
) {
232 lyxerr
<< to_utf8((*it
)->name())
236 //lexrc.printError("Cannot copy known "
237 // "style `$$Token'");
242 case LT_OBSOLETEDBY
: // replace with a known style
244 docstring
const style
=
245 subst(lexrc
.getDocString(), '_', ' ');
247 if (tclass
.hasLayout(style
)) {
248 docstring
const tmpname
= name_
;
249 this->operator=(*tclass
[style
]);
251 if (obsoleted_by().empty())
252 obsoleted_by_
= style
;
254 lyxerr
<< "Cannot replace with unknown style `"
255 << to_utf8(style
) << '\'' << endl
;
257 //lexrc.printError("Cannot replace with"
266 depends_on_
= subst(lexrc
.getDocString(), '_', ' ');
269 case LT_MARGIN
: // margin style definition.
273 case LT_LATEXTYPE
: // LaTeX style definition.
274 readLatexType(lexrc
);
277 case LT_LATEXHEADER
: // header for environments
279 latexheader
= lexrc
.getString();
282 case LT_LATEXFOOTER
: // footer for environments
284 latexfooter
= lexrc
.getString();
287 case LT_LATEXPARAGRAPH
:
289 latexparagraph
= lexrc
.getString();
293 intitle
= lexrc
.next() && lexrc
.getInteger();
298 toclevel
= lexrc
.getInteger();
303 optionalargs
= lexrc
.getInteger();
306 case LT_NEED_PROTECT
:
307 needprotect
= lexrc
.next() && lexrc
.getInteger();
311 keepempty
= lexrc
.next() && lexrc
.getInteger();
324 labelfont
.lyxRead(lexrc
);
327 case LT_NEXTNOINDENT
: // Indent next paragraph?
328 if (lexrc
.next() && lexrc
.getInteger())
331 nextnoindent
= false;
334 case LT_COMMANDDEPTH
:
336 commanddepth
= lexrc
.getInteger();
341 latexname_
= lexrc
.getString();
346 latexparam_
= subst(lexrc
.getString(), """, "\"");
351 innertag_
= lexrc
.getString();
356 labeltag_
= lexrc
.getString();
361 itemtag_
= lexrc
.getString();
365 preamble_
= from_utf8(lexrc
.getLongString("EndPreamble"));
369 readLabelType(lexrc
);
372 case LT_ENDLABELTYPE
:
373 readEndLabelType(lexrc
);
376 case LT_LEFTMARGIN
: // left margin type
378 leftmargin
= lexrc
.getString();
381 case LT_RIGHTMARGIN
: // right margin type
383 rightmargin
= lexrc
.getString();
386 case LT_LABELINDENT
: // label indenting flag
388 labelindent
= lexrc
.getString();
391 case LT_PARINDENT
: // paragraph indent. flag
393 parindent
= lexrc
.getString();
396 case LT_PARSKIP
: // paragraph skip size
398 parskip
= lexrc
.getFloat();
401 case LT_ITEMSEP
: // item separation size
403 itemsep
= lexrc
.getFloat();
406 case LT_TOPSEP
: // top separation size
408 topsep
= lexrc
.getFloat();
411 case LT_BOTTOMSEP
: // bottom separation size
413 bottomsep
= lexrc
.getFloat();
416 case LT_LABEL_BOTTOMSEP
: // label bottom separation size
418 labelbottomsep
= lexrc
.getFloat();
421 case LT_LABELSEP
: // label separator
423 labelsep
= subst(lexrc
.getString(), 'x', ' ');
427 case LT_PARSEP
: // par. separation size
429 parsep
= lexrc
.getFloat();
432 case LT_FILL_TOP
: // fill top flag
434 fill_top
= lexrc
.getInteger();
437 case LT_FILL_BOTTOM
: // fill bottom flag
439 fill_bottom
= lexrc
.getInteger();
442 case LT_NEWLINE
: // newlines allowed?
444 newline_allowed
= lexrc
.getInteger();
447 case LT_ALIGN
: // paragraph align
450 case LT_ALIGNPOSSIBLE
: // paragraph allowed align
451 readAlignPossible(lexrc
);
454 case LT_LABELSTRING
: // label string definition
456 labelstring_
= trim(lexrc
.getDocString());
457 labelstring_appendix_
= labelstring_
;
461 case LT_ENDLABELSTRING
: // endlabel string definition
463 endlabelstring_
= trim(lexrc
.getDocString());
466 case LT_LABELSTRING_APPENDIX
: // label string appendix definition
468 labelstring_appendix_
= trim(lexrc
.getDocString());
471 case LT_LABELCOUNTER
: // name of counter to use
473 counter
= lyx::from_ascii(trim(lexrc
.getString()));
476 case LT_FREE_SPACING
: // Allow for free spacing.
478 free_spacing
= lexrc
.getInteger();
481 case LT_PASS_THRU
: // Allow for pass thru.
483 pass_thru
= lexrc
.getInteger();
486 case LT_SPACING
: // setspace.sty
506 void Layout::readAlign(Lexer
& lexrc
)
508 keyword_item alignTags
[] = {
509 { "block", AT_BLOCK
},
510 { "center", AT_CENTER
},
511 { "layout", AT_LAYOUT
},
513 { "right", AT_RIGHT
}
516 PushPopHelper
pph(lexrc
, alignTags
, AT_LAYOUT
);
517 int le
= lexrc
.lex();
519 case Lexer::LEX_UNDEF
:
520 lexrc
.printError("Unknown alignment `$$Token'");
524 switch (static_cast<AlignTags
>(le
)) {
526 align
= LYX_ALIGN_BLOCK
;
529 align
= LYX_ALIGN_LEFT
;
532 align
= LYX_ALIGN_RIGHT
;
535 align
= LYX_ALIGN_CENTER
;
538 align
= LYX_ALIGN_LAYOUT
;
544 void Layout::readAlignPossible(Lexer
& lexrc
)
546 keyword_item alignTags
[] = {
547 { "block", AT_BLOCK
},
548 { "center", AT_CENTER
},
549 { "layout", AT_LAYOUT
},
551 { "right", AT_RIGHT
}
554 lexrc
.pushTable(alignTags
, AT_LAYOUT
);
555 alignpossible
= LYX_ALIGN_NONE
;
556 int lineno
= lexrc
.getLineNo();
558 int le
= lexrc
.lex();
560 case Lexer::LEX_UNDEF
:
561 lexrc
.printError("Unknown alignment `$$Token'");
565 switch (static_cast<AlignTags
>(le
)) {
567 alignpossible
|= LYX_ALIGN_BLOCK
;
570 alignpossible
|= LYX_ALIGN_LEFT
;
573 alignpossible
|= LYX_ALIGN_RIGHT
;
576 alignpossible
|= LYX_ALIGN_CENTER
;
579 alignpossible
|= LYX_ALIGN_LAYOUT
;
582 } while (lineno
== lexrc
.getLineNo());
591 LA_CENTERED_TOP_ENVIRONMENT
,
601 void Layout::readLabelType(Lexer
& lexrc
)
603 keyword_item labelTypeTags
[] = {
604 { "bibliography", LA_BIBLIO
},
605 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT
},
606 { "counter", LA_COUNTER
},
607 { "enumerate", LA_ENUMERATE
},
608 { "itemize", LA_ITEMIZE
},
609 { "manual", LA_MANUAL
},
610 { "no_label", LA_NO_LABEL
},
611 { "sensitive", LA_SENSITIVE
},
612 { "static", LA_STATIC
},
613 { "top_environment", LA_TOP_ENVIRONMENT
}
616 PushPopHelper
pph(lexrc
, labelTypeTags
, LA_BIBLIO
);
617 int le
= lexrc
.lex();
619 case Lexer::LEX_UNDEF
:
620 lexrc
.printError("Unknown labeltype tag `$$Token'");
624 switch (static_cast<LabelTypeTags
>(le
)) {
626 labeltype
= LABEL_NO_LABEL
;
629 labeltype
= LABEL_MANUAL
;
631 case LA_TOP_ENVIRONMENT
:
632 labeltype
= LABEL_TOP_ENVIRONMENT
;
634 case LA_CENTERED_TOP_ENVIRONMENT
:
635 labeltype
= LABEL_CENTERED_TOP_ENVIRONMENT
;
638 labeltype
= LABEL_STATIC
;
641 labeltype
= LABEL_SENSITIVE
;
644 labeltype
= LABEL_COUNTER
;
647 labeltype
= LABEL_ENUMERATE
;
650 labeltype
= LABEL_ITEMIZE
;
653 labeltype
= LABEL_BIBLIO
;
661 keyword_item endlabelTypeTags
[] = {
662 { "box", END_LABEL_BOX
},
663 { "filled_box", END_LABEL_FILLED_BOX
},
664 { "no_label", END_LABEL_NO_LABEL
},
665 { "static", END_LABEL_STATIC
}
671 void Layout::readEndLabelType(Lexer
& lexrc
)
673 PushPopHelper
pph(lexrc
, endlabelTypeTags
,
674 END_LABEL_ENUM_LAST
-END_LABEL_ENUM_FIRST
+1);
675 int le
= lexrc
.lex();
677 case Lexer::LEX_UNDEF
:
678 lexrc
.printError("Unknown labeltype tag `$$Token'");
680 case END_LABEL_STATIC
:
682 case END_LABEL_FILLED_BOX
:
683 case END_LABEL_NO_LABEL
:
684 endlabeltype
= static_cast<LYX_END_LABEL_TYPES
>(le
);
687 lyxerr
<< "Unhandled value " << le
688 << " in Layout::readEndLabelType." << endl
;
694 void Layout::readMargin(Lexer
& lexrc
)
696 keyword_item marginTags
[] = {
697 { "dynamic", MARGIN_DYNAMIC
},
698 { "first_dynamic", MARGIN_FIRST_DYNAMIC
},
699 { "manual", MARGIN_MANUAL
},
700 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX
},
701 { "static", MARGIN_STATIC
}
704 PushPopHelper
pph(lexrc
, marginTags
, MARGIN_RIGHT_ADDRESS_BOX
);
706 int le
= lexrc
.lex();
708 case Lexer::LEX_UNDEF
:
709 lexrc
.printError("Unknown margin type tag `$$Token'");
714 case MARGIN_FIRST_DYNAMIC
:
715 case MARGIN_RIGHT_ADDRESS_BOX
:
716 margintype
= static_cast<LYX_MARGIN_TYPE
>(le
);
719 lyxerr
<< "Unhandled value " << le
720 << " in Layout::readMargin." << endl
;
726 void Layout::readLatexType(Lexer
& lexrc
)
728 keyword_item latexTypeTags
[] = {
729 { "bib_environment", LATEX_BIB_ENVIRONMENT
},
730 { "command", LATEX_COMMAND
},
731 { "environment", LATEX_ENVIRONMENT
},
732 { "item_environment", LATEX_ITEM_ENVIRONMENT
},
733 { "list_environment", LATEX_LIST_ENVIRONMENT
},
734 { "paragraph", LATEX_PARAGRAPH
}
737 PushPopHelper
pph(lexrc
, latexTypeTags
, LATEX_LIST_ENVIRONMENT
);
738 int le
= lexrc
.lex();
740 case Lexer::LEX_UNDEF
:
741 lexrc
.printError("Unknown latextype tag `$$Token'");
743 case LATEX_PARAGRAPH
:
745 case LATEX_ENVIRONMENT
:
746 case LATEX_ITEM_ENVIRONMENT
:
747 case LATEX_BIB_ENVIRONMENT
:
748 case LATEX_LIST_ENVIRONMENT
:
749 latextype
= static_cast<LYX_LATEX_TYPES
>(le
);
752 lyxerr
<< "Unhandled value " << le
753 << " in Layout::readLatexType." << endl
;
760 ST_SPACING_SINGLE
= 1,
767 void Layout::readSpacing(Lexer
& lexrc
)
769 keyword_item spacingTags
[] = {
770 {"double", ST_SPACING_DOUBLE
},
771 {"onehalf", ST_SPACING_ONEHALF
},
772 {"other", ST_OTHER
},
773 {"single", ST_SPACING_SINGLE
}
776 PushPopHelper
pph(lexrc
, spacingTags
, ST_OTHER
);
777 int le
= lexrc
.lex();
779 case Lexer::LEX_UNDEF
:
780 lexrc
.printError("Unknown spacing token `$$Token'");
784 switch (static_cast<SpacingTags
>(le
)) {
785 case ST_SPACING_SINGLE
:
786 spacing
.set(Spacing::Single
);
788 case ST_SPACING_ONEHALF
:
789 spacing
.set(Spacing::Onehalf
);
791 case ST_SPACING_DOUBLE
:
792 spacing
.set(Spacing::Double
);
796 spacing
.set(Spacing::Other
, lexrc
.getString());
802 docstring
const & Layout::name() const
808 void Layout::setName(docstring
const & n
)
814 docstring
const & Layout::obsoleted_by() const
816 return obsoleted_by_
;
820 docstring
const & Layout::depends_on() const
826 Layout
* Layout::forCaption()
828 Layout
* lay
= new Layout();
829 lay
->name_
= from_ascii("Caption");
830 lay
->latexname_
= "caption";
831 lay
->latextype
= LATEX_COMMAND
;
832 lay
->optionalargs
= 1;