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