]> git.lyx.org Git - lyx.git/blob - src/layout.C
paragraph-spacing, redoparagraph in deleteemptyparagraphmechanism, got rid of some...
[lyx.git] / src / layout.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include <algorithm>
18
19 #include "layout.h"
20 #include "lyxlex.h"
21 #include "support/filetools.h"
22 #include "lyx_gui_misc.h"
23 #include "debug.h"
24 #include "gettext.h"
25 #include "support/LAssert.h"
26
27 using std::pair;
28 using std::make_pair;
29 using std::sort;
30 using std::endl;
31
32 // Global variable: textclass table.
33 LyXTextClassList textclasslist;
34
35
36 // Reads the style files
37 void LyXSetStyle()
38 {
39         lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
40         
41         if (!textclasslist.Read()) {
42                 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
43                         "during parsing.\n             Exiting." << endl;
44                 exit(1);
45         }
46
47         lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
48 }
49
50
51 //  The order of the LayoutTags enum is no more important. [asierra300396]
52 // Tags indexes.
53 enum LayoutTags {
54         LT_ALIGN = 1, 
55         LT_ALIGNPOSSIBLE, 
56         LT_MARGIN, 
57         LT_BOTTOMSEP, 
58         LT_COPYSTYLE, 
59         LT_OBSOLETEDBY, 
60         //LT_EMPTY,
61         LT_END, 
62         //LT_ENVIRONMENT_DEFAULT, 
63         //LT_FANCYHDR,
64         LT_FILL_BOTTOM, 
65         LT_FILL_TOP, 
66         //LT_FIRST_COUNTER,
67         LT_FONT, 
68         LT_FREE_SPACING, 
69         //LT_HEADINGS,
70         LT_ITEMSEP, 
71         LT_KEEPEMPTY, 
72         LT_LABEL_BOTTOMSEP, 
73         LT_LABELFONT, 
74         LT_TEXTFONT,
75         LT_LABELINDENT, 
76         LT_LABELSEP, 
77         LT_LABELSTRING, 
78         LT_LABELSTRING_APPENDIX, 
79         LT_LABELTYPE,
80         LT_ENDLABELTYPE,
81         LT_LATEXNAME, 
82         LT_LATEXPARAM, 
83         LT_LATEXTYPE, 
84         LT_LEFTMARGIN, 
85         LT_NEED_PROTECT, 
86         LT_NEWLINE, 
87         LT_NEXTNOINDENT, 
88         LT_PARINDENT, 
89         LT_PARSEP, 
90         LT_PARSKIP, 
91         //LT_PLAIN,
92         LT_PREAMBLE, 
93         LT_RIGHTMARGIN, 
94         LT_SPACING, 
95         LT_TOPSEP, 
96         LT_INTITLE 
97 };
98
99
100 #if 0
101 // This table is sorted alphabetically [asierra 30March96]
102 static keyword_item layoutTags[] = {
103         { "align",                      LT_ALIGN },
104         { "alignpossible",              LT_ALIGNPOSSIBLE },
105         { "bottomsep",                  LT_BOTTOMSEP },
106         { "copystyle",                  LT_COPYSTYLE },
107         { "end",                        LT_END },
108         { "endlabeltype",               LT_ENDLABELTYPE },
109         { "fill_bottom",                LT_FILL_BOTTOM },
110         { "fill_top",                   LT_FILL_TOP },
111         { "font",                       LT_FONT },
112         { "freespacing",                LT_FREE_SPACING },
113         { "intitle",                    LT_INTITLE },
114         { "itemsep",                    LT_ITEMSEP },
115         { "keepempty",                  LT_KEEPEMPTY },
116         { "labelbottomsep",             LT_LABEL_BOTTOMSEP },
117         { "labelfont",                  LT_LABELFONT },
118         { "labelindent",                LT_LABELINDENT },
119         { "labelsep",                   LT_LABELSEP },
120         { "labelstring",                LT_LABELSTRING },
121         { "labelstringappendix",        LT_LABELSTRING_APPENDIX },
122         { "labeltype",                  LT_LABELTYPE },
123         { "latexname",                  LT_LATEXNAME },
124         { "latexparam",                 LT_LATEXPARAM },
125         { "latextype",                  LT_LATEXTYPE },
126         { "leftmargin",                 LT_LEFTMARGIN },
127         { "margin",                     LT_MARGIN },
128         { "needprotect",                LT_NEED_PROTECT },
129         { "newline",                    LT_NEWLINE },
130         { "nextnoindent",               LT_NEXTNOINDENT },
131         { "obsoletedby",                LT_OBSOLETEDBY },
132         { "parindent",                  LT_PARINDENT },
133         { "parsep",                     LT_PARSEP },
134         { "parskip",                    LT_PARSKIP },
135         { "preamble",                   LT_PREAMBLE },
136         { "rightmargin",                LT_RIGHTMARGIN },
137         { "spacing",                    LT_SPACING },
138         { "textfont",                   LT_TEXTFONT },
139         { "topsep",                     LT_TOPSEP }
140 };
141 #endif
142
143
144 /////////////////////
145
146 // Constructor for layout
147 LyXLayout::LyXLayout ()
148 {
149         margintype = MARGIN_STATIC;
150         latextype = LATEX_PARAGRAPH;
151         intitle = false;
152         needprotect = false;
153         keepempty = false;
154         font = LyXFont(LyXFont::ALL_INHERIT);
155         labelfont = LyXFont(LyXFont::ALL_INHERIT);
156         resfont = LyXFont(LyXFont::ALL_SANE);
157         reslabelfont = LyXFont(LyXFont::ALL_SANE);
158         nextnoindent = false;
159         parskip = 0.0;
160         itemsep = 0;
161         topsep = 0.0;
162         bottomsep = 0.0;
163         labelbottomsep = 0.0;
164         parsep = 0;
165         align = LYX_ALIGN_BLOCK;
166         alignpossible = LYX_ALIGN_BLOCK;
167         labeltype = LABEL_NO_LABEL;
168         endlabeltype = END_LABEL_NO_LABEL;
169         // Should or should not. That is the question.
170         // spacing.set(Spacing::OneHalf);
171         fill_top = false;
172         fill_bottom = false;
173         newline_allowed = true;
174         free_spacing = false;
175 }
176
177
178 // Reads a layout definition from file
179 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
180 {
181 #if 1
182         // This table is sorted alphabetically [asierra 30March96]
183         keyword_item layoutTags[] = {
184                 { "align",                      LT_ALIGN },
185                 { "alignpossible",              LT_ALIGNPOSSIBLE },
186                 { "bottomsep",                  LT_BOTTOMSEP },
187                 { "copystyle",                  LT_COPYSTYLE },
188                 { "end",                        LT_END },
189                 { "endlabeltype",               LT_ENDLABELTYPE },
190                 { "fill_bottom",                LT_FILL_BOTTOM },
191                 { "fill_top",                   LT_FILL_TOP },
192                 { "font",                       LT_FONT },
193                 { "freespacing",                LT_FREE_SPACING },
194                 { "intitle",                    LT_INTITLE },
195                 { "itemsep",                    LT_ITEMSEP },
196                 { "keepempty",                  LT_KEEPEMPTY },
197                 { "labelbottomsep",             LT_LABEL_BOTTOMSEP },
198                 { "labelfont",                  LT_LABELFONT },
199                 { "labelindent",                LT_LABELINDENT },
200                 { "labelsep",                   LT_LABELSEP },
201                 { "labelstring",                LT_LABELSTRING },
202                 { "labelstringappendix",        LT_LABELSTRING_APPENDIX },
203                 { "labeltype",                  LT_LABELTYPE },
204                 { "latexname",                  LT_LATEXNAME },
205                 { "latexparam",                 LT_LATEXPARAM },
206                 { "latextype",                  LT_LATEXTYPE },
207                 { "leftmargin",                 LT_LEFTMARGIN },
208                 { "margin",                     LT_MARGIN },
209                 { "needprotect",                LT_NEED_PROTECT },
210                 { "newline",                    LT_NEWLINE },
211                 { "nextnoindent",               LT_NEXTNOINDENT },
212                 { "obsoletedby",                LT_OBSOLETEDBY },
213                 { "parindent",                  LT_PARINDENT },
214                 { "parsep",                     LT_PARSEP },
215                 { "parskip",                    LT_PARSKIP },
216                 { "preamble",                   LT_PREAMBLE },
217                 { "rightmargin",                LT_RIGHTMARGIN },
218                 { "spacing",                    LT_SPACING },
219                 { "textfont",                   LT_TEXTFONT },
220                 { "topsep",                     LT_TOPSEP }
221         };
222 #endif
223         bool error = false;
224         bool finished = false;
225         lexrc.pushTable(layoutTags, LT_INTITLE);
226         // parse style section
227         while (!finished && lexrc.IsOK() && !error) {
228                 int le = lexrc.lex();
229                 // See comment in lyxrc.C.
230                 switch(le) {
231                 case LyXLex::LEX_FEOF:
232                         continue; 
233
234                 case LyXLex::LEX_UNDEF:         // parse error
235                         lexrc.printError("Unknown layout tag `$$Token'");
236                         error = true;
237                         continue; 
238                 default: break;
239                 }
240                 switch(static_cast<LayoutTags>(le)) {
241                 case LT_END:            // end of structure
242                         finished = true;
243                         break;
244
245                 case LT_COPYSTYLE:     // initialize with a known style
246                         if (lexrc.next()) {
247                                 if (tclass.hasLayout(lexrc.GetString())) {
248                                         string tmpname = name_;
249                                         this->operator= (tclass.GetLayout(lexrc.GetString()));
250                                         name_ = tmpname;
251                                 } else {
252                                         lexrc.printError("Cannot copy known "
253                                                          "style `$$Token'");
254                                 }
255                         }
256                         break;
257
258                 case LT_OBSOLETEDBY:     // replace with a known style
259                         if (lexrc.next()) {
260                                 if (tclass.hasLayout(lexrc.GetString())) {
261                                         string tmpname = name_;
262                                         this->operator= (tclass.GetLayout(lexrc.GetString()));
263                                         name_ = tmpname;
264                                         if (obsoleted_by().empty())
265                                           obsoleted_by_ = lexrc.GetString();
266                                 } else {
267                                         lexrc.printError("Cannot replace with" 
268                                                          " unknown style "
269                                                          "`$$Token'");
270                                 }
271                         }
272                         break;
273
274                 case LT_MARGIN:         // Margin style definition.
275                         readMargin(lexrc);
276                         break;
277
278                 case LT_LATEXTYPE:      // Latex style definition.
279                         readLatexType(lexrc);
280                         break;
281
282                 case LT_INTITLE:
283                         intitle = lexrc.next() && lexrc.GetInteger();
284                         break;
285                         
286                 case LT_NEED_PROTECT:
287                         needprotect = lexrc.next() && lexrc.GetInteger();
288                         break;
289                         
290                 case LT_KEEPEMPTY:
291                         keepempty = lexrc.next() && lexrc.GetInteger();
292                         break;
293
294                 case LT_FONT:
295                         font.lyxRead(lexrc);
296                         labelfont= font;
297                         break;
298
299                 case LT_TEXTFONT:
300                         font.lyxRead(lexrc);
301                         break;
302
303                 case LT_LABELFONT:
304                         labelfont.lyxRead(lexrc);
305                         break;
306
307                 case LT_NEXTNOINDENT:   // Indent next paragraph?
308                         if (lexrc.next() && lexrc.GetInteger())
309                                 nextnoindent = true;
310                         else
311                                 nextnoindent = false;
312                         break;
313
314                 case LT_LATEXNAME:
315                         if (lexrc.next())
316                                 latexname_ = lexrc.GetString();
317                         break;
318                         
319                 case LT_LATEXPARAM:
320                         if (lexrc.next())
321                                 latexparam_ = lexrc.GetString();
322                         break;
323
324                 case LT_PREAMBLE:
325                         preamble_ = lexrc.getLongString("EndPreamble");
326                         break;
327
328                 case LT_LABELTYPE:
329                         readLabelType(lexrc);
330                         break;
331
332                 case LT_ENDLABELTYPE:
333                         readEndLabelType(lexrc);
334                         break;
335                         
336                 case LT_LEFTMARGIN:     // left margin type
337                         if (lexrc.next())
338                                 leftmargin = lexrc.GetString();
339                         break;                  
340
341                 case LT_RIGHTMARGIN:    // right margin type
342                         if (lexrc.next())
343                                 rightmargin = lexrc.GetString();
344                         break;
345
346                 case LT_LABELINDENT:    // label indenting flag
347                         if (lexrc.next())
348                                 labelindent = lexrc.GetString();
349                         break;
350
351                 case LT_PARINDENT:      // paragraph indent. flag
352                         if (lexrc.next())
353                                 parindent = lexrc.GetString();
354                         break;
355
356                 case LT_PARSKIP:        // paragraph skip size
357                         if (lexrc.next())
358                                 parskip = lexrc.GetFloat();
359                         break;
360
361                 case LT_ITEMSEP:        // item separation size
362                         if (lexrc.next())
363                                 itemsep = lexrc.GetFloat();
364                         break;
365
366                 case LT_TOPSEP:         // top separation size
367                         if (lexrc.next())
368                                 topsep = lexrc.GetFloat();
369                         break;
370
371                 case LT_BOTTOMSEP:      // bottom separation size
372                         if (lexrc.next())
373                                 bottomsep = lexrc.GetFloat();
374                         break;
375
376                 case LT_LABEL_BOTTOMSEP: // label bottom separation size
377                         if (lexrc.next())
378                                 labelbottomsep = lexrc.GetFloat();
379                         break;
380
381                 case LT_LABELSEP:       // label separator
382                         if (lexrc.next()) {
383                                 labelsep = subst(lexrc.GetString(), 'x', ' ');
384                         }
385                         break;
386
387                 case LT_PARSEP:         // par. separation size
388                         if (lexrc.next())
389                                 parsep = lexrc.GetFloat();
390                         break;
391
392                 case LT_FILL_TOP:       // fill top flag
393                         if (lexrc.next())
394                                 fill_top = lexrc.GetInteger();
395                         break;
396
397                 case LT_FILL_BOTTOM:    // fill bottom flag
398                         if (lexrc.next())
399                                 fill_bottom = lexrc.GetInteger();
400                         break;
401
402                 case LT_NEWLINE:        // newlines allowed?
403                         if (lexrc.next())
404                                 newline_allowed = lexrc.GetInteger();
405                         break;
406
407                 case LT_ALIGN:          // paragraph align
408                         readAlign(lexrc);
409                         break;
410                 case LT_ALIGNPOSSIBLE:  // paragraph allowed align
411                         readAlignPossible(lexrc);
412                         break;
413
414                 case LT_LABELSTRING:    // label string definition
415                         if (lexrc.next())
416                                 labelstring_ = lexrc.GetString();
417                         break;
418
419                 case LT_LABELSTRING_APPENDIX: // label string appendix definition
420                         if (lexrc.next())
421                                 labelstring_appendix_ = lexrc.GetString();
422                         break;
423
424                 case LT_FREE_SPACING:   // Allow for free spacing.
425                         if (lexrc.next())
426                                 free_spacing = lexrc.GetInteger();
427                         break;
428
429                 case LT_SPACING: // setspace.sty
430                         readSpacing(lexrc);
431                         break;
432                 }
433         }
434         lexrc.popTable();
435         return error;
436 }
437
438
439 enum AlignTags {
440         AT_BLOCK = 1,
441         AT_LEFT,
442         AT_RIGHT,
443         AT_CENTER,
444         AT_LAYOUT
445 };
446
447
448 #if 0
449 static keyword_item alignTags[] = {
450         { "block",  AT_BLOCK },
451         { "center", AT_CENTER },
452         { "layout", AT_LAYOUT },
453         { "left",   AT_LEFT },
454         { "right",  AT_RIGHT }
455 };
456 #endif
457
458 void LyXLayout::readAlign(LyXLex & lexrc)
459 {
460 #if 1
461         keyword_item alignTags[] = {
462                 { "block",  AT_BLOCK },
463                 { "center", AT_CENTER },
464                 { "layout", AT_LAYOUT },
465                 { "left",   AT_LEFT },
466                 { "right",  AT_RIGHT }
467         };
468 #endif
469         pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
470         int le = lexrc.lex();
471         switch (le) {
472         case LyXLex::LEX_UNDEF:
473                 lexrc.printError("Unknown alignment `$$Token'");
474                 return; 
475         default: break;
476         };
477         switch(static_cast<AlignTags>(le)) {
478         case AT_BLOCK:
479                 align = LYX_ALIGN_BLOCK;
480                 break;
481         case AT_LEFT:
482                 align = LYX_ALIGN_LEFT;
483                 break;
484         case AT_RIGHT:
485                 align = LYX_ALIGN_RIGHT;
486                 break;
487         case AT_CENTER:
488                 align = LYX_ALIGN_CENTER;
489                 break;
490         case AT_LAYOUT:
491                 align = LYX_ALIGN_LAYOUT;
492                 break;
493         }
494 }
495
496
497 void LyXLayout::readAlignPossible(LyXLex & lexrc)
498 {
499 #if 1
500         keyword_item alignTags[] = {
501                 { "block",  AT_BLOCK },
502                 { "center", AT_CENTER },
503                 { "layout", AT_LAYOUT },
504                 { "left",   AT_LEFT },
505                 { "right",  AT_RIGHT }
506         };
507 #endif
508         lexrc.pushTable(alignTags, AT_LAYOUT);
509         alignpossible = LYX_ALIGN_NONE;
510         int lineno = lexrc.GetLineNo();
511         do {
512                 int le = lexrc.lex();
513                 switch (le) {
514                 case LyXLex::LEX_UNDEF:
515                         lexrc.printError("Unknown alignment `$$Token'");
516                         continue; 
517                 default: break;
518                 };
519                 switch (static_cast<AlignTags>(le)) {
520                 case AT_BLOCK:
521                         alignpossible |= LYX_ALIGN_BLOCK;
522                         break;
523                 case AT_LEFT:
524                         alignpossible |= LYX_ALIGN_LEFT;
525                         break;
526                 case AT_RIGHT:
527                         alignpossible |= LYX_ALIGN_RIGHT;
528                         break;
529                 case AT_CENTER:
530                         alignpossible |= LYX_ALIGN_CENTER;
531                         break;
532                 case AT_LAYOUT:
533                         alignpossible |= LYX_ALIGN_LAYOUT;
534                         break;
535                 }
536         } while (lineno == lexrc.GetLineNo());
537         lexrc.popTable();
538 }
539
540
541 enum LabelTypeTags {
542         LA_NO_LABEL = 1,
543         LA_MANUAL,
544         LA_TOP_ENVIRONMENT,
545         LA_CENTERED_TOP_ENVIRONMENT,
546         LA_STATIC,
547         LA_SENSITIVE,
548         LA_COUNTER_CHAPTER,
549         LA_COUNTER_SECTION,
550         LA_COUNTER_SUBSECTION,
551         LA_COUNTER_SUBSUBSECTION,
552         LA_COUNTER_PARAGRAPH,
553         LA_COUNTER_SUBPARAGRAPH,
554         LA_COUNTER_ENUMI,
555         LA_COUNTER_ENUMII,
556         LA_COUNTER_ENUMIII,
557         LA_COUNTER_ENUMIV,
558         LA_BIBLIO
559 };
560
561
562 #if 0
563 static keyword_item labelTypeTags[] = {
564         { "bibliography",             LA_BIBLIO },
565         { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
566         { "counter_chapter",          LA_COUNTER_CHAPTER },
567         { "counter_enumi",            LA_COUNTER_ENUMI },
568         { "counter_enumii",           LA_COUNTER_ENUMII },
569         { "counter_enumiii",          LA_COUNTER_ENUMIII },
570         { "counter_enumiv",           LA_COUNTER_ENUMIV },
571         { "counter_paragraph",        LA_COUNTER_PARAGRAPH },
572         { "counter_section",          LA_COUNTER_SECTION },
573         { "counter_subparagraph",     LA_COUNTER_SUBPARAGRAPH },
574         { "counter_subsection",       LA_COUNTER_SUBSECTION },
575         { "counter_subsubsection",    LA_COUNTER_SUBSUBSECTION },
576         { "manual",                   LA_MANUAL },
577         { "no_label",                 LA_NO_LABEL },
578         { "sensitive",                LA_SENSITIVE },
579         { "static",                   LA_STATIC },
580         { "top_environment",          LA_TOP_ENVIRONMENT }
581 };
582 #endif
583
584
585 void LyXLayout::readLabelType(LyXLex & lexrc)
586 {
587 #if 1
588         keyword_item labelTypeTags[] = {
589         { "bibliography",             LA_BIBLIO },
590         { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
591         { "counter_chapter",          LA_COUNTER_CHAPTER },
592         { "counter_enumi",            LA_COUNTER_ENUMI },
593         { "counter_enumii",           LA_COUNTER_ENUMII },
594         { "counter_enumiii",          LA_COUNTER_ENUMIII },
595         { "counter_enumiv",           LA_COUNTER_ENUMIV },
596         { "counter_paragraph",        LA_COUNTER_PARAGRAPH },
597         { "counter_section",          LA_COUNTER_SECTION },
598         { "counter_subparagraph",     LA_COUNTER_SUBPARAGRAPH },
599         { "counter_subsection",       LA_COUNTER_SUBSECTION },
600         { "counter_subsubsection",    LA_COUNTER_SUBSUBSECTION },
601         { "manual",                   LA_MANUAL },
602         { "no_label",                 LA_NO_LABEL },
603         { "sensitive",                LA_SENSITIVE },
604         { "static",                   LA_STATIC },
605         { "top_environment",          LA_TOP_ENVIRONMENT }
606 };
607 #endif
608         pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
609         int le = lexrc.lex();
610         switch (le) {
611         case LyXLex::LEX_UNDEF:
612                 lexrc.printError("Unknown labeltype tag `$$Token'");
613                 return; 
614         default: break;
615         }
616         switch (static_cast<LabelTypeTags>(le)) {
617         case LA_NO_LABEL:
618                 labeltype = LABEL_NO_LABEL;
619                 break;
620         case LA_MANUAL:
621                 labeltype = LABEL_MANUAL;
622                 break;
623         case LA_TOP_ENVIRONMENT:
624                 labeltype = LABEL_TOP_ENVIRONMENT;
625                 break;
626         case LA_CENTERED_TOP_ENVIRONMENT:
627                 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
628                 break;
629         case LA_STATIC:
630                 labeltype = LABEL_STATIC;
631                 break;
632         case LA_SENSITIVE:
633                 labeltype = LABEL_SENSITIVE;
634                 break;
635         case LA_COUNTER_CHAPTER:
636                 labeltype = LABEL_COUNTER_CHAPTER;
637                 break;
638         case LA_COUNTER_SECTION:
639                 labeltype = LABEL_COUNTER_SECTION;
640                 break;
641         case LA_COUNTER_SUBSECTION:
642                 labeltype = LABEL_COUNTER_SUBSECTION;
643                 break;
644         case LA_COUNTER_SUBSUBSECTION:
645                 labeltype = LABEL_COUNTER_SUBSUBSECTION;
646                 break;
647         case LA_COUNTER_PARAGRAPH:
648                 labeltype = LABEL_COUNTER_PARAGRAPH;
649                 break;
650         case LA_COUNTER_SUBPARAGRAPH:
651                 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
652                 break;
653         case LA_COUNTER_ENUMI:
654                 labeltype = LABEL_COUNTER_ENUMI;
655                 break;
656         case LA_COUNTER_ENUMII:
657                 labeltype = LABEL_COUNTER_ENUMII;
658                 break;
659         case LA_COUNTER_ENUMIII:
660                 labeltype = LABEL_COUNTER_ENUMIII;
661                 break;
662         case LA_COUNTER_ENUMIV:
663                 labeltype = LABEL_COUNTER_ENUMIV;
664                 break;
665         case LA_BIBLIO:
666                 labeltype = LABEL_BIBLIO;
667                 break;
668         }
669 }
670
671 static keyword_item endlabelTypeTags[] = {
672         { "box",        END_LABEL_BOX },
673         { "filled_box", END_LABEL_FILLED_BOX },
674         { "no_label",   END_LABEL_NO_LABEL }
675 };
676
677 void LyXLayout::readEndLabelType(LyXLex & lexrc)
678 {
679         pushpophelper pph(lexrc, endlabelTypeTags,
680                           END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
681         int le = lexrc.lex();
682         switch(le) {
683         case LyXLex::LEX_UNDEF:
684                 lexrc.printError("Unknown labeltype tag `$$Token'");
685                 break;
686         case END_LABEL_BOX:
687         case END_LABEL_FILLED_BOX:
688         case END_LABEL_NO_LABEL:
689                 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
690                 break;
691         default:
692                 lyxerr << "Unhandled value " << le
693                        << " in LyXLayout::readEndLabelType." << endl;
694                 break;
695         }
696 }
697
698 #if 0
699 static keyword_item marginTags[] = {
700         { "dynamic",           MARGIN_DYNAMIC },
701         { "first_dynamic",     MARGIN_FIRST_DYNAMIC },
702         { "manual",            MARGIN_MANUAL },
703         { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
704         { "static",            MARGIN_STATIC }
705 };
706 #endif
707
708 void LyXLayout::readMargin(LyXLex & lexrc)
709 {
710 #if 1
711         keyword_item marginTags[] = {
712                 { "dynamic",           MARGIN_DYNAMIC },
713                 { "first_dynamic",     MARGIN_FIRST_DYNAMIC },
714                 { "manual",            MARGIN_MANUAL },
715                 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
716                 { "static",            MARGIN_STATIC }
717         };
718 #endif
719         pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
720
721         int le = lexrc.lex();
722         switch(le) {
723         case LyXLex::LEX_UNDEF:
724                 lexrc.printError("Unknown margin type tag `$$Token'");
725                 return;
726         case MARGIN_STATIC:
727         case MARGIN_MANUAL:
728         case MARGIN_DYNAMIC:
729         case MARGIN_FIRST_DYNAMIC:
730         case MARGIN_RIGHT_ADDRESS_BOX:
731                 margintype = static_cast<LYX_MARGIN_TYPE>(le);
732                 break;
733         default:
734                 lyxerr << "Unhandled value " << le
735                        << " in LyXLayout::readMargin." << endl;
736                 break;
737         }
738 }
739
740
741 #if 0
742 static keyword_item latexTypeTags[] = {
743         { "command",          LATEX_COMMAND },
744         { "environment",      LATEX_ENVIRONMENT },
745         { "item_environment", LATEX_ITEM_ENVIRONMENT },
746         { "list_environment", LATEX_LIST_ENVIRONMENT },
747         { "paragraph",        LATEX_PARAGRAPH }
748 };
749 #endif
750
751
752 void LyXLayout::readLatexType(LyXLex & lexrc)
753 {
754 #if 1
755         keyword_item latexTypeTags[] = {
756                 { "command",          LATEX_COMMAND },
757                 { "environment",      LATEX_ENVIRONMENT },
758                 { "item_environment", LATEX_ITEM_ENVIRONMENT },
759                 { "list_environment", LATEX_LIST_ENVIRONMENT },
760                 { "paragraph",        LATEX_PARAGRAPH }
761 };
762 #endif
763         pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
764         int le = lexrc.lex();
765         switch (le) {
766         case LyXLex::LEX_UNDEF:
767                 lexrc.printError("Unknown latextype tag `$$Token'");
768                 return;
769         case LATEX_PARAGRAPH:
770         case LATEX_COMMAND:
771         case LATEX_ENVIRONMENT:
772         case LATEX_ITEM_ENVIRONMENT:
773         case LATEX_LIST_ENVIRONMENT:
774                 latextype = static_cast<LYX_LATEX_TYPES>(le);
775                 break;
776         default:
777                 lyxerr << "Unhandled value " << le
778                        << " in LyXLayout::readLatexType." << endl;
779                 break;
780         }
781 }
782
783
784 enum SpacingTags {
785         ST_SPACING_SINGLE = 1,
786         ST_SPACING_ONEHALF,
787         ST_SPACING_DOUBLE,
788         ST_OTHER
789 };
790
791
792 #if 0
793 static keyword_item spacingTags[] = {
794         {"double",  ST_SPACING_DOUBLE },
795         {"onehalf", ST_SPACING_ONEHALF },
796         {"other",   ST_OTHER },
797         {"single",  ST_SPACING_SINGLE }
798 };
799 #endif
800
801
802 void LyXLayout::readSpacing(LyXLex & lexrc)
803 {
804 #if 1
805         keyword_item spacingTags[] = {
806                 {"double",  ST_SPACING_DOUBLE },
807                 {"onehalf", ST_SPACING_ONEHALF },
808                 {"other",   ST_OTHER },
809                 {"single",  ST_SPACING_SINGLE }
810         };
811 #endif
812         pushpophelper pph(lexrc, spacingTags, ST_OTHER);
813         int le = lexrc.lex();
814         switch(le) {
815         case LyXLex::LEX_UNDEF:
816                 lexrc.printError("Unknown spacing token `$$Token'");
817                 return;
818         default: break;
819         }
820         switch(static_cast<SpacingTags>(le)) {
821         case ST_SPACING_SINGLE:
822                 spacing.set(Spacing::Single);
823                 break;
824         case ST_SPACING_ONEHALF:
825                 spacing.set(Spacing::Onehalf);
826                 break;
827         case ST_SPACING_DOUBLE:
828                 spacing.set(Spacing::Double);
829                 break;
830         case ST_OTHER:
831                 lexrc.next();
832                 spacing.set(Spacing::Other, lexrc.GetFloat());
833                 break;
834         }
835 }
836
837
838 /* ******************************************************************* */
839
840 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
841                            string const & desc)
842         : name_(fn), latexname_(cln), description_(desc)
843 {
844         outputType_ = LATEX;
845         columns_ = 1;
846         sides_ = OneSide;
847         secnumdepth_ = 3;
848         tocdepth_ = 3;
849         pagestyle_ = "default";
850         maxcounter_ = LABEL_COUNTER_CHAPTER;
851         defaultfont_ = LyXFont(LyXFont::ALL_SANE);
852         opt_fontsize_ = "10|11|12";
853         opt_pagestyle_ = "empty|plain|headings|fancy";
854         provides_ = nothing;
855         loaded = false;
856 }
857
858
859 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
860 {
861         lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
862         if (!lay.Read(lexrc, *this)) {
863                 // Reslove fonts
864                 lay.resfont = lay.font;
865                 lay.resfont.realize(defaultfont());
866                 lay.reslabelfont = lay.labelfont;
867                 lay.reslabelfont.realize(defaultfont());
868                 return false; // no errors
869         } 
870         lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
871         return true;
872 }
873
874
875 enum TextClassTags {
876         TC_OUTPUTTYPE = 1,
877         TC_INPUT,
878         TC_STYLE,
879         TC_NOSTYLE,
880         TC_COLUMNS,
881         TC_SIDES,
882         TC_PAGESTYLE,
883         TC_DEFAULTFONT,
884         TC_MAXCOUNTER,
885         TC_SECNUMDEPTH,
886         TC_TOCDEPTH,
887         TC_CLASSOPTIONS,
888         TC_PREAMBLE,
889         TC_PROVIDESAMSMATH,
890         TC_PROVIDESMAKEIDX,
891         TC_PROVIDESURL,
892         TC_LEFTMARGIN,
893         TC_RIGHTMARGIN
894 };
895
896
897 #if 0
898 static keyword_item textClassTags[] = {
899         { "classoptions",    TC_CLASSOPTIONS },
900         { "columns",         TC_COLUMNS },
901         { "defaultfont",     TC_DEFAULTFONT },
902         { "input",           TC_INPUT },
903         { "leftmargin",      TC_LEFTMARGIN },
904         { "maxcounter",      TC_MAXCOUNTER },
905         { "nostyle",         TC_NOSTYLE },
906         { "outputtype",      TC_OUTPUTTYPE },
907         { "pagestyle",       TC_PAGESTYLE },
908         { "preamble",        TC_PREAMBLE },
909         { "providesamsmath", TC_PROVIDESAMSMATH },
910         { "providesmakeidx", TC_PROVIDESMAKEIDX },
911         { "providesurl",     TC_PROVIDESURL },
912         { "rightmargin",     TC_RIGHTMARGIN },
913         { "secnumdepth",     TC_SECNUMDEPTH },
914         { "sides",           TC_SIDES },
915         { "style",           TC_STYLE },
916         { "tocdepth",        TC_TOCDEPTH }
917 };
918 #endif
919
920
921 // Reads a textclass structure from file.
922 bool LyXTextClass::Read(string const & filename, bool merge)
923 {
924 #if 1
925         keyword_item textClassTags[] = {
926                 { "classoptions",    TC_CLASSOPTIONS },
927                 { "columns",         TC_COLUMNS },
928                 { "defaultfont",     TC_DEFAULTFONT },
929                 { "input",           TC_INPUT },
930                 { "leftmargin",      TC_LEFTMARGIN },
931                 { "maxcounter",      TC_MAXCOUNTER },
932                 { "nostyle",         TC_NOSTYLE },
933                 { "outputtype",      TC_OUTPUTTYPE },
934                 { "pagestyle",       TC_PAGESTYLE },
935                 { "preamble",        TC_PREAMBLE },
936                 { "providesamsmath", TC_PROVIDESAMSMATH },
937                 { "providesmakeidx", TC_PROVIDESMAKEIDX },
938                 { "providesurl",     TC_PROVIDESURL },
939                 { "rightmargin",     TC_RIGHTMARGIN },
940                 { "secnumdepth",     TC_SECNUMDEPTH },
941                 { "sides",           TC_SIDES },
942                 { "style",           TC_STYLE },
943                 { "tocdepth",        TC_TOCDEPTH }
944 };
945 #endif
946         if (!merge)
947                 lyxerr[Debug::TCLASS] << "Reading textclass "
948                                       << MakeDisplayPath(filename)
949                                       << endl;
950         else
951                 lyxerr[Debug::TCLASS] << "Reading input file "
952                                      << MakeDisplayPath(filename)
953                                      << endl;
954         
955         LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
956         bool error = false;
957
958         lexrc.setFile(filename);
959         if (!lexrc.IsOK()) error = true; 
960
961         // parsing
962         while (lexrc.IsOK() && !error) {
963                 int le = lexrc.lex();
964                 switch(le) {
965                 case LyXLex::LEX_FEOF:
966                         continue; 
967
968                 case LyXLex::LEX_UNDEF:                                 
969                         lexrc.printError("Unknown TextClass tag `$$Token'");
970                         error = true;
971                         continue; 
972                 default: break;
973                 }
974                 switch(static_cast<TextClassTags>(le)) {
975                 case TC_OUTPUTTYPE:   // output type definition
976                         readOutputType(lexrc);
977                         break;
978                         
979                 case TC_INPUT: // Include file
980                         if (lexrc.next()) {
981                                 string tmp = LibFileSearch("layouts",
982                                                             lexrc.GetString(), 
983                                                             "layout");
984                                 
985                                 if (Read(tmp, true)) {
986                                         lexrc.printError("Error reading input"
987                                                          "file: "+tmp);
988                                         error = true;
989                                 }
990                         }
991                         break;
992
993                 case TC_STYLE:
994                         if (lexrc.next()) {
995                                 string name = subst(lexrc.GetString(),
996                                                     '_', ' ');
997                                 if (hasLayout(name)) {
998                                         LyXLayout & lay = GetLayout(name);
999                                         error = do_readStyle(lexrc, lay);
1000                                 } else {
1001                                         LyXLayout lay;
1002                                         lay.name(name);
1003                                         if (!(error = do_readStyle(lexrc, lay)))
1004                                                 layoutlist.push_back(lay);
1005                                 }
1006                         }
1007                         else {
1008                                 lexrc.printError("No name given for style: `$$Token'.");
1009                                 error = true;
1010                         }
1011                         break;
1012
1013                 case TC_NOSTYLE:
1014                         if (lexrc.next()) {
1015                                 string style = subst(lexrc.GetString(),
1016                                                      '_', ' ');
1017                                 if (!delete_layout(style))
1018                                         lexrc.printError("Cannot delete style"
1019                                                          " `$$Token'");
1020                         }
1021                         break;
1022
1023                 case TC_COLUMNS:
1024                         if (lexrc.next())
1025                                 columns_ = lexrc.GetInteger();
1026                         break;
1027                         
1028                 case TC_SIDES:
1029                         if (lexrc.next()) {
1030                                 switch(lexrc.GetInteger()) {
1031                                 case 1: sides_ = OneSide; break;
1032                                 case 2: sides_ = TwoSides; break;
1033                                 default:
1034                                         lyxerr << "Impossible number of page"
1035                                                 " sides, setting to one."
1036                                                << endl;
1037                                         sides_ = OneSide;
1038                                         break;
1039                                 }
1040                         }
1041                         break;
1042                         
1043                 case TC_PAGESTYLE:
1044                         lexrc.next();
1045                         pagestyle_ = strip(lexrc.GetString());
1046                         break;
1047                         
1048                 case TC_DEFAULTFONT:
1049                         defaultfont_.lyxRead(lexrc);
1050                         if (!defaultfont_.resolved()) {
1051                                 lexrc.printError("Warning: defaultfont should "
1052                                                  "be fully instantiated!");
1053                                 defaultfont_.realize(LyXFont(LyXFont::ALL_SANE));
1054                         }
1055                         break;
1056
1057                 case TC_MAXCOUNTER:
1058                         readMaxCounter(lexrc);
1059                         break;
1060
1061                 case TC_SECNUMDEPTH:
1062                         lexrc.next();
1063                         secnumdepth_ = lexrc.GetInteger();
1064                         break;
1065
1066                 case TC_TOCDEPTH:
1067                         lexrc.next();
1068                         tocdepth_ = lexrc.GetInteger();
1069                         break;
1070
1071                         // First step to support options 
1072                 case TC_CLASSOPTIONS:
1073                         readClassOptions(lexrc);
1074                         break;
1075
1076                 case TC_PREAMBLE:
1077                         preamble_ = lexrc.getLongString("EndPreamble");
1078                         break;
1079
1080                 case TC_PROVIDESAMSMATH:
1081                         if (lexrc.next() && lexrc.GetInteger())
1082                                 provides_ |= amsmath;
1083                         break;
1084
1085                 case TC_PROVIDESMAKEIDX:
1086                         if (lexrc.next() && lexrc.GetInteger())
1087                                 provides_ |= makeidx;
1088                         break;
1089
1090                 case TC_PROVIDESURL:
1091                         if (lexrc.next() && lexrc.GetInteger())
1092                                 provides_ = url;
1093                         break;
1094
1095                 case TC_LEFTMARGIN:     // left margin type
1096                         if (lexrc.next())
1097                                 leftmargin_ = lexrc.GetString();
1098                         break;                  
1099
1100                 case TC_RIGHTMARGIN:    // right margin type
1101                         if (lexrc.next())
1102                                 rightmargin_ = lexrc.GetString();
1103                         break;
1104                 }
1105         }       
1106
1107         if (!merge) { // we are at top level here.
1108                 lyxerr[Debug::TCLASS] << "Finished reading textclass " 
1109                                       << MakeDisplayPath(filename)
1110                                       << endl;
1111         } else
1112                 lyxerr[Debug::TCLASS] << "Finished reading input file " 
1113                                       << MakeDisplayPath(filename)
1114                                       << endl;
1115
1116         return error;
1117 }
1118
1119
1120 #if 0
1121 static keyword_item outputTypeTags[] = {
1122         { "docbook", DOCBOOK },
1123         { "latex", LATEX },
1124         { "linuxdoc", LINUXDOC },
1125         { "literate", LITERATE }
1126 };
1127 #endif
1128
1129 void LyXTextClass::readOutputType(LyXLex & lexrc)
1130 {
1131 #if 1
1132         keyword_item outputTypeTags[] = {
1133                 { "docbook", DOCBOOK },
1134                 { "latex", LATEX },
1135                 { "linuxdoc", LINUXDOC },
1136                 { "literate", LITERATE }
1137 };
1138 #endif
1139         pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1140
1141         int le = lexrc.lex();
1142         switch(le) {
1143         case LyXLex::LEX_UNDEF:
1144                 lexrc.printError("Unknown output type `$$Token'");
1145                 return;
1146         case LATEX:
1147         case LINUXDOC:
1148         case DOCBOOK:
1149         case LITERATE:
1150                 outputType_ = static_cast<OutputType>(le);
1151                 break;
1152         default:
1153                 lyxerr << "Unhandled value " << le
1154                        << " in LyXTextClass::readOutputType." << endl;
1155
1156                 break;
1157         }
1158 }
1159
1160
1161 enum MaxCounterTags {
1162         MC_COUNTER_CHAPTER = 1,
1163         MC_COUNTER_SECTION,
1164         MC_COUNTER_SUBSECTION,
1165         MC_COUNTER_SUBSUBSECTION,
1166         MC_COUNTER_PARAGRAPH,
1167         MC_COUNTER_SUBPARAGRAPH,
1168         MC_COUNTER_ENUMI,
1169         MC_COUNTER_ENUMII,
1170         MC_COUNTER_ENUMIII,
1171         MC_COUNTER_ENUMIV
1172 };
1173
1174
1175 #if 0
1176 static keyword_item maxCounterTags[] = {
1177         {"counter_chapter", MC_COUNTER_CHAPTER },
1178         {"counter_enumi", MC_COUNTER_ENUMI },
1179         {"counter_enumii", MC_COUNTER_ENUMII },
1180         {"counter_enumiii", MC_COUNTER_ENUMIII },
1181         {"counter_enumiv", MC_COUNTER_ENUMIV },
1182         {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1183         {"counter_section", MC_COUNTER_SECTION },
1184         {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1185         {"counter_subsection", MC_COUNTER_SUBSECTION },
1186         {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1187 };
1188 #endif
1189
1190
1191 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1192 {
1193 #if 1
1194         keyword_item maxCounterTags[] = {
1195                 {"counter_chapter", MC_COUNTER_CHAPTER },
1196                 {"counter_enumi", MC_COUNTER_ENUMI },
1197                 {"counter_enumii", MC_COUNTER_ENUMII },
1198                 {"counter_enumiii", MC_COUNTER_ENUMIII },
1199                 {"counter_enumiv", MC_COUNTER_ENUMIV },
1200                 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1201                 {"counter_section", MC_COUNTER_SECTION },
1202                 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1203                 {"counter_subsection", MC_COUNTER_SUBSECTION },
1204                 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1205         };
1206 #endif
1207         pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1208         int le = lexrc.lex();
1209         switch(le) {
1210         case LyXLex::LEX_UNDEF:
1211                 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1212                 return; 
1213         default: break;
1214         }
1215         switch (static_cast<MaxCounterTags>(le)) {
1216         case MC_COUNTER_CHAPTER:
1217                 maxcounter_ = LABEL_COUNTER_CHAPTER;
1218                 break;
1219         case MC_COUNTER_SECTION:
1220                 maxcounter_ = LABEL_COUNTER_SECTION;
1221                 break;
1222         case MC_COUNTER_SUBSECTION:
1223                 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1224                 break;
1225         case MC_COUNTER_SUBSUBSECTION:
1226                 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1227                 break;
1228         case MC_COUNTER_PARAGRAPH:
1229                 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1230                 break;
1231         case MC_COUNTER_SUBPARAGRAPH:
1232                 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1233                 break;
1234         case MC_COUNTER_ENUMI:
1235                 maxcounter_ = LABEL_COUNTER_ENUMI;
1236                 break;
1237         case MC_COUNTER_ENUMII:
1238                 maxcounter_ = LABEL_COUNTER_ENUMII;
1239                 break;
1240         case MC_COUNTER_ENUMIII:
1241                 maxcounter_ = LABEL_COUNTER_ENUMIII;
1242                 break;
1243         case MC_COUNTER_ENUMIV:
1244                 maxcounter_ = LABEL_COUNTER_ENUMIV;
1245                 break;
1246         }
1247 }
1248
1249
1250 enum ClassOptionsTags {
1251         CO_FONTSIZE = 1,
1252         CO_PAGESTYLE,
1253         CO_OTHER,
1254         CO_END
1255 };
1256
1257
1258 #if 0
1259 static keyword_item classOptionsTags[] = {
1260         {"end", CO_END },
1261         {"fontsize", CO_FONTSIZE },
1262         {"other", CO_OTHER },
1263         {"pagestyle", CO_PAGESTYLE }
1264 };
1265 #endif
1266
1267
1268 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1269 {
1270 #if 1
1271         keyword_item classOptionsTags[] = {
1272                 {"end", CO_END },
1273                 {"fontsize", CO_FONTSIZE },
1274                 {"other", CO_OTHER },
1275                 {"pagestyle", CO_PAGESTYLE }
1276         };
1277 #endif
1278         lexrc.pushTable(classOptionsTags, CO_END);
1279         bool getout = false;
1280         while (!getout && lexrc.IsOK()) {
1281                 int le = lexrc.lex();
1282                 switch (le) {
1283                 case LyXLex::LEX_UNDEF:
1284                         lexrc.printError("Unknown ClassOption tag `$$Token'");
1285                         continue; 
1286                 default: break;
1287                 }
1288                 switch (static_cast<ClassOptionsTags>(le)) {
1289                 case CO_FONTSIZE:
1290                         lexrc.next();
1291                         opt_fontsize_ = strip(lexrc.GetString());
1292                         break;
1293                 case CO_PAGESTYLE:
1294                         lexrc.next();
1295                         opt_pagestyle_ = strip(lexrc.GetString()); 
1296                         break;
1297                 case CO_OTHER:
1298                         lexrc.next();
1299                         options_ = lexrc.GetString();
1300                         break;
1301                 case CO_END:
1302                         getout = true;
1303                         break;
1304                 }
1305         }
1306         lexrc.popTable();
1307 }
1308
1309
1310 bool LyXTextClass::hasLayout(string const & name) const
1311 {
1312         for (LayoutList::const_iterator cit = layoutlist.begin();
1313              cit != layoutlist.end(); ++cit) {
1314                 if ((*cit).name() == name)
1315                         return true;
1316         }
1317         return false;
1318 }
1319
1320
1321 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1322 {
1323         for (LayoutList::const_iterator cit = layoutlist.begin();
1324              cit != layoutlist.end(); ++cit) {
1325                 if ((*cit).name() == name)
1326                         return (*cit);
1327         }
1328         Assert(false); // we actually require the name to exist.
1329         return layoutlist.front();
1330 }
1331
1332
1333 LyXLayout & LyXTextClass::GetLayout(string const & name)
1334 {
1335         for (LayoutList::iterator it = layoutlist.begin();
1336              it != layoutlist.end(); ++it) {
1337                 if ((*it).name() == name)
1338                         return (*it);
1339         }
1340         Assert(false); // we actually require the name to exist.
1341         return layoutlist.front();
1342 }
1343
1344
1345 bool LyXTextClass::delete_layout (string const & name)
1346 {
1347         for(LayoutList::iterator it = layoutlist.begin();
1348             it != layoutlist.end(); ++it) {
1349                 if ((*it).name() == name) {
1350                         layoutlist.erase(it);
1351                         return true;
1352                 }
1353         }
1354         return false;
1355 }
1356
1357
1358 // Load textclass info if not loaded yet
1359 void LyXTextClass::load()
1360 {
1361         if (loaded) return;
1362
1363         // Read style-file
1364         string real_file = LibFileSearch("layouts", name_, "layout");
1365
1366         if (Read(real_file)) {
1367                 lyxerr << "Error reading `"
1368                        << MakeDisplayPath(real_file)
1369                        << "'\n(Check `" << name_
1370                        << "')\nCheck your installation and "
1371                         "try Options/Reconfigure..." << endl;
1372         }
1373         loaded = true;
1374 }
1375
1376
1377 //////////////////////////////////////////
1378
1379 // Gets textclass number from name
1380 pair<bool, LyXTextClassList::size_type>
1381 LyXTextClassList::NumberOfClass(string const & textclass) const
1382 {
1383         for (ClassList::const_iterator cit = classlist.begin();
1384              cit != classlist.end(); ++cit) {
1385                 if ((*cit).name() == textclass)
1386                         return make_pair(true, cit - classlist.begin());
1387         }
1388         return make_pair(false, size_type(0));
1389 }
1390
1391
1392 // Gets layout structure from style number and textclass number
1393 LyXLayout const &
1394 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1395                         LyXTextClass::size_type layout) const
1396 {
1397         classlist[textclass].load();
1398         if (layout < classlist[textclass].numLayouts())
1399                 return classlist[textclass][layout];
1400         return classlist[textclass][0];
1401 }
1402
1403
1404 // Gets layout number from name and textclass number
1405 pair<bool, LyXTextClass::size_type>
1406 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1407                                  string const & name) const
1408 {
1409         classlist[textclass].load();
1410         for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1411                 if (classlist[textclass][i].name() == name)
1412                         return make_pair(true, i);
1413         }
1414         if (name == "dummy")
1415                 return make_pair(true, LYX_DUMMY_LAYOUT);
1416         return make_pair(false, LyXTextClass::LayoutList::size_type(0)); // not found
1417 }
1418
1419
1420 // Gets a layout (style) name from layout number and textclass number
1421 string const &
1422 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1423                                LyXTextClass::size_type layout) const
1424 {
1425         static string dummy("dummy");
1426         classlist[textclass].load();
1427         if (layout < classlist[textclass].numLayouts())
1428                 return classlist[textclass][layout].name();
1429         return dummy;
1430 }
1431
1432
1433 // Gets a textclass name from number
1434 string const &
1435 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1436 {
1437         static string dummy("dummy");
1438         if (classlist.size() == 0) {
1439                 return dummy;
1440         }
1441         Assert(number < classlist.size());
1442         return classlist[number].name();
1443 }
1444
1445
1446 // Gets a textclass latexname from number
1447 string const &
1448 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1449 {
1450         static string dummy("dummy");
1451         classlist[number].load();
1452         if (classlist.size() == 0) {
1453                 return dummy;
1454         }
1455         Assert(number < classlist.size());
1456         return classlist[number].latexname();
1457 }
1458
1459
1460 // Gets a textclass description from number
1461 string const &
1462 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1463 {
1464         static string dummy("dummy");
1465         if (classlist.size() == 0) {
1466                 return dummy;
1467         }
1468         Assert(number < classlist.size());
1469         return classlist[number].description();
1470 }
1471
1472
1473 // Gets a textclass structure from number
1474 LyXTextClass const &
1475 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1476 {
1477         classlist[textclass].load();
1478         if (textclass < classlist.size())
1479                 return classlist[textclass];
1480         else
1481                 return classlist[0];
1482 }
1483
1484
1485 void LyXTextClassList::Add(LyXTextClass const & t)
1486 {
1487         classlist.push_back(t);
1488 }
1489
1490
1491 // used when sorting the textclass list.
1492 class less_textclass_desc {
1493 public:
1494         int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1495                 return tc1.description() < tc2.description();
1496         }
1497 };
1498
1499
1500 // Reads LyX textclass definitions according to textclass config file
1501 bool LyXTextClassList::Read ()
1502 {
1503         LyXLex lex(0, 0);
1504         string real_file = LibFileSearch("", "textclass.lst");
1505         lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1506                               << real_file << "'" << endl;
1507
1508         if (real_file.empty()) {
1509                 lyxerr << "LyXTextClassList::Read: unable to find "
1510                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1511                        << "'. Exiting." << endl;
1512
1513                 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1514                            _("Check that the file \"textclass.lst\""),
1515                            _("is installed correctly. Sorry, has to exit :-("));
1516                 return false;
1517                 // This causes LyX to end... Not a desirable behaviour. Lgb
1518                 // What do you propose? That the user gets a file dialog
1519                 // and is allowed to hunt for the file? (Asger)
1520                 // more that we have a layout for minimal.cls statically
1521                 // compiled in... (Lgb)
1522         }
1523
1524         if (!lex.setFile(real_file)) {
1525                 lyxerr << "LyXTextClassList::Read: "
1526                         "lyxlex was not able to set file: "
1527                        << real_file << endl;
1528         }
1529         
1530         if (!lex.IsOK()) {
1531                 lyxerr << "LyXTextClassList::Read: unable to open "
1532                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1533                        << "'\nCheck your installation. LyX can't continue."
1534                        << endl;
1535                 return false;
1536         }
1537         bool finished = false;
1538         string fname, clname, desc;
1539         // Parse config-file
1540         lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1541         while (lex.IsOK() && !finished) {
1542                 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1543                 switch (lex.lex()) {
1544                 case LyXLex::LEX_FEOF:
1545                         finished = true;
1546                         break;
1547                 default:
1548                         fname = lex.GetString();
1549                         lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1550                         if (lex.next()) {
1551                                 clname = lex.GetString();
1552                                 lyxerr[Debug::TCLASS]
1553                                         << "Clname: " << clname << endl;
1554                                 if (lex.next()) {
1555                                               desc = lex.GetString();
1556                                               lyxerr[Debug::TCLASS]
1557                                                       << "Desc: " << desc << endl;
1558                                               // This code is run when we have
1559                                               // fname, clname and desc
1560                                               LyXTextClass tmpl(fname,
1561                                                                 clname,
1562                                                                 desc);
1563                                               if (lyxerr.
1564                                                   debugging(Debug::TCLASS)) {
1565                                                       tmpl.load();
1566                                               }
1567                                               Add (tmpl);
1568                                 }
1569                         }
1570                 }
1571         }
1572         lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1573
1574         if (classlist.size() == 0) {
1575                 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1576                        << endl;
1577                 WriteAlert(_("LyX wasn't able to find any layout description!"),
1578                            _("Check the contents of  the file \"textclass.lst\""),
1579                            _("Sorry, has to exit :-("));
1580                 return false;
1581         }
1582         // Ok everything loaded ok, now sort the list.
1583         sort(classlist.begin(), classlist.end(), less_textclass_desc());
1584         return true;
1585 }
1586
1587         
1588 /* Load textclass
1589    Returns false if this fails
1590 */
1591 bool
1592 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1593 {
1594         bool result = true;
1595         if (number < classlist.size()) {
1596                 classlist[number].load();
1597                 if (classlist[number].numLayouts() == 0) {
1598                         result = false;
1599                 }
1600         } else {
1601                 result = false;
1602         }
1603         return result;
1604 }
1605
1606
1607 std::ostream & operator<<(std::ostream & os, LyXTextClass::PageSides p)
1608 {
1609         switch (p) {
1610         case LyXTextClass::OneSide:
1611                 os << "1";
1612                 break;
1613         case LyXTextClass::TwoSides:
1614                 os << "2";
1615                 break;
1616         }
1617         return os;
1618 }