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