]> git.lyx.org Git - lyx.git/blob - src/layout.C
Remove unused font variable which caused a warning.
[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(), default_language);
779                 lay.reslabelfont = lay.labelfont;
780                 lay.reslabelfont.realize(defaultfont(), default_language);
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                                                      default_language);
943                         }
944                         break;
945
946                 case TC_MAXCOUNTER:
947                         readMaxCounter(lexrc);
948                         break;
949
950                 case TC_SECNUMDEPTH:
951                         lexrc.next();
952                         secnumdepth_ = lexrc.GetInteger();
953                         break;
954
955                 case TC_TOCDEPTH:
956                         lexrc.next();
957                         tocdepth_ = lexrc.GetInteger();
958                         break;
959
960                         // First step to support options 
961                 case TC_CLASSOPTIONS:
962                         readClassOptions(lexrc);
963                         break;
964
965                 case TC_PREAMBLE:
966                         preamble_ = lexrc.getLongString("EndPreamble");
967                         break;
968
969                 case TC_PROVIDESAMSMATH:
970                         if (lexrc.next() && lexrc.GetInteger())
971                                 provides_ |= amsmath;
972                         break;
973
974                 case TC_PROVIDESMAKEIDX:
975                         if (lexrc.next() && lexrc.GetInteger())
976                                 provides_ |= makeidx;
977                         break;
978
979                 case TC_PROVIDESURL:
980                         if (lexrc.next() && lexrc.GetInteger())
981                                 provides_ = url;
982                         break;
983
984                 case TC_LEFTMARGIN:     // left margin type
985                         if (lexrc.next())
986                                 leftmargin_ = lexrc.GetString();
987                         break;                  
988
989                 case TC_RIGHTMARGIN:    // right margin type
990                         if (lexrc.next())
991                                 rightmargin_ = lexrc.GetString();
992                         break;
993                 }
994         }       
995
996         if (!merge) { // we are at top level here.
997                 lyxerr[Debug::TCLASS] << "Finished reading textclass " 
998                                       << MakeDisplayPath(filename)
999                                       << endl;
1000         } else
1001                 lyxerr[Debug::TCLASS] << "Finished reading input file " 
1002                                       << MakeDisplayPath(filename)
1003                                       << endl;
1004
1005         return error;
1006 }
1007
1008
1009 void LyXTextClass::readOutputType(LyXLex & lexrc)
1010 {
1011         keyword_item outputTypeTags[] = {
1012                 { "docbook", DOCBOOK },
1013                 { "latex", LATEX },
1014                 { "linuxdoc", LINUXDOC },
1015                 { "literate", LITERATE }
1016         };
1017
1018         pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1019
1020         int le = lexrc.lex();
1021         switch (le) {
1022         case LyXLex::LEX_UNDEF:
1023                 lexrc.printError("Unknown output type `$$Token'");
1024                 return;
1025         case LATEX:
1026         case LINUXDOC:
1027         case DOCBOOK:
1028         case LITERATE:
1029                 outputType_ = static_cast<OutputType>(le);
1030                 break;
1031         default:
1032                 lyxerr << "Unhandled value " << le
1033                        << " in LyXTextClass::readOutputType." << endl;
1034
1035                 break;
1036         }
1037 }
1038
1039
1040 enum MaxCounterTags {
1041         MC_COUNTER_CHAPTER = 1,
1042         MC_COUNTER_SECTION,
1043         MC_COUNTER_SUBSECTION,
1044         MC_COUNTER_SUBSUBSECTION,
1045         MC_COUNTER_PARAGRAPH,
1046         MC_COUNTER_SUBPARAGRAPH,
1047         MC_COUNTER_ENUMI,
1048         MC_COUNTER_ENUMII,
1049         MC_COUNTER_ENUMIII,
1050         MC_COUNTER_ENUMIV
1051 };
1052
1053
1054 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1055 {
1056         keyword_item maxCounterTags[] = {
1057                 {"counter_chapter", MC_COUNTER_CHAPTER },
1058                 {"counter_enumi", MC_COUNTER_ENUMI },
1059                 {"counter_enumii", MC_COUNTER_ENUMII },
1060                 {"counter_enumiii", MC_COUNTER_ENUMIII },
1061                 {"counter_enumiv", MC_COUNTER_ENUMIV },
1062                 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1063                 {"counter_section", MC_COUNTER_SECTION },
1064                 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1065                 {"counter_subsection", MC_COUNTER_SUBSECTION },
1066                 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1067         };
1068
1069         pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1070         int le = lexrc.lex();
1071         switch (le) {
1072         case LyXLex::LEX_UNDEF:
1073                 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1074                 return; 
1075         default: break;
1076         }
1077         switch (static_cast<MaxCounterTags>(le)) {
1078         case MC_COUNTER_CHAPTER:
1079                 maxcounter_ = LABEL_COUNTER_CHAPTER;
1080                 break;
1081         case MC_COUNTER_SECTION:
1082                 maxcounter_ = LABEL_COUNTER_SECTION;
1083                 break;
1084         case MC_COUNTER_SUBSECTION:
1085                 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1086                 break;
1087         case MC_COUNTER_SUBSUBSECTION:
1088                 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1089                 break;
1090         case MC_COUNTER_PARAGRAPH:
1091                 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1092                 break;
1093         case MC_COUNTER_SUBPARAGRAPH:
1094                 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1095                 break;
1096         case MC_COUNTER_ENUMI:
1097                 maxcounter_ = LABEL_COUNTER_ENUMI;
1098                 break;
1099         case MC_COUNTER_ENUMII:
1100                 maxcounter_ = LABEL_COUNTER_ENUMII;
1101                 break;
1102         case MC_COUNTER_ENUMIII:
1103                 maxcounter_ = LABEL_COUNTER_ENUMIII;
1104                 break;
1105         case MC_COUNTER_ENUMIV:
1106                 maxcounter_ = LABEL_COUNTER_ENUMIV;
1107                 break;
1108         }
1109 }
1110
1111
1112 enum ClassOptionsTags {
1113         CO_FONTSIZE = 1,
1114         CO_PAGESTYLE,
1115         CO_OTHER,
1116         CO_END
1117 };
1118
1119
1120 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1121 {
1122         keyword_item classOptionsTags[] = {
1123                 {"end", CO_END },
1124                 {"fontsize", CO_FONTSIZE },
1125                 {"other", CO_OTHER },
1126                 {"pagestyle", CO_PAGESTYLE }
1127         };
1128
1129         lexrc.pushTable(classOptionsTags, CO_END);
1130         bool getout = false;
1131         while (!getout && lexrc.IsOK()) {
1132                 int le = lexrc.lex();
1133                 switch (le) {
1134                 case LyXLex::LEX_UNDEF:
1135                         lexrc.printError("Unknown ClassOption tag `$$Token'");
1136                         continue; 
1137                 default: break;
1138                 }
1139                 switch (static_cast<ClassOptionsTags>(le)) {
1140                 case CO_FONTSIZE:
1141                         lexrc.next();
1142                         opt_fontsize_ = strip(lexrc.GetString());
1143                         break;
1144                 case CO_PAGESTYLE:
1145                         lexrc.next();
1146                         opt_pagestyle_ = strip(lexrc.GetString()); 
1147                         break;
1148                 case CO_OTHER:
1149                         lexrc.next();
1150                         options_ = lexrc.GetString();
1151                         break;
1152                 case CO_END:
1153                         getout = true;
1154                         break;
1155                 }
1156         }
1157         lexrc.popTable();
1158 }
1159
1160
1161 bool LyXTextClass::hasLayout(string const & name) const
1162 {
1163         return find_if(layoutlist.begin(), layoutlist.end(),
1164                        lyx::compare_memfun(&LyXLayout::name, name))
1165                 != layoutlist.end();
1166 }
1167
1168
1169 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1170 {
1171         LayoutList::const_iterator cit =
1172                 find_if(layoutlist.begin(),
1173                         layoutlist.end(),
1174                         lyx::compare_memfun(&LyXLayout::name, name));
1175         lyx::Assert(cit != layoutlist.end()); // we require the name to exist
1176         return (*cit);
1177 }
1178
1179
1180 LyXLayout & LyXTextClass::GetLayout(string const & name)
1181 {
1182         LayoutList::iterator it =
1183                 find_if(layoutlist.begin(),
1184                         layoutlist.end(),
1185                         lyx::compare_memfun(&LyXLayout::name, name));
1186         lyx::Assert(it != layoutlist.end()); // we require the name to exist
1187         return (*it);
1188 }
1189
1190
1191 bool LyXTextClass::delete_layout(string const & name)
1192 {
1193         LayoutList::iterator it =
1194                 remove_if(layoutlist.begin(), layoutlist.end(),
1195                           lyx::compare_memfun(&LyXLayout::name, name));
1196         LayoutList::iterator end = layoutlist.end();
1197         bool const ret = (it != end);
1198         layoutlist.erase(it, end);
1199         return ret;
1200 }
1201
1202
1203 // Load textclass info if not loaded yet
1204 void LyXTextClass::load()
1205 {
1206         if (loaded) return;
1207
1208         // Read style-file
1209         string const real_file = LibFileSearch("layouts", name_, "layout");
1210
1211         if (Read(real_file)) {
1212                 lyxerr << "Error reading `"
1213                        << MakeDisplayPath(real_file)
1214                        << "'\n(Check `" << name_
1215                        << "')\nCheck your installation and "
1216                         "try Options/Reconfigure..." << endl;
1217         }
1218         loaded = true;
1219 }
1220
1221
1222 //////////////////////////////////////////
1223
1224 // Gets textclass number from name
1225 pair<bool, LyXTextClassList::size_type> const
1226 LyXTextClassList::NumberOfClass(string const & textclass) const
1227 {
1228         ClassList::const_iterator cit =
1229                 find_if(classlist.begin(), classlist.end(),
1230                         lyx::compare_memfun(&LyXTextClass::name, textclass));
1231         return cit != classlist.end() ?
1232                 make_pair(true, size_type(cit - classlist.begin())) :
1233                 make_pair(false, size_type(0));
1234 }
1235
1236
1237 // Gets layout structure from style number and textclass number
1238 LyXLayout const &
1239 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1240                         LyXTextClass::size_type layout) const
1241 {
1242         classlist[textclass].load();
1243         if (layout < classlist[textclass].numLayouts())
1244                 return classlist[textclass][layout];
1245         return classlist[textclass][0];
1246 }
1247
1248
1249 // Gets layout number from name and textclass number
1250 pair<bool, LyXTextClass::size_type> const
1251 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1252                                  string const & name) const
1253 {
1254         classlist[textclass].load();
1255         for (unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1256                 if (classlist[textclass][i].name() == name)
1257                         return make_pair(true, i);
1258         }
1259         if (name == "dummy")
1260                 return make_pair(true, LyXTextClassList::size_type(LYX_DUMMY_LAYOUT));
1261         return make_pair(false, LyXTextClass::size_type(0)); // not found
1262 }
1263
1264
1265 // Gets a layout (style) name from layout number and textclass number
1266 string const &
1267 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1268                                LyXTextClass::size_type layout) const
1269 {
1270         static string const dummy("dummy");
1271         classlist[textclass].load();
1272         if (layout < classlist[textclass].numLayouts())
1273                 return classlist[textclass][layout].name();
1274         return dummy;
1275 }
1276
1277
1278 // Gets a textclass name from number
1279 string const &
1280 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1281 {
1282         static string const dummy("dummy");
1283         if (classlist.size() == 0) {
1284                 return dummy;
1285         }
1286         lyx::Assert(number < classlist.size());
1287         return classlist[number].name();
1288 }
1289
1290
1291 // Gets a textclass latexname from number
1292 string const &
1293 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1294 {
1295         static string const dummy("dummy");
1296         classlist[number].load();
1297         if (classlist.size() == 0) {
1298                 return dummy;
1299         }
1300         lyx::Assert(number < classlist.size());
1301         return classlist[number].latexname();
1302 }
1303
1304
1305 // Gets a textclass description from number
1306 string const &
1307 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1308 {
1309         static string const dummy("dummy");
1310         if (classlist.size() == 0) {
1311                 return dummy;
1312         }
1313         lyx::Assert(number < classlist.size());
1314         return classlist[number].description();
1315 }
1316
1317
1318 // Gets a textclass structure from number
1319 LyXTextClass const &
1320 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1321 {
1322         classlist[textclass].load();
1323         if (textclass < classlist.size())
1324                 return classlist[textclass];
1325         else
1326                 return classlist[0];
1327 }
1328
1329
1330 void LyXTextClassList::Add(LyXTextClass const & t)
1331 {
1332         classlist.push_back(t);
1333 }
1334
1335
1336 // used when sorting the textclass list.
1337 class less_textclass_desc {
1338 public:
1339         int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1340                 return tc1.description() < tc2.description();
1341         }
1342 };
1343
1344
1345 // Reads LyX textclass definitions according to textclass config file
1346 bool LyXTextClassList::Read ()
1347 {
1348         LyXLex lex(0, 0);
1349         string real_file = LibFileSearch("", "textclass.lst");
1350         lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1351                               << real_file << "'" << endl;
1352
1353         if (real_file.empty()) {
1354                 lyxerr << "LyXTextClassList::Read: unable to find "
1355                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1356                        << "'. Exiting." << endl;
1357
1358                 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1359                            _("Check that the file \"textclass.lst\""),
1360                            _("is installed correctly. Sorry, has to exit :-("));
1361                 return false;
1362                 // This causes LyX to end... Not a desirable behaviour. Lgb
1363                 // What do you propose? That the user gets a file dialog
1364                 // and is allowed to hunt for the file? (Asger)
1365                 // more that we have a layout for minimal.cls statically
1366                 // compiled in... (Lgb)
1367         }
1368
1369         if (!lex.setFile(real_file)) {
1370                 lyxerr << "LyXTextClassList::Read: "
1371                         "lyxlex was not able to set file: "
1372                        << real_file << endl;
1373         }
1374         
1375         if (!lex.IsOK()) {
1376                 lyxerr << "LyXTextClassList::Read: unable to open "
1377                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1378                        << "'\nCheck your installation. LyX can't continue."
1379                        << endl;
1380                 return false;
1381         }
1382         bool finished = false;
1383         string fname, clname, desc;
1384         // Parse config-file
1385         lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1386         while (lex.IsOK() && !finished) {
1387                 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1388                 switch (lex.lex()) {
1389                 case LyXLex::LEX_FEOF:
1390                         finished = true;
1391                         break;
1392                 default:
1393                         fname = lex.GetString();
1394                         lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1395                         if (lex.next()) {
1396                                 clname = lex.GetString();
1397                                 lyxerr[Debug::TCLASS]
1398                                         << "Clname: " << clname << endl;
1399                                 if (lex.next()) {
1400                                               desc = lex.GetString();
1401                                               lyxerr[Debug::TCLASS]
1402                                                       << "Desc: " << desc << endl;
1403                                               // This code is run when we have
1404                                               // fname, clname and desc
1405                                               LyXTextClass tmpl(fname,
1406                                                                 clname,
1407                                                                 desc);
1408                                               if (lyxerr.
1409                                                   debugging(Debug::TCLASS)) {
1410                                                       tmpl.load();
1411                                               }
1412                                               Add (tmpl);
1413                                 }
1414                         }
1415                 }
1416         }
1417         lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1418
1419         if (classlist.size() == 0) {
1420                 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1421                        << endl;
1422                 WriteAlert(_("LyX wasn't able to find any layout description!"),
1423                            _("Check the contents of  the file \"textclass.lst\""),
1424                            _("Sorry, has to exit :-("));
1425                 return false;
1426         }
1427         // Ok everything loaded ok, now sort the list.
1428         sort(classlist.begin(), classlist.end(), less_textclass_desc());
1429         return true;
1430 }
1431
1432         
1433 /* Load textclass
1434    Returns false if this fails
1435 */
1436 bool
1437 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1438 {
1439         bool result = true;
1440         if (number < classlist.size()) {
1441                 classlist[number].load();
1442                 if (classlist[number].numLayouts() == 0) {
1443                         result = false;
1444                 }
1445         } else {
1446                 result = false;
1447         }
1448         return result;
1449 }
1450
1451
1452 std::ostream & operator<<(std::ostream & os, LyXTextClass::PageSides p)
1453 {
1454         switch (p) {
1455         case LyXTextClass::OneSide:
1456                 os << "1";
1457                 break;
1458         case LyXTextClass::TwoSides:
1459                 os << "2";
1460                 break;
1461         }
1462         return os;
1463 }
1464