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