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