]> git.lyx.org Git - lyx.git/blob - src/Layout.cpp
DocBook: add DocBookSection parameter for styles that define new sections and impleme...
[lyx.git] / src / Layout.cpp
1 /**
2  * \file Layout.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Jean-Marc Lasgouttes
8  * \author André Pönitz
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "Layout.h"
16 #include "FontInfo.h"
17 #include "Language.h"
18 #include "Lexer.h"
19 #include "output_xhtml.h"
20 #include "TextClass.h"
21
22 #include "support/debug.h"
23 #include "support/docstream.h"
24 #include "support/lassert.h"
25 #include "support/lstrings.h"
26 #include "support/Messages.h"
27 #include "support/textutils.h"
28
29
30 using namespace std;
31 using namespace lyx::support;
32
33 namespace lyx {
34
35 /// Special value of toclevel for layouts that do not belong to a TOC
36 const int Layout::NOT_IN_TOC = -1000;
37
38 //  The order of the LayoutTags enum is no more important. [asierra300396]
39 // Tags indexes.
40 enum LayoutTags {
41         LT_ALIGN = 1,
42         LT_ALIGNPOSSIBLE,
43         LT_ARGUMENT,
44         LT_AUTONESTS,
45         LT_AUTONESTEDBY,
46         LT_MARGIN,
47         LT_BOTTOMSEP,
48         LT_CATEGORY,
49         LT_COMMANDDEPTH,
50         LT_COPYSTYLE,
51         LT_DEPENDSON,
52         LT_OBSOLETEDBY,
53         LT_END,
54         LT_FONT,
55         LT_FREE_SPACING,
56         LT_PASS_THRU,
57         LT_PASS_THRU_CHARS,
58         LT_PARBREAK_IS_NEWLINE,
59         LT_ITEMCOMMAND,
60         LT_ITEMSEP,
61         LT_KEEPEMPTY,
62         LT_LABEL_BOTTOMSEP,
63         LT_LABELFONT,
64         LT_TEXTFONT,
65         LT_LABELINDENT,
66         LT_LABELSEP,
67         LT_LABELSTRING,
68         LT_LABELSTRING_APPENDIX,
69         LT_LABELCOUNTER,
70         LT_LABELTYPE,
71         LT_ENDLABELSTRING,
72         LT_ENDLABELTYPE,
73         LT_LATEXNAME,
74         LT_LATEXPARAM,
75         LT_LATEXTYPE,
76         LT_LEFTDELIM,
77         LT_LEFTMARGIN,
78         LT_NEED_CPROTECT,
79         LT_NEED_MBOXPROTECT,
80         LT_NEED_PROTECT,
81         LT_NEWLINE,
82         LT_NEXTNOINDENT,
83         LT_PAR_GROUP,
84         LT_PARINDENT,
85         LT_PARSEP,
86         LT_PARSKIP,
87         LT_PREAMBLE,
88         LT_LANGPREAMBLE,
89         LT_BABELPREAMBLE,
90         LT_REQUIRES,
91         LT_RIGHTMARGIN,
92         LT_SPACING,
93         LT_TOPSEP,
94         LT_TOCLEVEL,
95         LT_INNERTAG,
96         LT_LABELTAG,
97         LT_ITEMTAG,
98         LT_HTMLTAG,
99         LT_HTMLATTR,
100         LT_HTMLITEM,
101         LT_HTMLITEMATTR,
102         LT_HTMLLABEL,
103         LT_HTMLLABELATTR,
104         LT_HTMLLABELFIRST,
105         LT_HTMLPREAMBLE,
106         LT_HTMLSTYLE,
107         LT_HTMLFORCECSS,
108         LT_DOCBOOKTAG,
109         LT_DOCBOOKATTR,
110         LT_DOCBOOKTAGTYPE,
111         LT_DOCBOOKINNERATTR,
112         LT_DOCBOOKINNERTAG,
113         LT_DOCBOOKINNERTAGTYPE,
114         LT_DOCBOOKININFO,
115         LT_DOCBOOKABSTRACT,
116         LT_DOCBOOKWRAPPERTAG,
117         LT_DOCBOOKWRAPPERATTR,
118         LT_DOCBOOKWRAPPERTAGTYPE,
119         LT_DOCBOOKWRAPPERMERGEWITHPREVIOUS,
120         LT_DOCBOOKSECTION,
121         LT_DOCBOOKSECTIONTAG,
122         LT_DOCBOOKITEMWRAPPERTAG,
123         LT_DOCBOOKITEMWRAPPERATTR,
124         LT_DOCBOOKITEMWRAPPERTAGTYPE,
125         LT_DOCBOOKITEMTAG,
126         LT_DOCBOOKITEMATTR,
127         LT_DOCBOOKITEMTAGTYPE,
128         LT_DOCBOOKITEMLABELTAG,
129         LT_DOCBOOKITEMLABELATTR,
130         LT_DOCBOOKITEMLABELTAGTYPE,
131         LT_DOCBOOKITEMINNERTAG,
132         LT_DOCBOOKITEMINNERATTR,
133         LT_DOCBOOKITEMINNERTAGTYPE,
134         LT_DOCBOOKFORCEABSTRACTTAG,
135         LT_INPREAMBLE,
136         LT_HTMLTITLE,
137         LT_SPELLCHECK,
138         LT_REFPREFIX,
139         LT_RESETARGS,
140         LT_RESUMECOUNTER,
141         LT_STEPMASTERCOUNTER,
142         LT_RIGHTDELIM,
143         LT_FORCELOCAL,
144         LT_TOGGLE_INDENT,
145         LT_ADDTOTOC,
146         LT_ISTOCCAPTION,
147         LT_INTITLE // keep this last!
148 };
149
150 /////////////////////
151
152 Layout::Layout()
153         : add_to_toc_(false), is_toc_caption_(true)
154 {
155         unknown_ = false;
156         margintype = MARGIN_STATIC;
157         latextype = LATEX_PARAGRAPH;
158         resumecounter = false;
159         stepmastercounter = false;
160         intitle = false;
161         inpreamble = false;
162         needprotect = false;
163         needcprotect = false;
164         needmboxprotect = false;
165         keepempty = false;
166         font = inherit_font;
167         labelfont = inherit_font;
168         resfont = sane_font;
169         reslabelfont = sane_font;
170         nextnoindent = false;
171         parskip = 0.0;
172         itemsep = 0;
173         topsep = 0.0;
174         bottomsep = 0.0;
175         labelbottomsep = 0.0;
176         parsep = 0;
177         align = LYX_ALIGN_BLOCK;
178         alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
179         labeltype = LABEL_NO_LABEL;
180         endlabeltype = END_LABEL_NO_LABEL;
181         // Should or should not. That is the question.
182         // spacing.set(Spacing::OneHalf);
183         newline_allowed = true;
184         free_spacing = false;
185         pass_thru = false;
186         parbreak_is_newline = false;
187         toclevel = NOT_IN_TOC;
188         commanddepth = 0;
189         htmllabelfirst_ = false;
190         htmlforcecss_ = false;
191         htmltitle_ = false;
192         docbookabstract_ = false;
193         docbookwrappermergewithprevious_ = false;
194         docbooksection_ = false;
195         spellcheck = true;
196         forcelocal = 0;
197         itemcommand_ = "item";
198         toggle_indent = ITOGGLE_DOCUMENT_DEFAULT;
199         par_group_ = false;
200 }
201
202
203 bool Layout::read(Lexer & lex, TextClass const & tclass, bool validating)
204 {
205         // If this is an empty layout, or if no force local version is set,
206         // we know that we will not discard the stuff to read
207         if (forcelocal == 0)
208                 return readIgnoreForcelocal(lex, tclass, validating);
209         Layout tmp(*this);
210         tmp.forcelocal = 0;
211         bool const ret = tmp.readIgnoreForcelocal(lex, tclass, validating);
212         // Keep the stuff if
213         // - the read version is higher
214         // - both versions are infinity (arbitrary decision)
215         // - the file did not contain any local version (needed for not
216         //   skipping user defined local layouts)
217         if (tmp.forcelocal <= 0 || tmp.forcelocal > forcelocal)
218                 *this = tmp;
219         return ret;
220 }
221
222
223 bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass,
224                                                                   bool validating)
225 {
226         // This table is sorted alphabetically [asierra 30March96]
227         LexerKeyword layoutTags[] = {
228                 { "addtotoc",       LT_ADDTOTOC },
229                 { "align",          LT_ALIGN },
230                 { "alignpossible",  LT_ALIGNPOSSIBLE },
231                 { "argument",       LT_ARGUMENT },
232                 { "autonests",      LT_AUTONESTS },
233                 { "babelpreamble",  LT_BABELPREAMBLE },
234                 { "bottomsep",      LT_BOTTOMSEP },
235                 { "category",       LT_CATEGORY },
236                 { "commanddepth",   LT_COMMANDDEPTH },
237                 { "copystyle",      LT_COPYSTYLE },
238                 { "dependson",      LT_DEPENDSON },
239                 { "docbookabstract",           LT_DOCBOOKABSTRACT },
240                 { "docbookattr",               LT_DOCBOOKATTR },
241                 { "docbookforceabstracttag",   LT_DOCBOOKFORCEABSTRACTTAG },
242                 { "docbookininfo",             LT_DOCBOOKININFO },
243                 { "docbookinnerattr",          LT_DOCBOOKINNERATTR },
244                 { "docbookinnertag",           LT_DOCBOOKINNERTAG },
245                 { "docbookinnertagtype",       LT_DOCBOOKINNERTAGTYPE },
246                 { "docbookitemattr",           LT_DOCBOOKITEMATTR },
247                 { "docbookiteminnerattr",      LT_DOCBOOKITEMINNERATTR },
248                 { "docbookiteminnertag",       LT_DOCBOOKITEMINNERTAG },
249                 { "docbookiteminnertagtype",   LT_DOCBOOKITEMINNERTAGTYPE },
250                 { "docbookitemlabelattr",      LT_DOCBOOKITEMLABELATTR },
251                 { "docbookitemlabeltag",       LT_DOCBOOKITEMLABELTAG },
252                 { "docbookitemlabeltagtype",   LT_DOCBOOKITEMLABELTAGTYPE },
253                 { "docbookitemtag",            LT_DOCBOOKITEMTAG },
254                 { "docbookitemtagtype",        LT_DOCBOOKITEMTAGTYPE },
255                 { "docbookitemwrapperattr",    LT_DOCBOOKITEMWRAPPERATTR },
256                 { "docbookitemwrappertag",     LT_DOCBOOKITEMWRAPPERTAG },
257                 { "docbookitemwrappertagtype", LT_DOCBOOKITEMWRAPPERTAGTYPE },
258                 { "docbooksection",            LT_DOCBOOKSECTION },
259                 { "docbooksectiontag",         LT_DOCBOOKSECTIONTAG },
260                 { "docbooktag",                LT_DOCBOOKTAG },
261                 { "docbooktagtype",            LT_DOCBOOKTAGTYPE },
262                 { "docbookwrapperattr",        LT_DOCBOOKWRAPPERATTR },
263                 { "docbookwrappermergewithprevious", LT_DOCBOOKWRAPPERMERGEWITHPREVIOUS },
264                 { "docbookwrappertag",         LT_DOCBOOKWRAPPERTAG },
265                 { "docbookwrappertagtype",     LT_DOCBOOKWRAPPERTAGTYPE },
266                 { "end",            LT_END },
267                 { "endlabelstring", LT_ENDLABELSTRING },
268                 { "endlabeltype",   LT_ENDLABELTYPE },
269                 { "font",           LT_FONT },
270                 { "forcelocal",     LT_FORCELOCAL },
271                 { "freespacing",    LT_FREE_SPACING },
272                 { "htmlattr",       LT_HTMLATTR },
273                 { "htmlforcecss",   LT_HTMLFORCECSS },
274                 { "htmlitem",       LT_HTMLITEM },
275                 { "htmlitemattr",   LT_HTMLITEMATTR },
276                 { "htmllabel",      LT_HTMLLABEL },
277                 { "htmllabelattr",  LT_HTMLLABELATTR },
278                 { "htmllabelfirst", LT_HTMLLABELFIRST },
279                 { "htmlpreamble",   LT_HTMLPREAMBLE },
280                 { "htmlstyle",      LT_HTMLSTYLE },
281                 { "htmltag",        LT_HTMLTAG },
282                 { "htmltitle",      LT_HTMLTITLE },
283                 { "innertag",       LT_INNERTAG },
284                 { "inpreamble",     LT_INPREAMBLE },
285                 { "intitle",        LT_INTITLE },
286                 { "isautonestedby", LT_AUTONESTEDBY },
287                 { "istoccaption",   LT_ISTOCCAPTION },
288                 { "itemcommand",    LT_ITEMCOMMAND },
289                 { "itemsep",        LT_ITEMSEP },
290                 { "itemtag",        LT_ITEMTAG },
291                 { "keepempty",      LT_KEEPEMPTY },
292                 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
293                 { "labelcounter",   LT_LABELCOUNTER },
294                 { "labelfont",      LT_LABELFONT },
295                 { "labelindent",    LT_LABELINDENT },
296                 { "labelsep",       LT_LABELSEP },
297                 { "labelstring",    LT_LABELSTRING },
298                 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
299                 { "labeltag",       LT_LABELTAG },
300                 { "labeltype",      LT_LABELTYPE },
301                 { "langpreamble",   LT_LANGPREAMBLE },
302                 { "latexname",      LT_LATEXNAME },
303                 { "latexparam",     LT_LATEXPARAM },
304                 { "latextype",      LT_LATEXTYPE },
305                 { "leftdelim",      LT_LEFTDELIM },
306                 { "leftmargin",     LT_LEFTMARGIN },
307                 { "margin",         LT_MARGIN },
308                 { "needcprotect",    LT_NEED_CPROTECT },
309                 { "needmboxprotect", LT_NEED_MBOXPROTECT },
310                 { "needprotect",    LT_NEED_PROTECT },
311                 { "newline",        LT_NEWLINE },
312                 { "nextnoindent",   LT_NEXTNOINDENT },
313                 { "obsoletedby",    LT_OBSOLETEDBY },
314                 { "paragraphgroup", LT_PAR_GROUP },
315                 { "parbreakisnewline", LT_PARBREAK_IS_NEWLINE },
316                 { "parindent",      LT_PARINDENT },
317                 { "parsep",         LT_PARSEP },
318                 { "parskip",        LT_PARSKIP },
319                 { "passthru",       LT_PASS_THRU },
320                 { "passthruchars",  LT_PASS_THRU_CHARS },
321                 { "preamble",       LT_PREAMBLE },
322                 { "refprefix",      LT_REFPREFIX },
323                 { "requires",       LT_REQUIRES },
324                 { "resetargs",      LT_RESETARGS },
325                 { "resumecounter",  LT_RESUMECOUNTER },
326                 { "rightdelim",     LT_RIGHTDELIM },
327                 { "rightmargin",    LT_RIGHTMARGIN },
328                 { "spacing",        LT_SPACING },
329                 { "spellcheck",     LT_SPELLCHECK },
330                 { "stepmastercounter",  LT_STEPMASTERCOUNTER },
331                 { "textfont",       LT_TEXTFONT },
332                 { "toclevel",       LT_TOCLEVEL },
333                 { "toggleindent",   LT_TOGGLE_INDENT },
334                 { "topsep",         LT_TOPSEP }
335         };
336
337         bool error = false;
338         bool finished = false;
339         lex.pushTable(layoutTags);
340
341         // parse style section
342         while (!finished && lex.isOK() && !error) {
343                 int le = lex.lex();
344                 // See comment in LyXRC.cpp.
345                 switch (le) {
346                 case Lexer::LEX_FEOF:
347                         continue;
348
349                 case Lexer::LEX_UNDEF:
350                         // parse error
351                         lex.printError("Unknown layout tag `$$Token'");
352                         error = true;
353                         continue;
354
355                 default:
356                         break;
357                 }
358                 switch (static_cast<LayoutTags>(le)) {
359                 case LT_END:
360                         finished = true;
361                         break;
362
363                 case LT_CATEGORY:
364                         lex >> category_;
365                         break;
366
367                 case LT_COPYSTYLE: {
368                         docstring style;
369                         lex >> style;
370                         style = subst(style, '_', ' ');
371
372                         if (tclass.hasLayout(style)) {
373                                 docstring const tmpname = name_;
374                                 this->operator=(tclass[style]);
375                                 name_ = tmpname;
376                         } else {
377                                 LYXERR0("Cannot copy unknown style `"
378                                         << style << "'\n"
379                                         << "All layouts so far:");
380                                 DocumentClass::const_iterator lit = tclass.begin();
381                                 DocumentClass::const_iterator len = tclass.end();
382                                 for (; lit != len; ++lit)
383                                         LYXERR0(lit->name());
384                         }
385                         break;
386                         }
387
388                 case LT_OBSOLETEDBY: {
389                         docstring style;
390                         lex >> style;
391                         style = subst(style, '_', ' ');
392
393                         if (tclass.hasLayout(style)) {
394                                 docstring const tmpname = name_;
395                                 this->operator=(tclass[style]);
396                                 name_ = tmpname;
397                                 if (obsoleted_by().empty())
398                                         obsoleted_by_ = style;
399                         } else {
400                                 LYXERR0("Cannot replace with unknown style `"
401                                         << style << '\'');
402
403                                 //lex.printError("Cannot replace with"
404                                 //               " unknown style "
405                                 //               "`$$Token'");
406                         }
407                         break;
408                 }
409
410                 case LT_DEPENDSON:
411                         lex >> depends_on_;
412                         depends_on_ = subst(depends_on_, '_', ' ');
413                         break;
414
415                 case LT_MARGIN:
416                         readMargin(lex);
417                         break;
418
419                 case LT_LATEXTYPE:
420                         readLatexType(lex);
421                         break;
422
423                 case LT_INTITLE:
424                         lex >> intitle;
425                         break;
426
427                 case LT_INPREAMBLE:
428                         lex >> inpreamble;
429                         break;
430
431                 case LT_TOCLEVEL:
432                         lex >> toclevel;
433                         break;
434
435                 case LT_RESETARGS:
436                         bool reset;
437                         lex >> reset;
438                         if (reset) {
439                                 latexargs_.clear();
440                                 itemargs_.clear();
441                                 postcommandargs_.clear();
442                                 listpreamble_.clear();
443                         }
444                         break;
445
446                 case LT_RESUMECOUNTER:
447                         lex >> resumecounter;
448                         break;
449
450                 case LT_STEPMASTERCOUNTER:
451                         lex >> stepmastercounter;
452                         break;
453
454                 case LT_ARGUMENT:
455                         readArgument(lex, validating);
456                         break;
457
458                 case LT_NEED_PROTECT:
459                         lex >> needprotect;
460                         break;
461
462                 case LT_NEED_CPROTECT:
463                         lex >> needcprotect;
464                         break;
465
466                 case LT_NEED_MBOXPROTECT:
467                         lex >> needmboxprotect;
468                         break;
469
470                 case LT_KEEPEMPTY:
471                         lex >> keepempty;
472                         break;
473
474                 case LT_FONT:
475                         font = lyxRead(lex, font);
476                         labelfont = font;
477                         break;
478
479                 case LT_TEXTFONT:
480                         font = lyxRead(lex, font);
481                         break;
482
483                 case LT_LABELFONT:
484                         labelfont = lyxRead(lex, labelfont);
485                         break;
486
487                 case LT_NEXTNOINDENT:
488                         lex >> nextnoindent;
489                         break;
490
491                 case LT_TOGGLE_INDENT: {
492                         string tog;
493                         lex >> tog;
494                         tog = support::ascii_lowercase(tog);
495                         if (tog == "always")
496                                 toggle_indent = ITOGGLE_ALWAYS;
497                         else if (tog == "never")
498                                 toggle_indent = ITOGGLE_NEVER;
499                         else
500                                 toggle_indent = ITOGGLE_DOCUMENT_DEFAULT;
501                         break;
502                 }
503
504                 case LT_COMMANDDEPTH:
505                         lex >> commanddepth;
506                         break;
507
508                 case LT_LATEXNAME:
509                         lex >> latexname_;
510                         break;
511
512                 case LT_LATEXPARAM:
513                         lex >> latexparam_;
514                         latexparam_ = subst(latexparam_, "&quot;", "\"");
515                         break;
516
517                 case LT_LEFTDELIM:
518                         lex >> leftdelim_;
519                         leftdelim_ = support::subst(leftdelim_, from_ascii("<br/>"),
520                                                     from_ascii("\n"));
521                         break;
522
523                 case LT_RIGHTDELIM:
524                         lex >> rightdelim_;
525                         rightdelim_ = support::subst(rightdelim_, from_ascii("<br/>"),
526                                                      from_ascii("\n"));
527                         break;
528
529                 case LT_INNERTAG:
530                         lex >> innertag_;
531                         break;
532
533                 case LT_LABELTAG:
534                         lex >> labeltag_;
535                         break;
536
537                 case LT_ITEMTAG:
538                         lex >> itemtag_;
539                         break;
540
541                 case LT_ITEMCOMMAND:
542                         lex >> itemcommand_;
543                         break;
544
545                 case LT_PREAMBLE:
546                         preamble_ = lex.getLongString(from_ascii("EndPreamble"));
547                         break;
548
549                 case LT_LANGPREAMBLE:
550                         langpreamble_ = lex.getLongString(from_ascii("EndLangPreamble"));
551                         break;
552
553                 case LT_BABELPREAMBLE:
554                         babelpreamble_ = lex.getLongString(from_ascii("EndBabelPreamble"));
555                         break;
556
557                 case LT_LABELTYPE:
558                         readLabelType(lex);
559                         break;
560
561                 case LT_ENDLABELTYPE:
562                         readEndLabelType(lex);
563                         break;
564
565                 case LT_LEFTMARGIN:
566                         lex >> leftmargin;
567                         break;
568
569                 case LT_RIGHTMARGIN:
570                         lex >> rightmargin;
571                         break;
572
573                 case LT_LABELINDENT:
574                         lex >> labelindent;
575                         break;
576
577                 case LT_PARINDENT:
578                         lex >> parindent;
579                         break;
580
581                 case LT_PARSKIP:
582                         lex >> parskip;
583                         break;
584
585                 case LT_ITEMSEP:
586                         lex >> itemsep;
587                         break;
588
589                 case LT_TOPSEP:
590                         lex >> topsep;
591                         break;
592
593                 case LT_BOTTOMSEP:
594                         lex >> bottomsep;
595                         break;
596
597                 case LT_LABEL_BOTTOMSEP:
598                         lex >> labelbottomsep;
599                         break;
600
601                 case LT_LABELSEP:
602                         lex >> labelsep;
603                         labelsep = subst(labelsep, 'x', ' ');
604                         break;
605
606                 case LT_PARSEP:
607                         lex >> parsep;
608                         break;
609
610                 case LT_NEWLINE:
611                         lex >> newline_allowed;
612                         break;
613
614                 case LT_ALIGN:
615                         readAlign(lex);
616                         break;
617
618                 case LT_ALIGNPOSSIBLE:
619                         readAlignPossible(lex);
620                         break;
621
622                 case LT_LABELSTRING:
623                         // FIXME: this means LT_LABELSTRING_APPENDIX may only
624                         // occur after LT_LABELSTRING
625                         lex >> labelstring_;
626                         labelstring_appendix_ = labelstring_;
627                         break;
628
629                 case LT_ENDLABELSTRING:
630                         lex >> endlabelstring_;
631                         break;
632
633                 case LT_LABELSTRING_APPENDIX:
634                         lex >> labelstring_appendix_;
635                         break;
636
637                 case LT_LABELCOUNTER:
638                         lex >> counter;
639                         break;
640
641                 case LT_PAR_GROUP:
642                         lex >> par_group_;
643                         break;
644
645                 case LT_FREE_SPACING:
646                         lex >> free_spacing;
647                         break;
648
649                 case LT_PASS_THRU:
650                         lex >> pass_thru;
651                         break;
652
653                 case LT_PASS_THRU_CHARS:
654                         lex >> pass_thru_chars;
655                         break;
656
657                 case LT_PARBREAK_IS_NEWLINE:
658                         lex >> parbreak_is_newline;
659                         break;
660
661                 case LT_SPACING:
662                         readSpacing(lex);
663                         break;
664
665                 case LT_REQUIRES: {
666                         lex.eatLine();
667                         vector<string> const req =
668                                 getVectorFromString(lex.getString(true));
669                         required_.insert(req.begin(), req.end());
670                         break;
671                 }
672
673                 case LT_AUTONESTS: {
674                         docstring autonest = lex.getLongString(from_ascii("EndAutoNests"));
675                         autonest = subst(autonest, from_ascii("\n"), docstring());
676                         autonest = subst(autonest, from_ascii("\t"), docstring());
677                         autonest = subst(autonest, from_ascii("\""), docstring());
678                         autonest = subst(autonest, '_', ' ');
679                         vector<docstring> const autonests =
680                                 getVectorFromString(autonest, from_ascii(","), false, true);
681                         autonests_.insert(autonests.begin(), autonests.end());
682                         break;
683                 }
684
685                 case LT_AUTONESTEDBY: {
686                         docstring autonest = lex.getLongString(from_ascii("EndIsAutoNestedBy"));
687                         autonest = subst(autonest, from_ascii("\n"), docstring());
688                         autonest = subst(autonest, from_ascii("\t"), docstring());
689                         autonest = subst(autonest, from_ascii("\""), docstring());
690                         autonest = subst(autonest, '_', ' ');
691                         vector<docstring> const autonests =
692                                 getVectorFromString(autonest, from_ascii(","), false, true);
693                         autonested_by_.insert(autonests.begin(), autonests.end());
694                         break;
695                 }
696
697                 case LT_REFPREFIX: {
698                         docstring arg;
699                         lex >> arg;
700                         if (arg == "OFF")
701                                 refprefix.clear();
702                         else
703                                 refprefix = arg;
704                         break;
705                 }
706
707                 case LT_HTMLTAG:
708                         lex >> htmltag_;
709                         break;
710
711                 case LT_HTMLATTR:
712                         lex >> htmlattr_;
713                         break;
714
715                 case LT_HTMLITEM:
716                         lex >> htmlitemtag_;
717                         break;
718
719                 case LT_HTMLITEMATTR:
720                         lex >> htmlitemattr_;
721                         break;
722
723                 case LT_HTMLLABEL:
724                         lex >> htmllabeltag_;
725                         break;
726
727                 case LT_HTMLLABELATTR:
728                         lex >> htmllabelattr_;
729                         break;
730
731                 case LT_HTMLLABELFIRST:
732                         lex >> htmllabelfirst_;
733                         break;
734
735                 case LT_HTMLSTYLE:
736                         htmlstyle_ = lex.getLongString(from_ascii("EndHTMLStyle"));
737                         break;
738
739                 case LT_HTMLFORCECSS:
740                         lex >> htmlforcecss_;
741                         break;
742
743                 case LT_HTMLPREAMBLE:
744                         htmlpreamble_ = lex.getLongString(from_ascii("EndPreamble"));
745                         break;
746
747                 case LT_HTMLTITLE:
748                         lex >> htmltitle_;
749                         break;
750
751                 case LT_DOCBOOKTAG:
752                         lex >> docbooktag_;
753                         break;
754
755                 case LT_DOCBOOKATTR:
756                         lex >> docbookattr_;
757                         break;
758
759                 case LT_DOCBOOKTAGTYPE:
760                         lex >> docbooktagtype_;
761                         break;
762
763                 case LT_DOCBOOKINNERTAG:
764                         lex >> docbookinnertag_;
765                         break;
766
767                 case LT_DOCBOOKINNERATTR:
768                         lex >> docbookinnerattr_;
769                         break;
770
771                 case LT_DOCBOOKINNERTAGTYPE:
772                         lex >> docbookinnertagtype_;
773                         break;
774
775                 case LT_DOCBOOKFORCEABSTRACTTAG:
776                         lex >> docbookforceabstracttag_;
777                         break;
778
779                 case LT_DOCBOOKININFO:
780                         lex >> docbookininfo_;
781                         break;
782
783                 case LT_DOCBOOKABSTRACT:
784                         lex >> docbookabstract_;
785                         break;
786
787                 case LT_DOCBOOKWRAPPERTAG:
788                         lex >> docbookwrappertag_;
789                         break;
790
791                 case LT_DOCBOOKWRAPPERATTR:
792                         lex >> docbookwrapperattr_;
793                         break;
794
795                 case LT_DOCBOOKWRAPPERTAGTYPE:
796                         lex >> docbookwrappertagtype_;
797                         break;
798
799                 case LT_DOCBOOKWRAPPERMERGEWITHPREVIOUS:
800                         lex >> docbookwrappermergewithprevious_;
801                         break;
802
803                 case LT_DOCBOOKSECTION:
804                         lex >> docbooksection_;
805                         break;
806
807                 case LT_DOCBOOKSECTIONTAG:
808                         lex >> docbooksectiontag_;
809                         break;
810
811         case LT_DOCBOOKITEMWRAPPERTAG:
812             lex >> docbookitemwrappertag_;
813             break;
814
815         case LT_DOCBOOKITEMWRAPPERATTR:
816                         lex >> docbookitemwrapperattr_;
817                         break;
818
819                 case LT_DOCBOOKITEMWRAPPERTAGTYPE:
820                         lex >> docbookitemwrappertagtype_;
821                         break;
822
823                 case LT_DOCBOOKITEMTAG:
824                         lex >> docbookitemtag_;
825                         break;
826
827                 case LT_DOCBOOKITEMATTR:
828                         lex >> docbookitemattr_;
829                         break;
830
831                 case LT_DOCBOOKITEMTAGTYPE:
832                         lex >> docbookitemtagtype_;
833                         break;
834
835                 case LT_DOCBOOKITEMLABELTAG:
836                         lex >> docbookitemlabeltag_;
837                         break;
838
839                 case LT_DOCBOOKITEMLABELATTR:
840                         lex >> docbookitemlabelattr_;
841                         break;
842
843                 case LT_DOCBOOKITEMLABELTAGTYPE:
844                         lex >> docbookitemlabeltagtype_;
845                         break;
846
847                 case LT_DOCBOOKITEMINNERTAG:
848                         lex >> docbookiteminnertag_;
849                         break;
850
851                 case LT_DOCBOOKITEMINNERATTR:
852                         lex >> docbookiteminnerattr_;
853                         break;
854
855                 case LT_DOCBOOKITEMINNERTAGTYPE:
856                         lex >> docbookiteminnertagtype_;
857                         break;
858
859                 case LT_SPELLCHECK:
860                         lex >> spellcheck;
861                         break;
862
863                 case LT_FORCELOCAL:
864                         lex >> forcelocal;
865                         break;
866
867                 case LT_ADDTOTOC:
868                         lex >> toc_type_;
869                         add_to_toc_ = !toc_type_.empty();
870                         break;
871
872                 case LT_ISTOCCAPTION:
873                         lex >> is_toc_caption_;
874                         break;
875
876                 }
877         }
878         lex.popTable();
879         // make sure we only have inpreamble = true for commands
880         if (inpreamble && latextype != LATEX_COMMAND && latextype != LATEX_PARAGRAPH) {
881                 LYXERR0("InPreamble not permitted except with command and paragraph layouts.");
882                 LYXERR0("Layout name: " << name());
883                 inpreamble = false;
884         }
885
886         return finished && !error;
887 }
888
889
890 enum {
891         AT_BLOCK = 1,
892         AT_LEFT,
893         AT_RIGHT,
894         AT_CENTER,
895         AT_LAYOUT
896 };
897
898
899 LexerKeyword alignTags[] = {
900         { "block",  AT_BLOCK },
901         { "center", AT_CENTER },
902         { "layout", AT_LAYOUT },
903         { "left",   AT_LEFT },
904         { "right",  AT_RIGHT }
905 };
906
907
908 void Layout::readAlign(Lexer & lex)
909 {
910         PushPopHelper pph(lex, alignTags);
911         int le = lex.lex();
912         switch (le) {
913         case Lexer::LEX_UNDEF:
914                 lex.printError("Unknown alignment `$$Token'");
915                 return;
916         default: break;
917         };
918         switch (le) {
919         case AT_BLOCK:
920                 align = LYX_ALIGN_BLOCK;
921                 break;
922         case AT_LEFT:
923                 align = LYX_ALIGN_LEFT;
924                 break;
925         case AT_RIGHT:
926                 align = LYX_ALIGN_RIGHT;
927                 break;
928         case AT_CENTER:
929                 align = LYX_ALIGN_CENTER;
930                 break;
931         case AT_LAYOUT:
932                 align = LYX_ALIGN_LAYOUT;
933                 break;
934         }
935 }
936
937
938 void Layout::readAlignPossible(Lexer & lex)
939 {
940         lex.pushTable(alignTags);
941         alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
942         int lineno = lex.lineNumber();
943         do {
944                 int le = lex.lex();
945                 switch (le) {
946                 case Lexer::LEX_UNDEF:
947                         lex.printError("Unknown alignment `$$Token'");
948                         continue;
949                 default: break;
950                 };
951                 switch (le) {
952                 case AT_BLOCK:
953                         alignpossible |= LYX_ALIGN_BLOCK;
954                         break;
955                 case AT_LEFT:
956                         alignpossible |= LYX_ALIGN_LEFT;
957                         break;
958                 case AT_RIGHT:
959                         alignpossible |= LYX_ALIGN_RIGHT;
960                         break;
961                 case AT_CENTER:
962                         alignpossible |= LYX_ALIGN_CENTER;
963                         break;
964                 case AT_LAYOUT:
965                         alignpossible |= LYX_ALIGN_LAYOUT;
966                         break;
967                 }
968         } while (lineno == lex.lineNumber());
969         lex.popTable();
970 }
971
972
973 void Layout::readLabelType(Lexer & lex)
974 {
975         enum {
976                 LA_NO_LABEL = 1,
977                 LA_MANUAL,
978                 LA_ABOVE,
979                 LA_CENTERED,
980                 LA_STATIC,
981                 LA_SENSITIVE,
982                 LA_ENUMERATE,
983                 LA_ITEMIZE,
984                 LA_BIBLIO
985         };
986
987
988         LexerKeyword labelTypeTags[] = {
989           { "above",        LA_ABOVE },
990                 { "bibliography", LA_BIBLIO },
991                 { "centered",     LA_CENTERED },
992                 { "enumerate",    LA_ENUMERATE },
993                 { "itemize",      LA_ITEMIZE },
994                 { "manual",       LA_MANUAL },
995                 { "no_label",     LA_NO_LABEL },
996                 { "sensitive",    LA_SENSITIVE },
997                 { "static",       LA_STATIC }
998         };
999
1000         PushPopHelper pph(lex, labelTypeTags);
1001         int le = lex.lex();
1002         switch (le) {
1003         case Lexer::LEX_UNDEF:
1004                 lex.printError("Unknown labeltype tag `$$Token'");
1005                 return;
1006         default: break;
1007         }
1008         switch (le) {
1009         case LA_NO_LABEL:
1010                 labeltype = LABEL_NO_LABEL;
1011                 break;
1012         case LA_MANUAL:
1013                 labeltype = LABEL_MANUAL;
1014                 break;
1015         case LA_ABOVE:
1016                 labeltype = LABEL_ABOVE;
1017                 break;
1018         case LA_CENTERED:
1019                 labeltype = LABEL_CENTERED;
1020                 break;
1021         case LA_STATIC:
1022                 labeltype = LABEL_STATIC;
1023                 break;
1024         case LA_SENSITIVE:
1025                 labeltype = LABEL_SENSITIVE;
1026                 break;
1027         case LA_ENUMERATE:
1028                 labeltype = LABEL_ENUMERATE;
1029                 break;
1030         case LA_ITEMIZE:
1031                 labeltype = LABEL_ITEMIZE;
1032                 break;
1033         case LA_BIBLIO:
1034                 labeltype = LABEL_BIBLIO;
1035                 break;
1036         }
1037 }
1038
1039
1040 void Layout::readEndLabelType(Lexer & lex)
1041 {
1042         // this should be const, but can't be because
1043         // of PushPopHelper.
1044         static LexerKeyword endlabelTypeTags[] = {
1045                 { "box",              END_LABEL_BOX },
1046                 { "filled_box", END_LABEL_FILLED_BOX },
1047                 { "no_label",     END_LABEL_NO_LABEL },
1048                 { "static",     END_LABEL_STATIC }
1049         };
1050
1051         PushPopHelper pph(lex, endlabelTypeTags);
1052         int le = lex.lex();
1053         switch (le) {
1054         case Lexer::LEX_UNDEF:
1055                 lex.printError("Unknown labeltype tag `$$Token'");
1056                 break;
1057         case END_LABEL_STATIC:
1058         case END_LABEL_BOX:
1059         case END_LABEL_FILLED_BOX:
1060         case END_LABEL_NO_LABEL:
1061                 endlabeltype = static_cast<EndLabelType>(le);
1062                 break;
1063         default:
1064                 LYXERR0("Unhandled value " << le);
1065                 break;
1066         }
1067 }
1068
1069
1070 void Layout::readMargin(Lexer & lex)
1071 {
1072         LexerKeyword marginTags[] = {
1073                 { "dynamic",           MARGIN_DYNAMIC },
1074                 { "first_dynamic",     MARGIN_FIRST_DYNAMIC },
1075                 { "manual",            MARGIN_MANUAL },
1076                 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
1077                 { "static",            MARGIN_STATIC }
1078         };
1079
1080         PushPopHelper pph(lex, marginTags);
1081
1082         int le = lex.lex();
1083         switch (le) {
1084         case Lexer::LEX_UNDEF:
1085                 lex.printError("Unknown margin type tag `$$Token'");
1086                 return;
1087         case MARGIN_STATIC:
1088         case MARGIN_MANUAL:
1089         case MARGIN_DYNAMIC:
1090         case MARGIN_FIRST_DYNAMIC:
1091         case MARGIN_RIGHT_ADDRESS_BOX:
1092                 margintype = static_cast<MarginType>(le);
1093                 break;
1094         default:
1095                 LYXERR0("Unhandled value " << le);
1096                 break;
1097         }
1098 }
1099
1100
1101 void Layout::readLatexType(Lexer & lex)
1102 {
1103         LexerKeyword latexTypeTags[] = {
1104                 { "bib_environment",  LATEX_BIB_ENVIRONMENT },
1105                 { "command",          LATEX_COMMAND },
1106                 { "environment",      LATEX_ENVIRONMENT },
1107                 { "item_environment", LATEX_ITEM_ENVIRONMENT },
1108                 { "list_environment", LATEX_LIST_ENVIRONMENT },
1109                 { "paragraph",        LATEX_PARAGRAPH }
1110         };
1111
1112         PushPopHelper pph(lex, latexTypeTags);
1113         int le = lex.lex();
1114         switch (le) {
1115         case Lexer::LEX_UNDEF:
1116                 lex.printError("Unknown latextype tag `$$Token'");
1117                 return;
1118         case LATEX_PARAGRAPH:
1119         case LATEX_COMMAND:
1120         case LATEX_ITEM_ENVIRONMENT:
1121         case LATEX_LIST_ENVIRONMENT:
1122                 latextype = static_cast<LatexType>(le);
1123                 break;
1124         case LATEX_ENVIRONMENT:
1125         case LATEX_BIB_ENVIRONMENT:
1126                 latextype = static_cast<LatexType>(le);
1127                 par_group_ = true;
1128                 break;
1129         default:
1130                 LYXERR0("Unhandled value " << le);
1131                 break;
1132         }
1133 }
1134
1135
1136 void Layout::readSpacing(Lexer & lex)
1137 {
1138         enum {
1139                 ST_SPACING_SINGLE = 1,
1140                 ST_SPACING_ONEHALF,
1141                 ST_SPACING_DOUBLE,
1142                 ST_OTHER
1143         };
1144
1145         LexerKeyword spacingTags[] = {
1146                 {"double",  ST_SPACING_DOUBLE },
1147                 {"onehalf", ST_SPACING_ONEHALF },
1148                 {"other",   ST_OTHER },
1149                 {"single",  ST_SPACING_SINGLE }
1150         };
1151
1152         PushPopHelper pph(lex, spacingTags);
1153         int le = lex.lex();
1154         switch (le) {
1155         case Lexer::LEX_UNDEF:
1156                 lex.printError("Unknown spacing token `$$Token'");
1157                 return;
1158         default: break;
1159         }
1160         switch (le) {
1161         case ST_SPACING_SINGLE:
1162                 spacing.set(Spacing::Single);
1163                 break;
1164         case ST_SPACING_ONEHALF:
1165                 spacing.set(Spacing::Onehalf);
1166                 break;
1167         case ST_SPACING_DOUBLE:
1168                 spacing.set(Spacing::Double);
1169                 break;
1170         case ST_OTHER:
1171                 lex.next();
1172                 spacing.set(Spacing::Other, lex.getString());
1173                 break;
1174         }
1175 }
1176
1177
1178 void Layout::readArgument(Lexer & lex, bool validating)
1179 {
1180         if (!lex.next()) {
1181                 LYXERR0("Unable to read argument ID!");
1182                 return;
1183         }
1184         string const id = lex.getString();
1185
1186         bool const itemarg = prefixIs(id, "item:");
1187         bool const postcmd = prefixIs(id, "post:");
1188         bool const listpreamble = prefixIs(id, "listpreamble:");
1189
1190         LaTeXArgMap & lam = itemarg ? itemargs_ :
1191                         (postcmd ? postcommandargs_ :
1192                         (listpreamble ? listpreamble_ :
1193                         latexargs_));
1194         latexarg & arg = lam[id];
1195
1196         bool error = false;
1197         bool finished = false;
1198         while (!finished && lex.isOK() && !error) {
1199                 lex.next();
1200                 string const tok = ascii_lowercase(lex.getString());
1201
1202                 if (tok.empty()) {
1203                         continue;
1204                 } else if (tok == "endargument") {
1205                         finished = true;
1206                 } else if (tok == "labelstring") {
1207                         lex.next();
1208                         arg.labelstring = lex.getDocString();
1209                 } else if (tok == "menustring") {
1210                         lex.next();
1211                         arg.menustring = lex.getDocString();
1212                 } else if (tok == "mandatory") {
1213                         lex.next();
1214                         arg.mandatory = lex.getBool();
1215                 } else if (tok == "autoinsert") {
1216                         lex.next();
1217                         arg.autoinsert = lex.getBool();
1218                 } else if (tok == "insertcotext") {
1219                         lex.next();
1220                         arg.insertcotext = lex.getBool();
1221                 } else if (tok == "leftdelim") {
1222                         lex.next();
1223                         arg.ldelim = lex.getDocString();
1224                         arg.ldelim = support::subst(arg.ldelim, from_ascii("<br/>"),
1225                                                     from_ascii("\n"));
1226                 } else if (tok == "rightdelim") {
1227                         lex.next();
1228                         arg.rdelim = lex.getDocString();
1229                         arg.rdelim = support::subst(arg.rdelim, from_ascii("<br/>"),
1230                                                     from_ascii("\n"));
1231                 } else if (tok == "defaultarg") {
1232                         lex.next();
1233                         arg.defaultarg = lex.getDocString();
1234                 } else if (tok == "presetarg") {
1235                         lex.next();
1236                         arg.presetarg = lex.getDocString();
1237                 } else if (tok == "tooltip") {
1238                         lex.next();
1239                         arg.tooltip = lex.getDocString();
1240                 } else if (tok == "requires") {
1241                         lex.next();
1242                         arg.required = lex.getString();
1243                 } else if (tok == "decoration") {
1244                         lex.next();
1245                         arg.decoration = lex.getString();
1246                 } else if (tok == "newlinecmd") {
1247                         lex.next();
1248                         arg.newlinecmd = lex.getString();
1249                 } else if (tok == "font") {
1250                         arg.font = lyxRead(lex, arg.font);
1251                 } else if (tok == "labelfont") {
1252                         arg.labelfont = lyxRead(lex, arg.labelfont);
1253                 } else if (tok == "passthruchars") {
1254                         lex.next();
1255                         arg.pass_thru_chars = lex.getDocString();
1256                 } else if (tok == "passthru") {
1257                         lex.next();
1258                         docstring value = lex.getDocString();
1259                         if (value == "true" || value == "1")
1260                                 arg.passthru = PT_TRUE;
1261                         else if (value == "false" || value == "0")
1262                                 arg.passthru = PT_FALSE;
1263                         else
1264                                 arg.passthru = PT_INHERITED;
1265                 } else if (tok == "istoccaption") {
1266                         lex.next();
1267                         arg.is_toc_caption = lex.getBool();
1268                 } else if (tok == "freespacing") {
1269                         lex.next();
1270                         arg.free_spacing = lex.getBool();
1271                 } else if (tok == "docbooktag") {
1272                         lex.next();
1273                         arg.docbooktag = lex.getDocString();
1274                 } else if (tok == "docbookattr") {
1275                         lex.next();
1276                         arg.docbookattr = lex.getDocString();
1277                 } else if (tok == "docbooktagtype") {
1278                         lex.next();
1279                         arg.docbooktagtype = lex.getDocString();
1280                 } else {
1281                         lex.printError("Unknown tag");
1282                         error = true;
1283                 }
1284         }
1285         if (!validating && arg.labelstring.empty()) {
1286                 LYXERR0("Incomplete Argument definition!");
1287                 // remove invalid definition
1288                 lam.erase(id);
1289         }
1290 }
1291
1292
1293 void writeArgument(ostream & os, string const & id, Layout::latexarg const & arg)
1294 {
1295         os << "\tArgument " << id << '\n';
1296         if (!arg.labelstring.empty())
1297                 os << "\t\tLabelString \"" << to_utf8(arg.labelstring) << "\"\n";
1298         if (!arg.menustring.empty())
1299                 os << "\t\tMenuString \"" << to_utf8(arg.menustring) << "\"\n";
1300         if (arg.mandatory)
1301                 os << "\t\tMandatory " << arg.mandatory << '\n';
1302         if (arg.autoinsert)
1303                 os << "\t\tAutoinsert " << arg.autoinsert << '\n';
1304         if (arg.insertcotext)
1305                 os << "\t\tInsertCotext " << arg.insertcotext << '\n';
1306         if (!arg.ldelim.empty())
1307                 os << "\t\tLeftDelim \""
1308                    << to_utf8(subst(arg.ldelim, from_ascii("\n"), from_ascii("<br/>")))
1309                    << "\"\n";
1310         if (!arg.rdelim.empty())
1311                 os << "\t\tRightDelim \""
1312                    << to_utf8(subst(arg.rdelim, from_ascii("\n"), from_ascii("<br/>")))
1313                    << "\"\n";
1314         if (!arg.defaultarg.empty())
1315                 os << "\t\tDefaultArg \"" << to_utf8(arg.defaultarg) << "\"\n";
1316         if (!arg.presetarg.empty())
1317                 os << "\t\tPresetArg \"" << to_utf8(arg.presetarg) << "\"\n";
1318         if (!arg.tooltip.empty())
1319                 os << "\t\tToolTip \"" << to_utf8(arg.tooltip) << "\"\n";
1320         if (!arg.required.empty())
1321                 os << "\t\tRequires \"" << arg.required << "\"\n";
1322         if (!arg.decoration.empty())
1323                 os << "\t\tDecoration \"" << arg.decoration << "\"\n";
1324         if (!arg.newlinecmd.empty())
1325                 os << "\t\tNewlineCmd \"" << arg.newlinecmd << "\"\n";
1326         if (arg.font != inherit_font)
1327                 lyxWrite(os, arg.font, "Font", 2);
1328         if (arg.labelfont != inherit_font)
1329                 lyxWrite(os, arg.labelfont, "LabelFont", 2);
1330         switch (arg.passthru) {
1331                 case PT_TRUE:
1332                         os << "\t\tPassThru true\n";
1333                         break;
1334                 case PT_FALSE:
1335                         os << "\t\tPassThru false\n";
1336                         break;
1337                 case PT_INHERITED:
1338                         os << "\t\tPassThru inherited\n";
1339                         break;
1340         }
1341         if (!arg.pass_thru_chars.empty())
1342                 os << "\t\tPassThruChars \"" << to_utf8(arg.pass_thru_chars) << "\"\n";
1343         if (arg.free_spacing)
1344                 os << "\t\tFreeSpacing " << arg.free_spacing << "\n";
1345         os << "\tEndArgument\n";
1346 }
1347
1348
1349 void Layout::write(ostream & os) const
1350 {
1351         os << "Style \"" << to_utf8(name_) << "\"\n";
1352         if (!category_.empty() && obsoleted_by_.empty())
1353                 os << "\tCategory \"" << to_utf8(category_) << "\"\n";
1354         // Can't deduce Copystyle here :-(
1355         if (!obsoleted_by_.empty()) {
1356                 os << "\tObsoletedBy \"" << to_utf8(obsoleted_by_)
1357                    << "\"\nEnd\n";
1358                 return;
1359         }
1360         if (!depends_on_.empty())
1361                 os << "\tDependsOn " << to_utf8(depends_on_) << '\n';
1362         switch (margintype) {
1363                 case MARGIN_DYNAMIC:
1364                         os << "\tMargin Dynamic\n";
1365                         break;
1366                 case MARGIN_FIRST_DYNAMIC:
1367                         os << "\tMargin First_Dynamic\n";
1368                         break;
1369                 case MARGIN_MANUAL:
1370                         os << "\tMargin Manual\n";
1371                         break;
1372                 case MARGIN_RIGHT_ADDRESS_BOX:
1373                         os << "\tMargin Right_Address_Box\n";
1374                         break;
1375                 case MARGIN_STATIC:
1376                         os << "\tMargin Static\n";
1377                         break;
1378         }
1379         switch (latextype) {
1380                 case LATEX_BIB_ENVIRONMENT:
1381                         os << "\tLatexType Bib_Environment\n";
1382                         break;
1383                 case LATEX_COMMAND:
1384                         os << "\tLatexType Command\n";
1385                         break;
1386                 case LATEX_ENVIRONMENT:
1387                         os << "\tLatexType Environment\n";
1388                         break;
1389                 case LATEX_ITEM_ENVIRONMENT:
1390                         os << "\tLatexType Item_Environment\n";
1391                         break;
1392                 case LATEX_LIST_ENVIRONMENT:
1393                         os << "\tLatexType List_Environment\n";
1394                         break;
1395                 case LATEX_PARAGRAPH:
1396                         os << "\tLatexType Paragraph\n";
1397                         break;
1398         }
1399         os << "\tInTitle " << intitle << "\n"
1400               "\tInPreamble " << inpreamble << "\n"
1401               "\tTocLevel " << toclevel << "\n"
1402               "\tResumeCounter " << resumecounter << "\n"
1403              "\tStepMasterCounter " << stepmastercounter << '\n';
1404         // ResetArgs does not make sense here
1405         for (LaTeXArgMap::const_iterator it = latexargs_.begin();
1406              it != latexargs_.end(); ++it)
1407                 writeArgument(os, it->first, it->second);
1408         for (LaTeXArgMap::const_iterator it = itemargs_.begin();
1409              it != itemargs_.end(); ++it)
1410                 writeArgument(os, it->first, it->second);
1411         for (LaTeXArgMap::const_iterator it = postcommandargs_.begin();
1412              it != postcommandargs_.end(); ++it)
1413                 writeArgument(os, it->first, it->second);
1414         for (LaTeXArgMap::const_iterator it = listpreamble_.begin();
1415              it != listpreamble_.end(); ++it)
1416                 writeArgument(os, it->first, it->second);
1417         os << "\tNeedProtect " << needprotect << "\n"
1418               "\tNeedCProtect " << needcprotect << "\n"
1419               "\tNeedMBoxProtect " << needmboxprotect << "\n"
1420               "\tKeepEmpty " << keepempty << '\n';
1421         if (labelfont == font)
1422                 lyxWrite(os, font, "Font", 1);
1423         else {
1424                 lyxWrite(os, font, "TextFont", 1);
1425                 lyxWrite(os, labelfont, "LabelFont", 1);
1426         }
1427         os << "\tNextNoIndent " << nextnoindent << "\n"
1428               "\tCommandDepth " << commanddepth << '\n';
1429         if (!latexname_.empty())
1430                 os << "\tLatexName \"" << latexname_ << "\"\n";
1431         if (!latexparam_.empty())
1432                 os << "\tLatexParam \"" << subst(latexparam_, "\"", "&quot;")
1433                    << "\"\n";
1434         if (!leftdelim_.empty())
1435                 os << "\tLeftDelim "
1436                    << to_utf8(subst(leftdelim_, from_ascii("\n"), from_ascii("<br/>")))
1437                    << '\n';
1438         if (!rightdelim_.empty())
1439                 os << "\tRightDelim "
1440                    << to_utf8(subst(rightdelim_, from_ascii("\n"), from_ascii("<br/>")))
1441                    << '\n';
1442         if (!innertag_.empty())
1443                 os << "\tInnerTag \"" << innertag_ << "\"\n";
1444         if (!labeltag_.empty())
1445                 os << "\tLabelTag \"" << labeltag_ << "\"\n";
1446         if (!itemtag_.empty())
1447                 os << "\tItemTag \"" << itemtag_ << "\"\n";
1448         if (!itemcommand_.empty())
1449                 os << "\tItemCommand " << itemcommand_ << '\n';
1450         if (!preamble_.empty())
1451                 os << "\tPreamble\n\t"
1452                    << to_utf8(subst(rtrim(preamble_, "\n"),
1453                                     from_ascii("\n"), from_ascii("\n\t")))
1454                    << "\n\tEndPreamble\n";
1455         if (!langpreamble_.empty())
1456                 os << "\tLangPreamble\n\t"
1457                    << to_utf8(subst(rtrim(langpreamble_, "\n"),
1458                                     from_ascii("\n"), from_ascii("\n\t")))
1459                    << "\n\tEndLangPreamble\n";
1460         if (!babelpreamble_.empty())
1461                 os << "\tBabelPreamble\n\t"
1462                    << to_utf8(subst(rtrim(babelpreamble_, "\n"),
1463                                     from_ascii("\n"), from_ascii("\n\t")))
1464                    << "\n\tEndBabelPreamble\n";
1465         switch (labeltype) {
1466         case LABEL_ABOVE:
1467                 os << "\tLabelType Above\n";
1468                 break;
1469         case LABEL_BIBLIO:
1470                 os << "\tLabelType Bibliography\n";
1471                 break;
1472         case LABEL_CENTERED:
1473                 os << "\tLabelType Centered\n";
1474                 break;
1475         case LABEL_ENUMERATE:
1476                 os << "\tLabelType Enumerate\n";
1477                 break;
1478         case LABEL_ITEMIZE:
1479                 os << "\tLabelType Itemize\n";
1480                 break;
1481         case LABEL_MANUAL:
1482                 os << "\tLabelType Manual\n";
1483                 break;
1484         case LABEL_NO_LABEL:
1485                 os << "\tLabelType No_Label\n";
1486                 break;
1487         case LABEL_SENSITIVE:
1488                 os << "\tLabelType Sensitive\n";
1489                 break;
1490         case LABEL_STATIC:
1491                 os << "\tLabelType Static\n";
1492                 break;
1493         }
1494         switch (endlabeltype) {
1495         case END_LABEL_BOX:
1496                 os << "\tEndLabelType Box\n";
1497                 break;
1498         case END_LABEL_FILLED_BOX:
1499                 os << "\tEndLabelType Filled_Box\n";
1500                 break;
1501         case END_LABEL_NO_LABEL:
1502                 os << "\tEndLabelType No_Label\n";
1503                 break;
1504         case END_LABEL_STATIC:
1505                 os << "\tEndLabelType Static\n";
1506                 break;
1507         }
1508         os << "\tParagraphGroup \"" << par_group_ << "\"\n";
1509         if (!leftmargin.empty())
1510                 os << "\tLeftMargin \"" << to_utf8(leftmargin) << "\"\n";
1511         if (!rightmargin.empty())
1512                 os << "\tRightMargin \"" << to_utf8(rightmargin) << "\"\n";
1513         if (!labelindent.empty())
1514                 os << "\tLabelIndent " << to_utf8(labelindent) << '\n';
1515         if (!parindent.empty())
1516                 os << "\tParIndent " << to_utf8(parindent) << '\n';
1517         os << "\tParSkip " << parskip << "\n"
1518               "\tItemSep " << itemsep << "\n"
1519               "\tTopSep " << topsep << "\n"
1520               "\tBottomSep " << bottomsep << "\n"
1521               "\tLabelBottomSep " << labelbottomsep << '\n';
1522         if (!labelsep.empty())
1523                 os << "\tLabelSep " << to_utf8(subst(labelsep, ' ', 'x'))
1524                    << '\n';
1525         os << "\tParSep " << parsep << "\n"
1526               "\tNewLine " << newline_allowed << '\n';
1527         switch (align) {
1528         case LYX_ALIGN_BLOCK:
1529                 os << "\tAlign Block\n";
1530                 break;
1531         case LYX_ALIGN_CENTER:
1532                 os << "\tAlign Center\n";
1533                 break;
1534         case LYX_ALIGN_LAYOUT:
1535                 os << "\tAlign Layout\n";
1536                 break;
1537         case LYX_ALIGN_LEFT:
1538                 os << "\tAlign Left\n";
1539                 break;
1540         case LYX_ALIGN_RIGHT:
1541                 os << "\tAlign Right\n";
1542                 break;
1543         case LYX_ALIGN_DECIMAL:
1544         case LYX_ALIGN_SPECIAL:
1545         case LYX_ALIGN_NONE:
1546                 break;
1547         }
1548         if (alignpossible & (LYX_ALIGN_BLOCK | LYX_ALIGN_CENTER |
1549                              LYX_ALIGN_LAYOUT | LYX_ALIGN_LEFT | LYX_ALIGN_RIGHT)) {
1550                 bool first = true;
1551                 os << "\tAlignPossible";
1552                 if (alignpossible & LYX_ALIGN_BLOCK) {
1553                         os << " Block";
1554                         first = false;
1555                 }
1556                 if (alignpossible & LYX_ALIGN_CENTER) {
1557                         if (!first)
1558                                 os << ',';
1559                         os << " Center";
1560                         first = false;
1561                 }
1562                 if (alignpossible & LYX_ALIGN_LAYOUT) {
1563                         if (!first)
1564                                 os << ',';
1565                         os << " Layout";
1566                         first = false;
1567                 }
1568                 if (alignpossible & LYX_ALIGN_LEFT) {
1569                         if (!first)
1570                                 os << ',';
1571                         os << " Left";
1572                         first = false;
1573                 }
1574                 if (alignpossible & LYX_ALIGN_RIGHT) {
1575                         if (!first)
1576                                 os << ',';
1577                         os << " Right";
1578                         first = false;
1579                 }
1580                 os << '\n';
1581         }
1582         // LabelString must come before LabelStringAppendix
1583         if (!labelstring_.empty())
1584                 os << "\tLabelString \"" << to_utf8(labelstring_) << "\"\n";
1585         if (!endlabelstring_.empty())
1586                 os << "\tEndLabelString \"" << to_utf8(endlabelstring_) << "\"\n";
1587         if (!labelstring_appendix_.empty() && labelstring_appendix_ != labelstring_)
1588                 os << "\tLabelStringAppendix \""
1589                    << to_utf8(labelstring_appendix_) << "\"\n";
1590         if (!counter.empty())
1591                 os << "\tLabelCounter \"" << to_utf8(counter) << "\"\n";
1592         os << "\tFreeSpacing " << free_spacing << '\n';
1593         os << "\tPassThru " << pass_thru << '\n';
1594         if (!pass_thru_chars.empty())
1595                 os << "\tPassThruChars " << to_utf8(pass_thru_chars) << '\n';
1596         os << "\tParbreakIsNewline " << parbreak_is_newline << '\n';
1597         switch (spacing.getSpace()) {
1598         case Spacing::Double:
1599                 os << "\tSpacing Double\n";
1600                 break;
1601         case Spacing::Onehalf:
1602                 os << "\tSpacing Onehalf\n";
1603                 break;
1604         case Spacing::Other:
1605                 os << "\tSpacing Other " << spacing.getValueAsString() << '\n';
1606                 break;
1607         case Spacing::Single:
1608                 os << "\tSpacing Single\n";
1609                 break;
1610         case Spacing::Default:
1611                 break;
1612         }
1613         if (!required_.empty()) {
1614                 os << "\tRequires ";
1615                 for (set<string>::const_iterator it = required_.begin();
1616                      it != required_.end(); ++it) {
1617                         if (it != required_.begin())
1618                                 os << ',';
1619                         os << *it;
1620                 }
1621                 os << '\n';
1622         }
1623         if (!autonests_.empty()) {
1624                 os << "\tAutoNests\n\t";
1625                 for (set<docstring>::const_iterator it = autonests_.begin();
1626                      it != autonests_.end(); ++it) {
1627                         if (it != autonests_.begin())
1628                                 os << ',';
1629                         os << to_utf8(*it);
1630                 }
1631                 os << "\n\tEndAutoNests\n";
1632         }
1633         if (!autonested_by_.empty()) {
1634                 os << "\tIsAutoNestedBy\n\t\t";
1635                 for (set<docstring>::const_iterator it = autonested_by_.begin();
1636                      it != autonested_by_.end(); ++it) {
1637                         if (it != autonested_by_.begin())
1638                                 os << ',';
1639                         os << to_utf8(*it);
1640                 }
1641                 os << "\n\tEndIsAutoNestedBy\n";
1642         }
1643         if (refprefix.empty())
1644                 os << "\tRefPrefix OFF\n";
1645         else
1646                 os << "\tRefPrefix " << to_utf8(refprefix) << '\n';
1647         if (!htmltag_.empty())
1648                 os << "\tHTMLTag " << htmltag_ << '\n';
1649         if (!htmlattr_.empty())
1650                 os << "\tHTMLAttr " << htmlattr_ << '\n';
1651         if (!htmlitemtag_.empty())
1652                 os << "\tHTMLItem " << htmlitemtag_ << '\n';
1653         if (!htmlitemattr_.empty())
1654                 os << "\tHTMLItemAttr " << htmlitemattr_ << '\n';
1655         if (!htmllabeltag_.empty())
1656                 os << "\tHTMLLabel " << htmllabeltag_ << '\n';
1657         if (!htmllabelattr_.empty())
1658                 os << "\tHTMLLabelAttr " << htmllabelattr_ << '\n';
1659         os << "\tHTMLLabelFirst " << htmllabelfirst_ << '\n';
1660         if (!htmlstyle_.empty())
1661                 os << "\tHTMLStyle\n"
1662                    << to_utf8(rtrim(htmlstyle_, "\n"))
1663                    << "\n\tEndHTMLStyle\n";
1664         os << "\tHTMLForceCSS " << htmlforcecss_ << '\n';
1665         if (!htmlpreamble_.empty())
1666                 os << "\tHTMLPreamble\n"
1667                    << to_utf8(rtrim(htmlpreamble_, "\n"))
1668                    << "\n\tEndPreamble\n";
1669         os << "\tHTMLTitle " << htmltitle_ << "\n";
1670         if(!docbooktag_.empty())
1671                 os << "\tDocBookTag " << docbooktag_ << '\n';
1672         if(!docbookattr_.empty())
1673                 os << "\tDocBookAttr \"" << docbookattr_ << "\"\n";
1674         if(!docbooktagtype_.empty())
1675                 os << "\tDocBookTagType " << docbooktagtype_ << '\n';
1676         if(!docbookinnertag_.empty())
1677                 os << "\tDocBookInnerTag " << docbookinnertag_ << '\n';
1678         if(!docbookinnerattr_.empty())
1679                 os << "\tDocBookInnerAttr \"" << docbookinnerattr_ << "\"\n";
1680         if(!docbookinnertagtype_.empty())
1681                 os << "\tDocBookInnerTagType " << docbookinnertagtype_ << '\n';
1682         if(!docbookininfo_.empty())
1683                 os << "\tDocBookInInfo " << docbookininfo_ << '\n';
1684         os << "\tDocBookAbstract " << docbookabstract_ << '\n';
1685         if(!docbookwrappertag_.empty())
1686                 os << "\tDocBookWrapperTag " << docbookwrappertag_ << '\n';
1687         if(!docbookwrapperattr_.empty())
1688                 os << "\tDocBookWrapperAttr " << docbookwrapperattr_ << '\n';
1689         if(!docbookwrappertagtype_.empty())
1690                 os << "\tDocBookWrapperTagType " << docbookwrappertagtype_ << '\n';
1691         os << "\tDocBookSection " << docbooksection_ << '\n';
1692         if(!docbooksectiontag_.empty())
1693                 os << "\tDocBookSectionTag " << docbooksectiontag_ << '\n';
1694         if(!docbookitemtag_.empty())
1695                 os << "\tDocBookItemTag " << docbookitemtag_ << '\n';
1696         if(!docbookitemattr_.empty())
1697                 os << "\tDocBookItemAttr " << docbookitemattr_ << '\n';
1698         if(!docbookitemtagtype_.empty())
1699                 os << "\tDocBookItemTagType " << docbookitemtagtype_ << '\n';
1700         if(!docbookitemwrappertag_.empty())
1701                 os << "\tDocBookItemWrapperTag " << docbookitemwrappertag_ << '\n';
1702         if(!docbookitemwrapperattr_.empty())
1703                 os << "\tDocBookItemWrapperAttr " << docbookitemwrapperattr_ << '\n';
1704         if(!docbookitemwrappertagtype_.empty())
1705                 os << "\tDocBookItemWrapperTagType " << docbookitemwrappertagtype_ << '\n';
1706         os << "\tDocBookWrapperMergeWithPrevious " << docbookwrappermergewithprevious_ << '\n';
1707         if(!docbookitemlabeltag_.empty())
1708                 os << "\tDocBookItemLabelTag " << docbookitemlabeltag_ << '\n';
1709         if(!docbookitemlabelattr_.empty())
1710                 os << "\tDocBookItemLabelAttr " << docbookitemlabelattr_ << '\n';
1711         if(!docbookitemlabeltagtype_.empty())
1712                 os << "\tDocBookItemLabelTagType " << docbookitemlabeltagtype_ << '\n';
1713         if(!docbookiteminnertag_.empty())
1714                 os << "\tDocBookItemInnerTag " << docbookiteminnertag_ << '\n';
1715         if(!docbookiteminnerattr_.empty())
1716                 os << "\tDocBookItemInnerAttr " << docbookiteminnerattr_ << '\n';
1717         if(!docbookiteminnertagtype_.empty())
1718                 os << "\tDocBookItemInnerTagType " << docbookiteminnertagtype_ << '\n';
1719         if(!docbookforceabstracttag_.empty())
1720                 os << "\tDocBookForceAbstractTag " << docbookforceabstracttag_ << '\n';
1721         os << "\tSpellcheck " << spellcheck << "\n"
1722               "\tForceLocal " << forcelocal << "\n"
1723               "End\n";
1724 }
1725
1726
1727 bool Layout::hasArgs() const
1728 {
1729         return !latexargs_.empty() || !postcommandargs_.empty() ||
1730                 !itemargs_.empty() || !listpreamble_.empty();
1731 }
1732
1733
1734 Layout::LaTeXArgMap Layout::args() const
1735 {
1736         LaTeXArgMap args = latexargs_;
1737         if (!postcommandargs_.empty())
1738                 args.insert(postcommandargs_.begin(), postcommandargs_.end());
1739         if (!listpreamble_.empty())
1740                 args.insert(listpreamble_.begin(), listpreamble_.end());
1741         if (!itemargs_.empty())
1742                 args.insert(itemargs_.begin(), itemargs_.end());
1743         return args;
1744 }
1745
1746
1747 int Layout::optArgs() const
1748 {
1749         int nr = 0;
1750         LaTeXArgMap::const_iterator it = latexargs_.begin();
1751         for (; it != latexargs_.end(); ++it) {
1752                 if (!(*it).second.mandatory)
1753                         ++nr;
1754         }
1755         LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
1756         for (; iit != postcommandargs_.end(); ++iit) {
1757                 if (!(*iit).second.mandatory)
1758                         ++nr;
1759         }
1760         return nr;
1761 }
1762
1763
1764 int Layout::requiredArgs() const
1765 {
1766         int nr = 0;
1767         LaTeXArgMap::const_iterator it = latexargs_.begin();
1768         for (; it != latexargs_.end(); ++it) {
1769                 if ((*it).second.mandatory)
1770                         ++nr;
1771         }
1772         LaTeXArgMap::const_iterator iit = postcommandargs_.begin();
1773         for (; iit != postcommandargs_.end(); ++iit) {
1774                 if (!(*iit).second.mandatory)
1775                         ++nr;
1776         }
1777         return nr;
1778 }
1779
1780
1781 string const & Layout::htmltag() const
1782 {
1783         if (htmltag_.empty())
1784                 htmltag_ =  "div";
1785         return htmltag_;
1786 }
1787
1788
1789 string const & Layout::htmlattr() const
1790 {
1791         if (htmlattr_.empty())
1792                 htmlattr_ = "class=\"" + defaultCSSClass() + "\"";
1793         return htmlattr_;
1794 }
1795
1796
1797 string const & Layout::htmlitemtag() const
1798 {
1799         if (htmlitemtag_.empty())
1800                 htmlitemtag_ = "div";
1801         return htmlitemtag_;
1802 }
1803
1804
1805 string const & Layout::htmlitemattr() const
1806 {
1807         if (htmlitemattr_.empty())
1808                 htmlitemattr_ = "class=\"" + defaultCSSItemClass() + "\"";
1809         return htmlitemattr_;
1810 }
1811
1812
1813 string const & Layout::htmllabeltag() const
1814 {
1815         if (htmllabeltag_.empty())
1816                         htmllabeltag_ = "span";
1817         return htmllabeltag_;
1818 }
1819
1820
1821 string const & Layout::htmllabelattr() const
1822 {
1823         if (htmllabelattr_.empty())
1824                 htmllabelattr_ = "class=\"" + defaultCSSLabelClass() + "\"";
1825         return htmllabelattr_;
1826 }
1827
1828
1829 docstring Layout::htmlstyle() const
1830 {
1831         if (!htmlstyle_.empty() && !htmlforcecss_)
1832                 return htmlstyle_;
1833         if (htmldefaultstyle_.empty())
1834                 makeDefaultCSS();
1835         docstring retval = htmldefaultstyle_;
1836         if (!htmlstyle_.empty())
1837                 retval += '\n' + htmlstyle_;
1838         return retval;
1839 }
1840
1841
1842 string Layout::defaultCSSClass() const
1843 {
1844         if (!defaultcssclass_.empty())
1845                 return defaultcssclass_;
1846         docstring d;
1847         docstring::const_iterator it = name().begin();
1848         docstring::const_iterator en = name().end();
1849         for (; it != en; ++it) {
1850                 char_type const c = *it;
1851                 if (!isAlphaASCII(c)) {
1852                         if (d.empty())
1853                                 // make sure we don't start with an underscore,
1854                                 // as that sometimes causes problems.
1855                                 d = from_ascii("lyx_");
1856                         else
1857                                 d += '_';
1858                 } else if (isLower(c))
1859                         d += c;
1860                 else
1861                         // this is slow, so do it only if necessary
1862                         d += lowercase(c);
1863         }
1864         defaultcssclass_ = to_utf8(d);
1865         return defaultcssclass_;
1866 }
1867
1868
1869 string const & Layout::docbooktag() const
1870 {
1871         if (docbooktag_.empty()) {
1872                 if (to_ascii(name_) == "Plain Layout")
1873                         docbooktag_ = "para";
1874                 else // No sensible default value, unhappily...
1875                         docbooktag_ = to_utf8(name_);
1876         }
1877         return docbooktag_;
1878 }
1879
1880
1881 string const & Layout::docbookattr() const
1882 {
1883         // Perfectly OK to return no attributes, so docbookattr_ does not need to be filled.
1884         return docbookattr_;
1885 }
1886
1887
1888 bool isValidTagType(std::string type)
1889 {
1890         return !(type.empty() || (type != "block" && type != "paragraph" && type != "inline"));
1891 }
1892
1893
1894 string const & Layout::docbooktagtype() const
1895 {
1896         if (!isValidTagType(docbooktagtype_))
1897                 docbooktagtype_ = "block";
1898         return docbooktagtype_;
1899 }
1900
1901
1902 string const & Layout::docbookinnertag() const
1903 {
1904         if (docbookinnertag_.empty())
1905                 docbookinnertag_ = "NONE";
1906         return docbookinnertag_;
1907 }
1908
1909
1910 string const & Layout::docbookinnerattr() const
1911 {
1912         return docbookinnerattr_;
1913 }
1914
1915
1916 string const & Layout::docbookinnertagtype() const
1917 {
1918         if (!isValidTagType(docbookinnertagtype_))
1919                 docbookinnertagtype_ = "block";
1920         return docbookinnertagtype_;
1921 }
1922
1923
1924 string const & Layout::docbookininfo() const
1925 {
1926         // Indeed, a trilean. Only titles should be "maybe": otherwise, metadata is "always", content is "never". 
1927         if (docbookininfo_.empty() || (docbookininfo_ != "never" && docbookininfo_ != "always" && docbookininfo_ != "maybe"))
1928                 docbookininfo_ = "never";
1929         return docbookininfo_;
1930 }
1931
1932
1933 string const & Layout::docbookwrappertag() const
1934 {
1935     if (docbookwrappertag_.empty())
1936         docbookwrappertag_ = "NONE";
1937     return docbookwrappertag_;
1938 }
1939
1940
1941 string const & Layout::docbookwrapperattr() const
1942 {
1943     return docbookwrapperattr_;
1944 }
1945
1946
1947 string const & Layout::docbookwrappertagtype() const
1948 {
1949         if (!isValidTagType(docbookwrappertagtype_))
1950                 docbookwrappertagtype_ = "block";
1951         return docbookwrappertagtype_;
1952 }
1953
1954
1955 string const & Layout::docbooksectiontag() const
1956 {
1957         if (docbooksectiontag_.empty())
1958                 docbooksectiontag_ = "section";
1959         return docbooksectiontag_;
1960 }
1961
1962
1963 string const & Layout::docbookitemwrappertag() const
1964 {
1965     if (docbookitemwrappertag_.empty())
1966         docbookitemwrappertag_ = "NONE";
1967     return docbookitemwrappertag_;
1968 }
1969
1970
1971 string const & Layout::docbookitemwrapperattr() const
1972 {
1973     return docbookitemwrapperattr_;
1974 }
1975
1976
1977 string const & Layout::docbookitemwrappertagtype() const
1978 {
1979         if (!isValidTagType(docbookitemwrappertagtype_))
1980                 docbookitemwrappertagtype_ = "block";
1981         return docbookitemwrappertagtype_;
1982 }
1983
1984
1985 string const & Layout::docbookitemtag() const
1986 {
1987         if (docbookitemtag_.empty())
1988                 docbookitemtag_ = "NONE";
1989         return docbookitemtag_;
1990 }
1991
1992
1993 string const & Layout::docbookitemattr() const
1994 {
1995     return docbookitemattr_;
1996 }
1997
1998
1999 string const & Layout::docbookitemtagtype() const
2000 {
2001         if (!isValidTagType(docbookitemtagtype_))
2002                 docbookitemtagtype_ = "block";
2003         return docbookitemtagtype_;
2004 }
2005
2006
2007 string const & Layout::docbookitemlabeltag() const
2008 {
2009         if (docbookitemlabeltag_.empty())
2010                 docbookitemlabeltag_ = "NONE";
2011         return docbookitemlabeltag_;
2012 }
2013
2014
2015 string const & Layout::docbookitemlabelattr() const
2016 {
2017         return docbookitemlabelattr_;
2018 }
2019
2020
2021 string const & Layout::docbookitemlabeltagtype() const
2022 {
2023         if (!isValidTagType(docbookitemlabeltagtype_))
2024                 docbookitemlabeltagtype_ = "block";
2025         return docbookitemlabeltagtype_;
2026 }
2027
2028
2029 string const & Layout::docbookiteminnertag() const
2030 {
2031         if (docbookiteminnertag_.empty())
2032                 docbookiteminnertag_ = "NONE";
2033         return docbookiteminnertag_;
2034 }
2035
2036
2037 string const & Layout::docbookiteminnerattr() const
2038 {
2039         return docbookiteminnerattr_;
2040 }
2041
2042
2043 string const & Layout::docbookiteminnertagtype() const
2044 {
2045         if (!isValidTagType(docbookiteminnertagtype_))
2046                 docbookiteminnertagtype_ = "block";
2047         return docbookiteminnertagtype_;
2048 }
2049
2050
2051 std::string const & Layout::docbookforceabstracttag() const
2052 {
2053         if (docbookforceabstracttag_.empty())
2054                 docbookforceabstracttag_ = "NONE";
2055         return docbookforceabstracttag_;
2056 }
2057
2058
2059
2060 namespace {
2061
2062 string makeMarginValue(char const * side, double d)
2063 {
2064         ostringstream os;
2065         os << "margin-" << side << ": " << d << "ex;\n";
2066         return os.str();
2067 }
2068
2069 } // namespace
2070
2071
2072 void Layout::makeDefaultCSS() const
2073 {
2074         // this never needs to be redone, since reloading layouts will
2075         // wipe out what we did before.
2076         if (!htmldefaultstyle_.empty())
2077                 return;
2078
2079         // main font
2080         htmldefaultstyle_ = font.asCSS();
2081
2082         // bottom margins
2083         string tmp;
2084         if (topsep > 0)
2085                 tmp += makeMarginValue("top", topsep);
2086         if (bottomsep > 0)
2087                 tmp += makeMarginValue("bottom", bottomsep);
2088         if (!leftmargin.empty()) {
2089                 // we can't really do what LyX does with the margin, so
2090                 // we'll just figure out how many characters it is
2091                 int const len = leftmargin.length();
2092                 tmp += makeMarginValue("left", len);
2093         }
2094         if (!rightmargin.empty()) {
2095                 int const len = rightmargin.length();
2096                 tmp += makeMarginValue("right", len);
2097         }
2098
2099         if (!tmp.empty()) {
2100                 if (!htmldefaultstyle_.empty())
2101                         htmldefaultstyle_ += from_ascii("\n");
2102                 htmldefaultstyle_ += from_ascii(tmp);
2103         }
2104
2105         // alignment
2106         string where = alignmentToCSS(align);
2107         if (!where.empty()) {
2108                 htmldefaultstyle_ += from_ascii("text-align: " + where + ";\n");
2109         }
2110
2111         // wrap up what we have, if anything
2112         if (!htmldefaultstyle_.empty())
2113                 htmldefaultstyle_ =
2114                         from_ascii(htmltag() + "." + defaultCSSClass() + " {\n") +
2115                         htmldefaultstyle_ + from_ascii("\n}\n");
2116
2117         if (labeltype == LABEL_NO_LABEL || htmllabeltag() == "NONE")
2118                 return;
2119
2120         docstring labelCSS;
2121
2122         // label font
2123         if (labelfont != font)
2124                 labelCSS = labelfont.asCSS() + from_ascii("\n");
2125         if (labeltype == LABEL_CENTERED)
2126                 labelCSS += from_ascii("text-align: center;\n");
2127
2128         if (!labelCSS.empty())
2129                 htmldefaultstyle_ +=
2130                         from_ascii(htmllabeltag() + "." + defaultCSSLabelClass() + " {\n") +
2131                         labelCSS + from_ascii("\n}\n");
2132 }
2133
2134
2135 bool Layout::operator==(Layout const & rhs) const
2136 {
2137         // This is enough for the applications we actually make,
2138         // at least at the moment. But we could check more.
2139         return name() == rhs.name()
2140                 && latexname() == rhs.latexname()
2141                 && latextype == rhs.latextype;
2142 }
2143
2144
2145 } // namespace lyx