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