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