]> git.lyx.org Git - lyx.git/blob - src/Layout.cpp
initial basic context menu support.
[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 "TextClass.h"
17 #include "Lexer.h"
18 #include "Font.h"
19 #include "support/debug.h"
20
21
22 #include "support/lstrings.h"
23
24 #include <ostream>
25
26 using namespace std;
27 using namespace lyx::support;
28
29 namespace lyx {
30
31 /// Special value of toclevel for layouts that to not belong in a TOC
32 const int Layout::NOT_IN_TOC = -1000;
33
34 //  The order of the LayoutTags enum is no more important. [asierra300396]
35 // Tags indexes.
36 enum LayoutTags {
37         LT_ALIGN = 1,
38         LT_ALIGNPOSSIBLE,
39         LT_MARGIN,
40         LT_BOTTOMSEP,
41         LT_COMMANDDEPTH,
42         LT_COPYSTYLE,
43         LT_DEPENDSON,
44         LT_OBSOLETEDBY,
45         //LT_EMPTY,
46         LT_END,
47         //LT_ENVIRONMENT_DEFAULT,
48         //LT_FANCYHDR,
49         LT_FILL_BOTTOM,
50         LT_FILL_TOP,
51         //LT_FIRST_COUNTER,
52         LT_FONT,
53         LT_FREE_SPACING,
54         LT_PASS_THRU,
55         //LT_HEADINGS,
56         LT_ITEMSEP,
57         LT_KEEPEMPTY,
58         LT_LABEL_BOTTOMSEP,
59         LT_LABELFONT,
60         LT_TEXTFONT,
61         LT_LABELINDENT,
62         LT_LABELSEP,
63         LT_LABELSTRING,
64         LT_LABELSTRING_APPENDIX,
65         LT_LABELCOUNTER,
66         LT_LABELTYPE,
67         LT_ENDLABELSTRING,
68         LT_ENDLABELTYPE,
69         LT_LATEXNAME,
70         LT_LATEXPARAM,
71         LT_OPTARGS,
72         LT_LATEXTYPE,
73         LT_LATEXHEADER,
74         LT_LATEXFOOTER,
75         LT_LATEXPARAGRAPH,
76         LT_LEFTMARGIN,
77         LT_NEED_PROTECT,
78         LT_NEWLINE,
79         LT_NEXTNOINDENT,
80         LT_PARINDENT,
81         LT_PARSEP,
82         LT_PARSKIP,
83         //LT_PLAIN,
84         LT_PREAMBLE,
85         LT_RIGHTMARGIN,
86         LT_SPACING,
87         LT_TOPSEP,
88         LT_TOCLEVEL,
89         LT_INNERTAG,
90         LT_LABELTAG,
91         LT_ITEMTAG,
92         LT_INTITLE // keep this last!
93 };
94
95 /////////////////////
96
97 Layout::Layout()
98 {
99         margintype = MARGIN_STATIC;
100         latextype = LATEX_PARAGRAPH;
101         intitle = false;
102         optionalargs = 0;
103         needprotect = false;
104         keepempty = false;
105         font = inherit_font;
106         labelfont = inherit_font;
107         resfont = sane_font;
108         reslabelfont = sane_font;
109         nextnoindent = false;
110         parskip = 0.0;
111         itemsep = 0;
112         topsep = 0.0;
113         bottomsep = 0.0;
114         labelbottomsep = 0.0;
115         parsep = 0;
116         align = LYX_ALIGN_BLOCK;
117         alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
118         labeltype = LABEL_NO_LABEL;
119         endlabeltype = END_LABEL_NO_LABEL;
120         // Should or should not. That is the question.
121         // spacing.set(Spacing::OneHalf);
122         fill_top = false;
123         fill_bottom = false;
124         newline_allowed = true;
125         free_spacing = false;
126         pass_thru = false;
127         is_environment = false;
128         toclevel = NOT_IN_TOC;
129         commanddepth = 0;
130 }
131
132
133 bool Layout::read(Lexer & lexrc, TextClass const & tclass)
134 {
135         // This table is sorted alphabetically [asierra 30March96]
136         keyword_item layoutTags[] = {
137                 { "align",          LT_ALIGN },
138                 { "alignpossible",  LT_ALIGNPOSSIBLE },
139                 { "bottomsep",      LT_BOTTOMSEP },
140                 { "commanddepth",   LT_COMMANDDEPTH },
141                 { "copystyle",      LT_COPYSTYLE },
142                 { "dependson",      LT_DEPENDSON },
143                 { "end",            LT_END },
144                 { "endlabelstring", LT_ENDLABELSTRING },
145                 { "endlabeltype",   LT_ENDLABELTYPE },
146                 { "fill_bottom",    LT_FILL_BOTTOM },
147                 { "fill_top",       LT_FILL_TOP },
148                 { "font",           LT_FONT },
149                 { "freespacing",    LT_FREE_SPACING },
150                 { "innertag",       LT_INNERTAG },
151                 { "intitle",        LT_INTITLE },
152                 { "itemsep",        LT_ITEMSEP },
153                 { "itemtag",        LT_ITEMTAG },
154                 { "keepempty",      LT_KEEPEMPTY },
155                 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
156                 { "labelcounter",   LT_LABELCOUNTER },
157                 { "labelfont",      LT_LABELFONT },
158                 { "labelindent",    LT_LABELINDENT },
159                 { "labelsep",       LT_LABELSEP },
160                 { "labelstring",    LT_LABELSTRING },
161                 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
162                 { "labeltag",       LT_LABELTAG },
163                 { "labeltype",      LT_LABELTYPE },
164                 { "latexfooter",    LT_LATEXFOOTER },
165                 { "latexheader",    LT_LATEXHEADER },
166                 { "latexname",      LT_LATEXNAME },
167                 { "latexparagraph", LT_LATEXPARAGRAPH },
168                 { "latexparam",     LT_LATEXPARAM },
169                 { "latextype",      LT_LATEXTYPE },
170                 { "leftmargin",     LT_LEFTMARGIN },
171                 { "margin",         LT_MARGIN },
172                 { "needprotect",    LT_NEED_PROTECT },
173                 { "newline",        LT_NEWLINE },
174                 { "nextnoindent",   LT_NEXTNOINDENT },
175                 { "obsoletedby",    LT_OBSOLETEDBY },
176                 { "optionalargs",   LT_OPTARGS },
177                 { "parindent",      LT_PARINDENT },
178                 { "parsep",         LT_PARSEP },
179                 { "parskip",        LT_PARSKIP },
180                 { "passthru",       LT_PASS_THRU },
181                 { "preamble",       LT_PREAMBLE },
182                 { "rightmargin",    LT_RIGHTMARGIN },
183                 { "spacing",        LT_SPACING },
184                 { "textfont",       LT_TEXTFONT },
185                 { "toclevel",       LT_TOCLEVEL },
186                 { "topsep",         LT_TOPSEP }
187         };
188
189         bool error = false;
190         bool finished = false;
191         lexrc.pushTable(layoutTags, LT_INTITLE);
192         // parse style section
193         while (!finished && lexrc.isOK() && !error) {
194                 int le = lexrc.lex();
195                 // See comment in LyXRC.cpp.
196                 switch (le) {
197                 case Lexer::LEX_FEOF:
198                         continue;
199
200                 case Lexer::LEX_UNDEF:          // parse error
201                         lexrc.printError("Unknown layout tag `$$Token'");
202                         error = true;
203                         continue;
204                 default: break;
205                 }
206                 switch (static_cast<LayoutTags>(le)) {
207                 case LT_END:            // end of structure
208                         finished = true;
209                         break;
210
211                 case LT_COPYSTYLE:     // initialize with a known style
212                         if (lexrc.next()) {
213                                 docstring const style = subst(lexrc.getDocString(),
214                                                                 '_', ' ');
215
216                                 if (tclass.hasLayout(style)) {
217                                         docstring const tmpname = name_;
218                                         this->operator=(*tclass[style]);
219                                         name_ = tmpname;
220                                 } else {
221                                         lyxerr << "Cannot copy unknown style `"
222                                                << to_utf8(style) << "'\n"
223                                                << "All layouts so far:"
224                                                << endl;
225                                         TextClass::const_iterator it =
226                                                 tclass.begin();
227                                         TextClass::const_iterator end =
228                                                 tclass.end();
229                                         for (; it != end; ++it) {
230                                                 lyxerr << to_utf8((*it)->name())
231                                                        << endl;
232                                         }
233
234                                         //lexrc.printError("Cannot copy known "
235                                         //               "style `$$Token'");
236                                 }
237                         }
238                         break;
239
240                 case LT_OBSOLETEDBY:     // replace with a known style
241                         if (lexrc.next()) {
242                                 docstring const style = 
243                                         subst(lexrc.getDocString(), '_', ' ');
244
245                                 if (tclass.hasLayout(style)) {
246                                         docstring const tmpname = name_;
247                                         this->operator=(*tclass[style]);
248                                         name_ = tmpname;
249                                         if (obsoleted_by().empty())
250                                                 obsoleted_by_ = style;
251                                 } else {
252                                         lyxerr << "Cannot replace with unknown style `" 
253                                                 << to_utf8(style) << '\'' << endl;
254
255                                         //lexrc.printError("Cannot replace with"
256                                         //               " unknown style "
257                                         //               "`$$Token'");
258                                 }
259                         }
260                         break;
261
262                 case LT_DEPENDSON:
263                         if (lexrc.next())
264                         depends_on_ = subst(lexrc.getDocString(), '_', ' ');
265                         break;
266
267                 case LT_MARGIN:         // margin style definition.
268                         readMargin(lexrc);
269                         break;
270
271                 case LT_LATEXTYPE:      // LaTeX style definition.
272                         readLatexType(lexrc);
273                         break;
274
275                 case LT_LATEXHEADER:    // header for environments
276                         lexrc.next();
277                         latexheader = lexrc.getString();
278                         break;
279
280                 case LT_LATEXFOOTER:    // footer for environments
281                         lexrc.next();
282                         latexfooter = lexrc.getString();
283                         break;
284
285                 case LT_LATEXPARAGRAPH:
286                         lexrc.next();
287                         latexparagraph = lexrc.getString();
288                         break;
289
290                 case LT_INTITLE:
291                         intitle = lexrc.next() && lexrc.getInteger();
292                         break;
293
294                 case LT_TOCLEVEL:
295                         lexrc.next();
296                         toclevel = lexrc.getInteger();
297                         break;
298
299                 case LT_OPTARGS:
300                         if (lexrc.next())
301                                 optionalargs = lexrc.getInteger();
302                         break;
303
304                 case LT_NEED_PROTECT:
305                         needprotect = lexrc.next() && lexrc.getInteger();
306                         break;
307
308                 case LT_KEEPEMPTY:
309                         keepempty = lexrc.next() && lexrc.getInteger();
310                         break;
311
312                 case LT_FONT:
313                         font = lyxRead(lexrc, font);
314                         labelfont = font;
315                         break;
316
317                 case LT_TEXTFONT:
318                         font = lyxRead(lexrc, font);
319                         break;
320
321                 case LT_LABELFONT:
322                         labelfont = lyxRead(lexrc, labelfont);
323                         break;
324
325                 case LT_NEXTNOINDENT:   // Indent next paragraph?
326                         if (lexrc.next() && lexrc.getInteger())
327                                 nextnoindent = true;
328                         else
329                                 nextnoindent = false;
330                         break;
331
332                 case LT_COMMANDDEPTH:
333                         lexrc.next();
334                         commanddepth = lexrc.getInteger();
335                         break;
336
337                 case LT_LATEXNAME:
338                         if (lexrc.next())
339                                 latexname_ = lexrc.getString();
340                         break;
341
342                 case LT_LATEXPARAM:
343                         if (lexrc.next())
344                                 latexparam_ = subst(lexrc.getString(), "&quot;", "\"");
345                         break;
346
347                 case LT_INNERTAG:
348                         if (lexrc.next())
349                                 innertag_ = lexrc.getString();
350                         break;
351
352                 case LT_LABELTAG:
353                         if (lexrc.next())
354                                 labeltag_ = lexrc.getString();
355                         break;
356
357                 case LT_ITEMTAG:
358                         if (lexrc.next())
359                                 itemtag_ = lexrc.getString();
360                         break;
361
362                 case LT_PREAMBLE:
363                         preamble_ = from_utf8(lexrc.getLongString("EndPreamble"));
364                         break;
365
366                 case LT_LABELTYPE:
367                         readLabelType(lexrc);
368                         break;
369
370                 case LT_ENDLABELTYPE:
371                         readEndLabelType(lexrc);
372                         break;
373
374                 case LT_LEFTMARGIN:     // left margin type
375                         if (lexrc.next())
376                                 leftmargin = lexrc.getDocString();
377                         break;
378
379                 case LT_RIGHTMARGIN:    // right margin type
380                         if (lexrc.next())
381                                 rightmargin = lexrc.getDocString();
382                         break;
383
384                 case LT_LABELINDENT:    // label indenting flag
385                         if (lexrc.next())
386                                 labelindent = lexrc.getDocString();
387                         break;
388
389                 case LT_PARINDENT:      // paragraph indent. flag
390                         if (lexrc.next())
391                                 parindent = lexrc.getDocString();
392                         break;
393
394                 case LT_PARSKIP:        // paragraph skip size
395                         if (lexrc.next())
396                                 parskip = lexrc.getFloat();
397                         break;
398
399                 case LT_ITEMSEP:        // item separation size
400                         if (lexrc.next())
401                                 itemsep = lexrc.getFloat();
402                         break;
403
404                 case LT_TOPSEP:         // top separation size
405                         if (lexrc.next())
406                                 topsep = lexrc.getFloat();
407                         break;
408
409                 case LT_BOTTOMSEP:      // bottom separation size
410                         if (lexrc.next())
411                                 bottomsep = lexrc.getFloat();
412                         break;
413
414                 case LT_LABEL_BOTTOMSEP: // label bottom separation size
415                         if (lexrc.next())
416                                 labelbottomsep = lexrc.getFloat();
417                         break;
418
419                 case LT_LABELSEP:       // label separator
420                         if (lexrc.next()) {
421                                 labelsep = from_utf8(subst(lexrc.getString(), 'x', ' '));
422                         }
423                         break;
424
425                 case LT_PARSEP:         // par. separation size
426                         if (lexrc.next())
427                                 parsep = lexrc.getFloat();
428                         break;
429
430                 case LT_FILL_TOP:       // fill top flag
431                         if (lexrc.next())
432                                 fill_top = lexrc.getInteger();
433                         break;
434
435                 case LT_FILL_BOTTOM:    // fill bottom flag
436                         if (lexrc.next())
437                                 fill_bottom = lexrc.getInteger();
438                         break;
439
440                 case LT_NEWLINE:        // newlines allowed?
441                         if (lexrc.next())
442                                 newline_allowed = lexrc.getInteger();
443                         break;
444
445                 case LT_ALIGN:          // paragraph align
446                         readAlign(lexrc);
447                         break;
448                 case LT_ALIGNPOSSIBLE:  // paragraph allowed align
449                         readAlignPossible(lexrc);
450                         break;
451
452                 case LT_LABELSTRING:    // label string definition
453                         if (lexrc.next()) {
454                                 labelstring_ = trim(lexrc.getDocString());
455                                 labelstring_appendix_ = labelstring_;
456                         }
457                         break;
458
459                 case LT_ENDLABELSTRING: // endlabel string definition
460                         if (lexrc.next())
461                                 endlabelstring_ = trim(lexrc.getDocString());
462                         break;
463
464                 case LT_LABELSTRING_APPENDIX: // label string appendix definition
465                         if (lexrc.next())
466                                 labelstring_appendix_ = trim(lexrc.getDocString());
467                         break;
468
469                 case LT_LABELCOUNTER: // name of counter to use
470                         if (lexrc.next())
471                                 counter = lyx::from_ascii(trim(lexrc.getString()));
472                         break;
473
474                 case LT_FREE_SPACING:   // Allow for free spacing.
475                         if (lexrc.next())
476                                 free_spacing = lexrc.getInteger();
477                         break;
478
479                 case LT_PASS_THRU:      // Allow for pass thru.
480                         if (lexrc.next())
481                                 pass_thru = lexrc.getInteger();
482                         break;
483
484                 case LT_SPACING: // setspace.sty
485                         readSpacing(lexrc);
486                         break;
487                 }
488         }
489         lexrc.popTable();
490
491         return error;
492 }
493
494
495 enum AlignTags {
496         AT_BLOCK = 1,
497         AT_LEFT,
498         AT_RIGHT,
499         AT_CENTER,
500         AT_LAYOUT
501 };
502
503
504 void Layout::readAlign(Lexer & lexrc)
505 {
506         keyword_item alignTags[] = {
507                 { "block",  AT_BLOCK },
508                 { "center", AT_CENTER },
509                 { "layout", AT_LAYOUT },
510                 { "left",   AT_LEFT },
511                 { "right",  AT_RIGHT }
512         };
513
514         PushPopHelper pph(lexrc, alignTags, AT_LAYOUT);
515         int le = lexrc.lex();
516         switch (le) {
517         case Lexer::LEX_UNDEF:
518                 lexrc.printError("Unknown alignment `$$Token'");
519                 return;
520         default: break;
521         };
522         switch (static_cast<AlignTags>(le)) {
523         case AT_BLOCK:
524                 align = LYX_ALIGN_BLOCK;
525                 break;
526         case AT_LEFT:
527                 align = LYX_ALIGN_LEFT;
528                 break;
529         case AT_RIGHT:
530                 align = LYX_ALIGN_RIGHT;
531                 break;
532         case AT_CENTER:
533                 align = LYX_ALIGN_CENTER;
534                 break;
535         case AT_LAYOUT:
536                 align = LYX_ALIGN_LAYOUT;
537                 break;
538         }
539 }
540
541
542 void Layout::readAlignPossible(Lexer & lexrc)
543 {
544         keyword_item alignTags[] = {
545                 { "block",  AT_BLOCK },
546                 { "center", AT_CENTER },
547                 { "layout", AT_LAYOUT },
548                 { "left",   AT_LEFT },
549                 { "right",  AT_RIGHT }
550         };
551
552         lexrc.pushTable(alignTags, AT_LAYOUT);
553         alignpossible = LYX_ALIGN_NONE | LYX_ALIGN_LAYOUT;
554         int lineno = lexrc.getLineNo();
555         do {
556                 int le = lexrc.lex();
557                 switch (le) {
558                 case Lexer::LEX_UNDEF:
559                         lexrc.printError("Unknown alignment `$$Token'");
560                         continue;
561                 default: break;
562                 };
563                 switch (static_cast<AlignTags>(le)) {
564                 case AT_BLOCK:
565                         alignpossible |= LYX_ALIGN_BLOCK;
566                         break;
567                 case AT_LEFT:
568                         alignpossible |= LYX_ALIGN_LEFT;
569                         break;
570                 case AT_RIGHT:
571                         alignpossible |= LYX_ALIGN_RIGHT;
572                         break;
573                 case AT_CENTER:
574                         alignpossible |= LYX_ALIGN_CENTER;
575                         break;
576                 case AT_LAYOUT:
577                         alignpossible |= LYX_ALIGN_LAYOUT;
578                         break;
579                 }
580         } while (lineno == lexrc.getLineNo());
581         lexrc.popTable();
582 }
583
584
585 enum LabelTypeTags {
586         LA_NO_LABEL = 1,
587         LA_MANUAL,
588         LA_TOP_ENVIRONMENT,
589         LA_CENTERED_TOP_ENVIRONMENT,
590         LA_STATIC,
591         LA_SENSITIVE,
592         LA_COUNTER,
593         LA_ENUMERATE,
594         LA_ITEMIZE,
595         LA_BIBLIO
596 };
597
598
599 void Layout::readLabelType(Lexer & lexrc)
600 {
601         keyword_item labelTypeTags[] = {
602         { "bibliography",             LA_BIBLIO },
603         { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
604         { "counter",                  LA_COUNTER },
605         { "enumerate",                LA_ENUMERATE },
606         { "itemize",                  LA_ITEMIZE },
607         { "manual",                   LA_MANUAL },
608         { "no_label",                 LA_NO_LABEL },
609         { "sensitive",                LA_SENSITIVE },
610         { "static",                   LA_STATIC },
611         { "top_environment",          LA_TOP_ENVIRONMENT }
612         };
613
614         PushPopHelper pph(lexrc, labelTypeTags, LA_BIBLIO);
615         int le = lexrc.lex();
616         switch (le) {
617         case Lexer::LEX_UNDEF:
618                 lexrc.printError("Unknown labeltype tag `$$Token'");
619                 return;
620         default: break;
621         }
622         switch (static_cast<LabelTypeTags>(le)) {
623         case LA_NO_LABEL:
624                 labeltype = LABEL_NO_LABEL;
625                 break;
626         case LA_MANUAL:
627                 labeltype = LABEL_MANUAL;
628                 break;
629         case LA_TOP_ENVIRONMENT:
630                 labeltype = LABEL_TOP_ENVIRONMENT;
631                 break;
632         case LA_CENTERED_TOP_ENVIRONMENT:
633                 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
634                 break;
635         case LA_STATIC:
636                 labeltype = LABEL_STATIC;
637                 break;
638         case LA_SENSITIVE:
639                 labeltype = LABEL_SENSITIVE;
640                 break;
641         case LA_COUNTER:
642                 labeltype = LABEL_COUNTER;
643                 break;
644         case LA_ENUMERATE:
645                 labeltype = LABEL_ENUMERATE;
646                 break;
647         case LA_ITEMIZE:
648                 labeltype = LABEL_ITEMIZE;
649                 break;
650         case LA_BIBLIO:
651                 labeltype = LABEL_BIBLIO;
652                 break;
653         }
654 }
655
656
657 static keyword_item endlabelTypeTags[] =
658 {
659         { "box",        END_LABEL_BOX },
660         { "filled_box", END_LABEL_FILLED_BOX },
661         { "no_label",   END_LABEL_NO_LABEL },
662         { "static",     END_LABEL_STATIC }
663 };
664
665
666 void Layout::readEndLabelType(Lexer & lexrc)
667 {
668         PushPopHelper pph(lexrc, endlabelTypeTags,
669                           END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
670         int le = lexrc.lex();
671         switch (le) {
672         case Lexer::LEX_UNDEF:
673                 lexrc.printError("Unknown labeltype tag `$$Token'");
674                 break;
675         case END_LABEL_STATIC:
676         case END_LABEL_BOX:
677         case END_LABEL_FILLED_BOX:
678         case END_LABEL_NO_LABEL:
679                 endlabeltype = static_cast<EndLabelType>(le);
680                 break;
681         default:
682                 lyxerr << "Unhandled value " << le
683                        << " in Layout::readEndLabelType." << endl;
684                 break;
685         }
686 }
687
688
689 void Layout::readMargin(Lexer & lexrc)
690 {
691         keyword_item marginTags[] = {
692                 { "dynamic",           MARGIN_DYNAMIC },
693                 { "first_dynamic",     MARGIN_FIRST_DYNAMIC },
694                 { "manual",            MARGIN_MANUAL },
695                 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
696                 { "static",            MARGIN_STATIC }
697         };
698
699         PushPopHelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
700
701         int le = lexrc.lex();
702         switch (le) {
703         case Lexer::LEX_UNDEF:
704                 lexrc.printError("Unknown margin type tag `$$Token'");
705                 return;
706         case MARGIN_STATIC:
707         case MARGIN_MANUAL:
708         case MARGIN_DYNAMIC:
709         case MARGIN_FIRST_DYNAMIC:
710         case MARGIN_RIGHT_ADDRESS_BOX:
711                 margintype = static_cast<MarginType>(le);
712                 break;
713         default:
714                 lyxerr << "Unhandled value " << le
715                        << " in Layout::readMargin." << endl;
716                 break;
717         }
718 }
719
720
721 void Layout::readLatexType(Lexer & lexrc)
722 {
723         keyword_item latexTypeTags[] = {
724                 { "bib_environment",  LATEX_BIB_ENVIRONMENT },
725                 { "command",          LATEX_COMMAND },
726                 { "environment",      LATEX_ENVIRONMENT },
727                 { "item_environment", LATEX_ITEM_ENVIRONMENT },
728                 { "list_environment", LATEX_LIST_ENVIRONMENT },
729                 { "paragraph",        LATEX_PARAGRAPH }
730         };
731
732         PushPopHelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
733         int le = lexrc.lex();
734         switch (le) {
735         case Lexer::LEX_UNDEF:
736                 lexrc.printError("Unknown latextype tag `$$Token'");
737                 return;
738         case LATEX_PARAGRAPH:
739         case LATEX_COMMAND:
740         case LATEX_ENVIRONMENT:
741         case LATEX_ITEM_ENVIRONMENT:
742         case LATEX_BIB_ENVIRONMENT:
743         case LATEX_LIST_ENVIRONMENT:
744                 latextype = static_cast<LatexType>(le);
745                 break;
746         default:
747                 lyxerr << "Unhandled value " << le
748                        << " in Layout::readLatexType." << endl;
749                 break;
750         }
751 }
752
753
754 enum SpacingTags {
755         ST_SPACING_SINGLE = 1,
756         ST_SPACING_ONEHALF,
757         ST_SPACING_DOUBLE,
758         ST_OTHER
759 };
760
761
762 void Layout::readSpacing(Lexer & lexrc)
763 {
764         keyword_item spacingTags[] = {
765                 {"double",  ST_SPACING_DOUBLE },
766                 {"onehalf", ST_SPACING_ONEHALF },
767                 {"other",   ST_OTHER },
768                 {"single",  ST_SPACING_SINGLE }
769         };
770
771         PushPopHelper pph(lexrc, spacingTags, ST_OTHER);
772         int le = lexrc.lex();
773         switch (le) {
774         case Lexer::LEX_UNDEF:
775                 lexrc.printError("Unknown spacing token `$$Token'");
776                 return;
777         default: break;
778         }
779         switch (static_cast<SpacingTags>(le)) {
780         case ST_SPACING_SINGLE:
781                 spacing.set(Spacing::Single);
782                 break;
783         case ST_SPACING_ONEHALF:
784                 spacing.set(Spacing::Onehalf);
785                 break;
786         case ST_SPACING_DOUBLE:
787                 spacing.set(Spacing::Double);
788                 break;
789         case ST_OTHER:
790                 lexrc.next();
791                 spacing.set(Spacing::Other, lexrc.getString());
792                 break;
793         }
794 }
795
796
797 docstring const & Layout::name() const
798 {
799         return name_;
800 }
801
802
803 void Layout::setName(docstring const & name)
804 {
805         name_ = name;
806 }
807
808
809 docstring const & Layout::obsoleted_by() const
810 {
811         return obsoleted_by_;
812 }
813
814
815 docstring const & Layout::depends_on() const
816 {
817         return depends_on_;
818 }
819
820
821 Layout * Layout::forCaption()
822 {
823         Layout * lay = new Layout();
824         lay->name_ = from_ascii("Caption");
825         lay->latexname_ = "caption";
826         lay->latextype = LATEX_COMMAND;
827         lay->optionalargs = 1;
828         return lay;
829 }
830
831 } // namespace lyx