]> git.lyx.org Git - lyx.git/blob - src/layout.C
Reverted the reverted changes - 1.
[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
602 namespace {
603
604 keyword_item endlabelTypeTags[] = {
605         { "box",        END_LABEL_BOX },
606         { "filled_box", END_LABEL_FILLED_BOX },
607         { "no_label",   END_LABEL_NO_LABEL },
608         { "static",     END_LABEL_STATIC }
609 };
610
611 } // namespace anon
612
613
614 void LyXLayout::readEndLabelType(LyXLex & lexrc)
615 {
616         pushpophelper pph(lexrc, endlabelTypeTags,
617                           END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
618         int le = lexrc.lex();
619         switch (le) {
620         case LyXLex::LEX_UNDEF:
621                 lexrc.printError("Unknown labeltype tag `$$Token'");
622                 break;
623         case END_LABEL_STATIC:
624         case END_LABEL_BOX:
625         case END_LABEL_FILLED_BOX:
626         case END_LABEL_NO_LABEL:
627                 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
628                 break;
629         default:
630                 lyxerr << "Unhandled value " << le
631                        << " in LyXLayout::readEndLabelType." << endl;
632                 break;
633         }
634 }
635
636
637 void LyXLayout::readMargin(LyXLex & lexrc)
638 {
639         keyword_item marginTags[] = {
640                 { "dynamic",           MARGIN_DYNAMIC },
641                 { "first_dynamic",     MARGIN_FIRST_DYNAMIC },
642                 { "manual",            MARGIN_MANUAL },
643                 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
644                 { "static",            MARGIN_STATIC }
645         };
646
647         pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
648
649         int le = lexrc.lex();
650         switch (le) {
651         case LyXLex::LEX_UNDEF:
652                 lexrc.printError("Unknown margin type tag `$$Token'");
653                 return;
654         case MARGIN_STATIC:
655         case MARGIN_MANUAL:
656         case MARGIN_DYNAMIC:
657         case MARGIN_FIRST_DYNAMIC:
658         case MARGIN_RIGHT_ADDRESS_BOX:
659                 margintype = static_cast<LYX_MARGIN_TYPE>(le);
660                 break;
661         default:
662                 lyxerr << "Unhandled value " << le
663                        << " in LyXLayout::readMargin." << endl;
664                 break;
665         }
666 }
667
668
669 void LyXLayout::readLatexType(LyXLex & lexrc)
670 {
671         keyword_item latexTypeTags[] = {
672                 { "command",          LATEX_COMMAND },
673                 { "environment",      LATEX_ENVIRONMENT },
674                 { "item_environment", LATEX_ITEM_ENVIRONMENT },
675                 { "list_environment", LATEX_LIST_ENVIRONMENT },
676                 { "paragraph",        LATEX_PARAGRAPH }
677         };
678
679         pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
680         int le = lexrc.lex();
681         switch (le) {
682         case LyXLex::LEX_UNDEF:
683                 lexrc.printError("Unknown latextype tag `$$Token'");
684                 return;
685         case LATEX_PARAGRAPH:
686         case LATEX_COMMAND:
687         case LATEX_ENVIRONMENT:
688         case LATEX_ITEM_ENVIRONMENT:
689         case LATEX_LIST_ENVIRONMENT:
690                 latextype = static_cast<LYX_LATEX_TYPES>(le);
691                 break;
692         default:
693                 lyxerr << "Unhandled value " << le
694                        << " in LyXLayout::readLatexType." << endl;
695                 break;
696         }
697 }
698
699
700 enum SpacingTags {
701         ST_SPACING_SINGLE = 1,
702         ST_SPACING_ONEHALF,
703         ST_SPACING_DOUBLE,
704         ST_OTHER
705 };
706
707
708 void LyXLayout::readSpacing(LyXLex & lexrc)
709 {
710         keyword_item spacingTags[] = {
711                 {"double",  ST_SPACING_DOUBLE },
712                 {"onehalf", ST_SPACING_ONEHALF },
713                 {"other",   ST_OTHER },
714                 {"single",  ST_SPACING_SINGLE }
715         };
716
717         pushpophelper pph(lexrc, spacingTags, ST_OTHER);
718         int le = lexrc.lex();
719         switch (le) {
720         case LyXLex::LEX_UNDEF:
721                 lexrc.printError("Unknown spacing token `$$Token'");
722                 return;
723         default: break;
724         }
725         switch (static_cast<SpacingTags>(le)) {
726         case ST_SPACING_SINGLE:
727                 spacing.set(Spacing::Single);
728                 break;
729         case ST_SPACING_ONEHALF:
730                 spacing.set(Spacing::Onehalf);
731                 break;
732         case ST_SPACING_DOUBLE:
733                 spacing.set(Spacing::Double);
734                 break;
735         case ST_OTHER:
736                 lexrc.next();
737                 spacing.set(Spacing::Other, lexrc.GetFloat());
738                 break;
739         }
740 }
741
742
743 /* ******************************************************************* */
744
745 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
746                            string const & desc)
747         : name_(fn), latexname_(cln), description_(desc)
748 {
749         outputType_ = LATEX;
750         columns_ = 1;
751         sides_ = OneSide;
752         secnumdepth_ = 3;
753         tocdepth_ = 3;
754         pagestyle_ = "default";
755         maxcounter_ = LABEL_COUNTER_CHAPTER;
756         defaultfont_ = LyXFont(LyXFont::ALL_SANE);
757         opt_fontsize_ = "10|11|12";
758         opt_pagestyle_ = "empty|plain|headings|fancy";
759         provides_ = nothing;
760         loaded = false;
761 }
762
763
764 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
765 {
766         lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
767         if (!lay.Read(lexrc, *this)) {
768                 // Reslove fonts
769                 lay.resfont = lay.font;
770                 lay.resfont.realize(defaultfont());
771                 lay.reslabelfont = lay.labelfont;
772                 lay.reslabelfont.realize(defaultfont());
773                 return false; // no errors
774         } 
775         lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
776         return true;
777 }
778
779
780 enum TextClassTags {
781         TC_OUTPUTTYPE = 1,
782         TC_INPUT,
783         TC_STYLE,
784         TC_NOSTYLE,
785         TC_COLUMNS,
786         TC_SIDES,
787         TC_PAGESTYLE,
788         TC_DEFAULTFONT,
789         TC_MAXCOUNTER,
790         TC_SECNUMDEPTH,
791         TC_TOCDEPTH,
792         TC_CLASSOPTIONS,
793         TC_PREAMBLE,
794         TC_PROVIDESAMSMATH,
795         TC_PROVIDESMAKEIDX,
796         TC_PROVIDESURL,
797         TC_LEFTMARGIN,
798         TC_RIGHTMARGIN
799 };
800
801
802 // Reads a textclass structure from file.
803 bool LyXTextClass::Read(string const & filename, bool merge)
804 {
805         keyword_item textClassTags[] = {
806                 { "classoptions",    TC_CLASSOPTIONS },
807                 { "columns",         TC_COLUMNS },
808                 { "defaultfont",     TC_DEFAULTFONT },
809                 { "input",           TC_INPUT },
810                 { "leftmargin",      TC_LEFTMARGIN },
811                 { "maxcounter",      TC_MAXCOUNTER },
812                 { "nostyle",         TC_NOSTYLE },
813                 { "outputtype",      TC_OUTPUTTYPE },
814                 { "pagestyle",       TC_PAGESTYLE },
815                 { "preamble",        TC_PREAMBLE },
816                 { "providesamsmath", TC_PROVIDESAMSMATH },
817                 { "providesmakeidx", TC_PROVIDESMAKEIDX },
818                 { "providesurl",     TC_PROVIDESURL },
819                 { "rightmargin",     TC_RIGHTMARGIN },
820                 { "secnumdepth",     TC_SECNUMDEPTH },
821                 { "sides",           TC_SIDES },
822                 { "style",           TC_STYLE },
823                 { "tocdepth",        TC_TOCDEPTH }
824         };
825
826         if (!merge)
827                 lyxerr[Debug::TCLASS] << "Reading textclass "
828                                       << MakeDisplayPath(filename)
829                                       << endl;
830         else
831                 lyxerr[Debug::TCLASS] << "Reading input file "
832                                      << MakeDisplayPath(filename)
833                                      << endl;
834         
835         LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
836         bool error = false;
837
838         lexrc.setFile(filename);
839         if (!lexrc.IsOK()) error = true; 
840
841         // parsing
842         while (lexrc.IsOK() && !error) {
843                 int le = lexrc.lex();
844                 switch (le) {
845                 case LyXLex::LEX_FEOF:
846                         continue; 
847
848                 case LyXLex::LEX_UNDEF:                                 
849                         lexrc.printError("Unknown TextClass tag `$$Token'");
850                         error = true;
851                         continue; 
852                 default: break;
853                 }
854                 switch (static_cast<TextClassTags>(le)) {
855                 case TC_OUTPUTTYPE:   // output type definition
856                         readOutputType(lexrc);
857                         break;
858                         
859                 case TC_INPUT: // Include file
860                         if (lexrc.next()) {
861                                 string tmp = LibFileSearch("layouts",
862                                                             lexrc.GetString(), 
863                                                             "layout");
864                                 
865                                 if (Read(tmp, true)) {
866                                         lexrc.printError("Error reading input"
867                                                          "file: "+tmp);
868                                         error = true;
869                                 }
870                         }
871                         break;
872
873                 case TC_STYLE:
874                         if (lexrc.next()) {
875                                 string name = subst(lexrc.GetString(),
876                                                     '_', ' ');
877                                 if (hasLayout(name)) {
878                                         LyXLayout & lay = GetLayout(name);
879                                         error = do_readStyle(lexrc, lay);
880                                 } else {
881                                         LyXLayout lay;
882                                         lay.setName(name);
883                                         if (!(error = do_readStyle(lexrc, lay)))
884                                                 layoutlist.push_back(lay);
885                                 }
886                         }
887                         else {
888                                 lexrc.printError("No name given for style: `$$Token'.");
889                                 error = true;
890                         }
891                         break;
892
893                 case TC_NOSTYLE:
894                         if (lexrc.next()) {
895                                 string style = subst(lexrc.GetString(),
896                                                      '_', ' ');
897                                 if (!delete_layout(style))
898                                         lexrc.printError("Cannot delete style"
899                                                          " `$$Token'");
900                         }
901                         break;
902
903                 case TC_COLUMNS:
904                         if (lexrc.next())
905                                 columns_ = lexrc.GetInteger();
906                         break;
907                         
908                 case TC_SIDES:
909                         if (lexrc.next()) {
910                                 switch (lexrc.GetInteger()) {
911                                 case 1: sides_ = OneSide; break;
912                                 case 2: sides_ = TwoSides; break;
913                                 default:
914                                         lyxerr << "Impossible number of page"
915                                                 " sides, setting to one."
916                                                << endl;
917                                         sides_ = OneSide;
918                                         break;
919                                 }
920                         }
921                         break;
922                         
923                 case TC_PAGESTYLE:
924                         lexrc.next();
925                         pagestyle_ = strip(lexrc.GetString());
926                         break;
927                         
928                 case TC_DEFAULTFONT:
929                         defaultfont_.lyxRead(lexrc);
930                         if (!defaultfont_.resolved()) {
931                                 lexrc.printError("Warning: defaultfont should "
932                                                  "be fully instantiated!");
933                                 defaultfont_.realize(LyXFont(LyXFont::ALL_SANE));
934                         }
935                         break;
936
937                 case TC_MAXCOUNTER:
938                         readMaxCounter(lexrc);
939                         break;
940
941                 case TC_SECNUMDEPTH:
942                         lexrc.next();
943                         secnumdepth_ = lexrc.GetInteger();
944                         break;
945
946                 case TC_TOCDEPTH:
947                         lexrc.next();
948                         tocdepth_ = lexrc.GetInteger();
949                         break;
950
951                         // First step to support options 
952                 case TC_CLASSOPTIONS:
953                         readClassOptions(lexrc);
954                         break;
955
956                 case TC_PREAMBLE:
957                         preamble_ = lexrc.getLongString("EndPreamble");
958                         break;
959
960                 case TC_PROVIDESAMSMATH:
961                         if (lexrc.next() && lexrc.GetInteger())
962                                 provides_ |= amsmath;
963                         break;
964
965                 case TC_PROVIDESMAKEIDX:
966                         if (lexrc.next() && lexrc.GetInteger())
967                                 provides_ |= makeidx;
968                         break;
969
970                 case TC_PROVIDESURL:
971                         if (lexrc.next() && lexrc.GetInteger())
972                                 provides_ = url;
973                         break;
974
975                 case TC_LEFTMARGIN:     // left margin type
976                         if (lexrc.next())
977                                 leftmargin_ = lexrc.GetString();
978                         break;                  
979
980                 case TC_RIGHTMARGIN:    // right margin type
981                         if (lexrc.next())
982                                 rightmargin_ = lexrc.GetString();
983                         break;
984                 }
985         }       
986
987         if (!merge) { // we are at top level here.
988                 lyxerr[Debug::TCLASS] << "Finished reading textclass " 
989                                       << MakeDisplayPath(filename)
990                                       << endl;
991         } else
992                 lyxerr[Debug::TCLASS] << "Finished reading input file " 
993                                       << MakeDisplayPath(filename)
994                                       << endl;
995
996         return error;
997 }
998
999
1000 void LyXTextClass::readOutputType(LyXLex & lexrc)
1001 {
1002         keyword_item outputTypeTags[] = {
1003                 { "docbook", DOCBOOK },
1004                 { "latex", LATEX },
1005                 { "linuxdoc", LINUXDOC },
1006                 { "literate", LITERATE }
1007         };
1008
1009         pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1010
1011         int le = lexrc.lex();
1012         switch (le) {
1013         case LyXLex::LEX_UNDEF:
1014                 lexrc.printError("Unknown output type `$$Token'");
1015                 return;
1016         case LATEX:
1017         case LINUXDOC:
1018         case DOCBOOK:
1019         case LITERATE:
1020                 outputType_ = static_cast<OutputType>(le);
1021                 break;
1022         default:
1023                 lyxerr << "Unhandled value " << le
1024                        << " in LyXTextClass::readOutputType." << endl;
1025
1026                 break;
1027         }
1028 }
1029
1030
1031 enum MaxCounterTags {
1032         MC_COUNTER_CHAPTER = 1,
1033         MC_COUNTER_SECTION,
1034         MC_COUNTER_SUBSECTION,
1035         MC_COUNTER_SUBSUBSECTION,
1036         MC_COUNTER_PARAGRAPH,
1037         MC_COUNTER_SUBPARAGRAPH,
1038         MC_COUNTER_ENUMI,
1039         MC_COUNTER_ENUMII,
1040         MC_COUNTER_ENUMIII,
1041         MC_COUNTER_ENUMIV
1042 };
1043
1044
1045 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1046 {
1047         keyword_item maxCounterTags[] = {
1048                 {"counter_chapter", MC_COUNTER_CHAPTER },
1049                 {"counter_enumi", MC_COUNTER_ENUMI },
1050                 {"counter_enumii", MC_COUNTER_ENUMII },
1051                 {"counter_enumiii", MC_COUNTER_ENUMIII },
1052                 {"counter_enumiv", MC_COUNTER_ENUMIV },
1053                 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1054                 {"counter_section", MC_COUNTER_SECTION },
1055                 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1056                 {"counter_subsection", MC_COUNTER_SUBSECTION },
1057                 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1058         };
1059
1060         pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1061         int le = lexrc.lex();
1062         switch (le) {
1063         case LyXLex::LEX_UNDEF:
1064                 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1065                 return; 
1066         default: break;
1067         }
1068         switch (static_cast<MaxCounterTags>(le)) {
1069         case MC_COUNTER_CHAPTER:
1070                 maxcounter_ = LABEL_COUNTER_CHAPTER;
1071                 break;
1072         case MC_COUNTER_SECTION:
1073                 maxcounter_ = LABEL_COUNTER_SECTION;
1074                 break;
1075         case MC_COUNTER_SUBSECTION:
1076                 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1077                 break;
1078         case MC_COUNTER_SUBSUBSECTION:
1079                 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1080                 break;
1081         case MC_COUNTER_PARAGRAPH:
1082                 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1083                 break;
1084         case MC_COUNTER_SUBPARAGRAPH:
1085                 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1086                 break;
1087         case MC_COUNTER_ENUMI:
1088                 maxcounter_ = LABEL_COUNTER_ENUMI;
1089                 break;
1090         case MC_COUNTER_ENUMII:
1091                 maxcounter_ = LABEL_COUNTER_ENUMII;
1092                 break;
1093         case MC_COUNTER_ENUMIII:
1094                 maxcounter_ = LABEL_COUNTER_ENUMIII;
1095                 break;
1096         case MC_COUNTER_ENUMIV:
1097                 maxcounter_ = LABEL_COUNTER_ENUMIV;
1098                 break;
1099         }
1100 }
1101
1102
1103 enum ClassOptionsTags {
1104         CO_FONTSIZE = 1,
1105         CO_PAGESTYLE,
1106         CO_OTHER,
1107         CO_END
1108 };
1109
1110
1111 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1112 {
1113         keyword_item classOptionsTags[] = {
1114                 {"end", CO_END },
1115                 {"fontsize", CO_FONTSIZE },
1116                 {"other", CO_OTHER },
1117                 {"pagestyle", CO_PAGESTYLE }
1118         };
1119
1120         lexrc.pushTable(classOptionsTags, CO_END);
1121         bool getout = false;
1122         while (!getout && lexrc.IsOK()) {
1123                 int le = lexrc.lex();
1124                 switch (le) {
1125                 case LyXLex::LEX_UNDEF:
1126                         lexrc.printError("Unknown ClassOption tag `$$Token'");
1127                         continue; 
1128                 default: break;
1129                 }
1130                 switch (static_cast<ClassOptionsTags>(le)) {
1131                 case CO_FONTSIZE:
1132                         lexrc.next();
1133                         opt_fontsize_ = strip(lexrc.GetString());
1134                         break;
1135                 case CO_PAGESTYLE:
1136                         lexrc.next();
1137                         opt_pagestyle_ = strip(lexrc.GetString()); 
1138                         break;
1139                 case CO_OTHER:
1140                         lexrc.next();
1141                         options_ = lexrc.GetString();
1142                         break;
1143                 case CO_END:
1144                         getout = true;
1145                         break;
1146                 }
1147         }
1148         lexrc.popTable();
1149 }
1150
1151
1152 bool LyXTextClass::hasLayout(string const & name) const
1153 {
1154         return find_if(layoutlist.begin(), layoutlist.end(),
1155                        lyx::compare_memfun(&LyXLayout::name, name))
1156                 != layoutlist.end();
1157 }
1158
1159
1160 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1161 {
1162         LayoutList::const_iterator cit =
1163                 find_if(layoutlist.begin(),
1164                         layoutlist.end(),
1165                         lyx::compare_memfun(&LyXLayout::name, name));
1166         lyx::Assert(cit != layoutlist.end()); // we require the name to exist
1167         return (*cit);
1168 }
1169
1170
1171 LyXLayout & LyXTextClass::GetLayout(string const & name)
1172 {
1173         LayoutList::iterator it =
1174                 find_if(layoutlist.begin(),
1175                         layoutlist.end(),
1176                         lyx::compare_memfun(&LyXLayout::name, name));
1177         lyx::Assert(it != layoutlist.end()); // we require the name to exist
1178         return (*it);
1179 }
1180
1181
1182 bool LyXTextClass::delete_layout(string const & name)
1183 {
1184         LayoutList::iterator it =
1185                 remove_if(layoutlist.begin(), layoutlist.end(),
1186                           lyx::compare_memfun(&LyXLayout::name, name));
1187         LayoutList::iterator end = layoutlist.end();
1188         bool const ret = (it != end);
1189         layoutlist.erase(it, end);
1190         return ret;
1191 }
1192
1193
1194 // Load textclass info if not loaded yet
1195 void LyXTextClass::load()
1196 {
1197         if (loaded) return;
1198
1199         // Read style-file
1200         string const real_file = LibFileSearch("layouts", name_, "layout");
1201
1202         if (Read(real_file)) {
1203                 lyxerr << "Error reading `"
1204                        << MakeDisplayPath(real_file)
1205                        << "'\n(Check `" << name_
1206                        << "')\nCheck your installation and "
1207                         "try Options/Reconfigure..." << endl;
1208         }
1209         loaded = true;
1210 }
1211
1212
1213 //////////////////////////////////////////
1214
1215 // Gets textclass number from name
1216 pair<bool, LyXTextClassList::size_type> const
1217 LyXTextClassList::NumberOfClass(string const & textclass) const
1218 {
1219         ClassList::const_iterator cit =
1220                 find_if(classlist.begin(), classlist.end(),
1221                         lyx::compare_memfun(&LyXTextClass::name, textclass));
1222         return cit != classlist.end() ?
1223                 make_pair(true, size_type(cit - classlist.begin())) :
1224                 make_pair(false, size_type(0));
1225 }
1226
1227
1228 // Gets layout structure from style number and textclass number
1229 LyXLayout const &
1230 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1231                         LyXTextClass::size_type layout) const
1232 {
1233         classlist[textclass].load();
1234         if (layout < classlist[textclass].numLayouts())
1235                 return classlist[textclass][layout];
1236         return classlist[textclass][0];
1237 }
1238
1239
1240 // Gets layout number from name and textclass number
1241 pair<bool, LyXTextClass::size_type> const
1242 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1243                                  string const & name) const
1244 {
1245         classlist[textclass].load();
1246         for (unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1247                 if (classlist[textclass][i].name() == name)
1248                         return make_pair(true, i);
1249         }
1250         if (name == "dummy")
1251                 return make_pair(true, LyXTextClassList::size_type(LYX_DUMMY_LAYOUT));
1252         return make_pair(false, LyXTextClass::size_type(0)); // not found
1253 }
1254
1255
1256 // Gets a layout (style) name from layout number and textclass number
1257 string const &
1258 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1259                                LyXTextClass::size_type layout) const
1260 {
1261         static string dummy("dummy");
1262         classlist[textclass].load();
1263         if (layout < classlist[textclass].numLayouts())
1264                 return classlist[textclass][layout].name();
1265         return dummy;
1266 }
1267
1268
1269 // Gets a textclass name from number
1270 string const &
1271 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1272 {
1273         static string dummy("dummy");
1274         if (classlist.size() == 0) {
1275                 return dummy;
1276         }
1277         lyx::Assert(number < classlist.size());
1278         return classlist[number].name();
1279 }
1280
1281
1282 // Gets a textclass latexname from number
1283 string const &
1284 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1285 {
1286         static string dummy("dummy");
1287         classlist[number].load();
1288         if (classlist.size() == 0) {
1289                 return dummy;
1290         }
1291         lyx::Assert(number < classlist.size());
1292         return classlist[number].latexname();
1293 }
1294
1295
1296 // Gets a textclass description from number
1297 string const &
1298 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1299 {
1300         static string dummy("dummy");
1301         if (classlist.size() == 0) {
1302                 return dummy;
1303         }
1304         lyx::Assert(number < classlist.size());
1305         return classlist[number].description();
1306 }
1307
1308
1309 // Gets a textclass structure from number
1310 LyXTextClass const &
1311 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1312 {
1313         classlist[textclass].load();
1314         if (textclass < classlist.size())
1315                 return classlist[textclass];
1316         else
1317                 return classlist[0];
1318 }
1319
1320
1321 void LyXTextClassList::Add(LyXTextClass const & t)
1322 {
1323         classlist.push_back(t);
1324 }
1325
1326
1327 // used when sorting the textclass list.
1328 class less_textclass_desc {
1329 public:
1330         int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1331                 return tc1.description() < tc2.description();
1332         }
1333 };
1334
1335
1336 // Reads LyX textclass definitions according to textclass config file
1337 bool LyXTextClassList::Read ()
1338 {
1339         LyXLex lex(0, 0);
1340         string real_file = LibFileSearch("", "textclass.lst");
1341         lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1342                               << real_file << "'" << endl;
1343
1344         if (real_file.empty()) {
1345                 lyxerr << "LyXTextClassList::Read: unable to find "
1346                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1347                        << "'. Exiting." << endl;
1348
1349                 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1350                            _("Check that the file \"textclass.lst\""),
1351                            _("is installed correctly. Sorry, has to exit :-("));
1352                 return false;
1353                 // This causes LyX to end... Not a desirable behaviour. Lgb
1354                 // What do you propose? That the user gets a file dialog
1355                 // and is allowed to hunt for the file? (Asger)
1356                 // more that we have a layout for minimal.cls statically
1357                 // compiled in... (Lgb)
1358         }
1359
1360         if (!lex.setFile(real_file)) {
1361                 lyxerr << "LyXTextClassList::Read: "
1362                         "lyxlex was not able to set file: "
1363                        << real_file << endl;
1364         }
1365         
1366         if (!lex.IsOK()) {
1367                 lyxerr << "LyXTextClassList::Read: unable to open "
1368                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1369                        << "'\nCheck your installation. LyX can't continue."
1370                        << endl;
1371                 return false;
1372         }
1373         bool finished = false;
1374         string fname, clname, desc;
1375         // Parse config-file
1376         lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1377         while (lex.IsOK() && !finished) {
1378                 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1379                 switch (lex.lex()) {
1380                 case LyXLex::LEX_FEOF:
1381                         finished = true;
1382                         break;
1383                 default:
1384                         fname = lex.GetString();
1385                         lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1386                         if (lex.next()) {
1387                                 clname = lex.GetString();
1388                                 lyxerr[Debug::TCLASS]
1389                                         << "Clname: " << clname << endl;
1390                                 if (lex.next()) {
1391                                               desc = lex.GetString();
1392                                               lyxerr[Debug::TCLASS]
1393                                                       << "Desc: " << desc << endl;
1394                                               // This code is run when we have
1395                                               // fname, clname and desc
1396                                               LyXTextClass tmpl(fname,
1397                                                                 clname,
1398                                                                 desc);
1399                                               if (lyxerr.
1400                                                   debugging(Debug::TCLASS)) {
1401                                                       tmpl.load();
1402                                               }
1403                                               Add (tmpl);
1404                                 }
1405                         }
1406                 }
1407         }
1408         lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1409
1410         if (classlist.size() == 0) {
1411                 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1412                        << endl;
1413                 WriteAlert(_("LyX wasn't able to find any layout description!"),
1414                            _("Check the contents of  the file \"textclass.lst\""),
1415                            _("Sorry, has to exit :-("));
1416                 return false;
1417         }
1418         // Ok everything loaded ok, now sort the list.
1419         sort(classlist.begin(), classlist.end(), less_textclass_desc());
1420         return true;
1421 }
1422
1423         
1424 /* Load textclass
1425    Returns false if this fails
1426 */
1427 bool
1428 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1429 {
1430         bool result = true;
1431         if (number < classlist.size()) {
1432                 classlist[number].load();
1433                 if (classlist[number].numLayouts() == 0) {
1434                         result = false;
1435                 }
1436         } else {
1437                 result = false;
1438         }
1439         return result;
1440 }
1441
1442
1443 std::ostream & operator<<(std::ostream & os, LyXTextClass::PageSides p)
1444 {
1445         switch (p) {
1446         case LyXTextClass::OneSide:
1447                 os << "1";
1448                 break;
1449         case LyXTextClass::TwoSides:
1450                 os << "2";
1451                 break;
1452         }
1453         return os;
1454 }
1455