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