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