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