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