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