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