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