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