This commit was manufactured by cvs2svn to create tag
[lyx.git] / src / layout.C
blob9c0dcf112542f0e4a60cf7c0b18912f2e015be62
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  * ====================================================== */
11 #include <config.h>
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
17 #include <algorithm>
19 #include "definitions.h"
20 #include "layout.h"
21 #include "lyxlex.h"
22 #include "support/filetools.h"
23 #include "lyx_gui_misc.h"
24 #include "debug.h"
25 #include "gettext.h"
26 #include "support/LAssert.h"
28 // Global variable: textclass table.
29 LyXTextClassList textclasslist;
31 // Reads the style files
32 void LyXSetStyle()
34         lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
35         
36         if (!textclasslist.Read()) {
37                 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
38                         "during parsing.\n             Exiting." << endl;
39                 exit(1);
40         }
42         lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
46 //  The order of the LayoutTags enum is no more important. [asierra300396]
47 // Tags indexes.
48 enum LayoutTags {
49         LT_ALIGN, LT_ALIGNPOSSIBLE, 
50         LT_BLOCK, LT_MARGIN,
51         LT_BOTTOMSEP, LT_CENTER, LT_CENTERED_TOP_ENVIRONMENT, LT_COLUMNS,
52         LT_COPYSTYLE, LT_OBSOLETEDBY,
53         LT_COMMAND, LT_COUNTER_CHAPTER, LT_COUNTER_ENUMI, LT_COUNTER_ENUMII,
54         LT_COUNTER_ENUMIII, LT_COUNTER_ENUMIV, LT_COUNTER_PARAGRAPH,
55         LT_COUNTER_SECTION, LT_COUNTER_SUBPARAGRAPH, LT_COUNTER_SUBSECTION,
56         LT_COUNTER_SUBSUBSECTION, LT_DEFAULTFONT, LT_DYNAMIC, LT_EMPTY,
57         LT_END, LT_ENVIRONMENT, LT_ENVIRONMENT_DEFAULT, 
58         LT_FANCYHDR, LT_FILL_BOTTOM, LT_FILL_TOP, LT_FIRST_COUNTER,
59         LT_FIRST_DYNAMIC, LT_FONT, LT_FREE_SPACING, LT_HEADINGS, LT_INPUT,
60         LT_ITEM_ENVIRONMENT, LT_ITEMSEP, LT_KEEPEMPTY,
61         LT_LABEL_BOTTOMSEP, LT_LABELFONT, LT_TEXTFONT,
62         LT_LABELINDENT, LT_LABELSEP, LT_LABELSTRING,
63         LT_LABELSTRING_APPENDIX, LT_LABELTYPE,
64         LT_LATEXNAME, LT_LATEXPARAM, LT_LATEXTYPE, LT_LAYOUT, LT_LEFT,
65         LT_LEFTMARGIN,
66         LT_LIST_ENVIRONMENT , LT_MANUAL, LT_MAXCOUNTER, 
67         LT_NEED_PROTECT, LT_NEWLINE,
68         LT_NEXTNOINDENT, LT_NO_LABEL, LT_NOSTYLE,
69         LT_PAGESTYLE, LT_PARAGRAPH,
70         LT_PARINDENT, LT_PARSEP, LT_PARSKIP, LT_PLAIN, LT_PREAMBLE, 
71         LT_PROVIDESAMSMATH, LT_PROVIDESMAKEIDX, LT_PROVIDESURL, LT_RIGHT,
72         LT_RIGHT_ADDRESS_BOX, LT_RIGHTMARGIN, LT_SENSITIVE, LT_SIDES,
73         LT_SPACING, LT_SPACING_SINGLE, LT_SPACING_ONEHALF,
74         LT_SPACING_DOUBLE, LT_OTHER,  LT_CLASSOPTIONS, LT_FONTSIZE,
75         LT_STATIC, LT_STYLE, LT_TOP_ENVIRONMENT, LT_TOPSEP, LT_BIBLIO,
76         LT_INTITLE, LT_SECNUMDEPTH, LT_TOCDEPTH,
77         LT_OUTPUTTYPE, LT_OTLATEX, LT_OTLINUXDOC, LT_OTDOCBOOK, LT_OTLITERATE
81 // This table is sorted alphabetically [asierra 30March96]
82 static keyword_item layoutTags[] = {
83         { "align",                      LT_ALIGN },
84         { "alignpossible",              LT_ALIGNPOSSIBLE },
85         { "bibliography",               LT_BIBLIO },
86         { "block",                      LT_BLOCK },
87         { "bottomsep",                  LT_BOTTOMSEP },
88         { "center",                     LT_CENTER },
89         { "centered_top_environment",   LT_CENTERED_TOP_ENVIRONMENT },
90         { "classoptions",               LT_CLASSOPTIONS },
91         { "columns",                    LT_COLUMNS },
92         { "command",                    LT_COMMAND },
93         { "copystyle",                  LT_COPYSTYLE },
94         { "counter_chapter",            LT_COUNTER_CHAPTER },
95         { "counter_enumi",              LT_COUNTER_ENUMI },
96         { "counter_enumii",             LT_COUNTER_ENUMII },
97         { "counter_enumiii",            LT_COUNTER_ENUMIII },
98         { "counter_enumiv",             LT_COUNTER_ENUMIV },
99         { "counter_paragraph",          LT_COUNTER_PARAGRAPH },
100         { "counter_section",            LT_COUNTER_SECTION },
101         { "counter_subparagraph",       LT_COUNTER_SUBPARAGRAPH },
102         { "counter_subsection",         LT_COUNTER_SUBSECTION },
103         { "counter_subsubsection",      LT_COUNTER_SUBSUBSECTION },
104         { "defaultfont",                LT_DEFAULTFONT },
105         { "docbook",                    LT_OTDOCBOOK },
106         { "double",                     LT_SPACING_DOUBLE },
107         { "dynamic",                    LT_DYNAMIC },
108         { "empty",                      LT_EMPTY },
109         { "end",                        LT_END },
110         { "environment",                LT_ENVIRONMENT },
111         { "environment_default",        LT_ENVIRONMENT_DEFAULT },
112         { "fancyhdr",                   LT_FANCYHDR },
113         { "fill_bottom",                LT_FILL_BOTTOM },
114         { "fill_top",                   LT_FILL_TOP },
115         { "first_counter",              LT_FIRST_COUNTER },
116         { "first_dynamic",              LT_FIRST_DYNAMIC },
117         { "font",                       LT_FONT },
118         { "fontsize",                   LT_FONTSIZE },
119         { "freespacing",                LT_FREE_SPACING },
120         { "headings",                   LT_HEADINGS },
121         { "input",                      LT_INPUT },
122         { "intitle",                    LT_INTITLE },
123         { "item_environment",           LT_ITEM_ENVIRONMENT },
124         { "itemsep",                    LT_ITEMSEP },
125         { "keepempty",                  LT_KEEPEMPTY },
126         { "labelbottomsep",             LT_LABEL_BOTTOMSEP },
127         { "labelfont",                  LT_LABELFONT },
128         { "labelindent",                LT_LABELINDENT },
129         { "labelsep",                   LT_LABELSEP },
130         { "labelstring",                LT_LABELSTRING },
131         { "labelstringappendix",        LT_LABELSTRING_APPENDIX },
132         { "labeltype",                  LT_LABELTYPE },
133         { "latex",                      LT_OTLATEX },
134         { "latexname",                  LT_LATEXNAME },
135         { "latexparam",                 LT_LATEXPARAM },    //arrae970411
136         { "latextype",                  LT_LATEXTYPE },
137         { "layout",                     LT_LAYOUT },
138         { "left",                       LT_LEFT },
139         { "leftmargin",                 LT_LEFTMARGIN },
140         { "linuxdoc",                   LT_OTLINUXDOC },
141         { "list_environment",           LT_LIST_ENVIRONMENT },
142         { "literate",                   LT_OTLITERATE },
143         { "manual",                     LT_MANUAL },
144         { "margin",                     LT_MARGIN },
145         { "maxcounter",                 LT_MAXCOUNTER },
146         { "needprotect",                LT_NEED_PROTECT },
147         { "newline",                    LT_NEWLINE },
148         { "nextnoindent",               LT_NEXTNOINDENT },
149         { "no_label",                   LT_NO_LABEL },
150         { "nostyle",                    LT_NOSTYLE },
151         { "obsoletedby",                LT_OBSOLETEDBY },
152         { "onehalf",                    LT_SPACING_ONEHALF },
153         { "other",                      LT_OTHER },
154         { "outputtype",                 LT_OUTPUTTYPE },
155         { "pagestyle",                  LT_PAGESTYLE },
156         { "paragraph",                  LT_PARAGRAPH },
157         { "parindent",                  LT_PARINDENT },
158         { "parsep",                     LT_PARSEP },
159         { "parskip",                    LT_PARSKIP },
160         { "plain",                      LT_PLAIN },
161         { "preamble",                   LT_PREAMBLE },
162         { "providesamsmath",            LT_PROVIDESAMSMATH },
163         { "providesmakeidx",            LT_PROVIDESMAKEIDX },
164         { "providesurl",                LT_PROVIDESURL },
165         { "right",                      LT_RIGHT },
166         { "right_address_box",          LT_RIGHT_ADDRESS_BOX },
167         { "rightmargin",                LT_RIGHTMARGIN },
168         { "secnumdepth",                LT_SECNUMDEPTH },
169         { "sensitive",                  LT_SENSITIVE },
170         { "sides",                      LT_SIDES },
171         { "single",                     LT_SPACING_SINGLE },
172         { "spacing",                    LT_SPACING },
173         { "static",                     LT_STATIC },
174         { "style",                      LT_STYLE },
175         { "textfont",                   LT_TEXTFONT },
176         { "tocdepth",                   LT_TOCDEPTH },
177         { "top_environment",            LT_TOP_ENVIRONMENT },
178         { "topsep",                     LT_TOPSEP }
182 /////////////////////
184 // Constructor for layout
185 LyXLayout::LyXLayout ()
187         margintype = MARGIN_STATIC;
188         latextype = LATEX_PARAGRAPH;
189         intitle = false;
190         needprotect = false;
191         keepempty = false;
192         font = LyXFont(LyXFont::ALL_INHERIT);
193         labelfont = LyXFont(LyXFont::ALL_INHERIT);
194         resfont = LyXFont(LyXFont::ALL_SANE);
195         reslabelfont = LyXFont(LyXFont::ALL_SANE);
196         nextnoindent = false;
197         parskip = 0.0;
198         itemsep = 0;
199         topsep = 0.0;
200         bottomsep = 0.0;
201         labelbottomsep = 0.0;
202         parsep = 0;
203         align = LYX_ALIGN_BLOCK;
204         alignpossible = LYX_ALIGN_BLOCK;
205         labeltype = LABEL_NO_LABEL;
206         // Should or should not. That is the question.
207         // spacing.set(Spacing::OneHalf);
208         fill_top = false;
209         fill_bottom = false;
210         newline_allowed = true;
211         free_spacing = false;
215 // Reads a layout definition from file
216 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
218         bool error = false;
219         bool finished = false;
220         
221         // parse style section
222         while (!finished && lexrc.IsOK() && !error) {
223                 switch(lexrc.lex()) {
225                 case -2:
226                         break;
228                 case -1:                // parse error
229                         lexrc.printError("Unknown tag `$$Token'");
230                         error = true;
231                         break;
233                 case LT_END:            // end of structure
234                         finished = true;
235                         break;
237                 case LT_COPYSTYLE:     // initialize with a known style
238                         if (lexrc.next()) {
239                                 if (tclass.hasLayout(lexrc.GetString())) {
240                                         string tmpname = name_;
241                                         this->operator=(tclass.GetLayout(lexrc.GetString()));
242                                         name_ = tmpname;
243                                 } else {
244                                         lexrc.printError("Cannot copy known "
245                                                          "style `$$Token'");
246                                 }
247                         }
248                         break;
250                 case LT_OBSOLETEDBY:     // replace with a known style
251                         if (lexrc.next()) {
252                                 if (tclass.hasLayout(lexrc.GetString())) {
253                                         string tmpname = name_;
254                                         this->operator=(tclass.GetLayout(lexrc.GetString()));
255                                         name_ = tmpname;
256                                         if (obsoleted_by().empty())
257                                           obsoleted_by_ = lexrc.GetString();
258                                 } else {
259                                         lexrc.printError("Cannot replace with" 
260                                                          " unknown style "
261                                                          "`$$Token'");
262                                 }
263                         }
264                         break;
266                 case LT_MARGIN:         // Margin style definition.
267                        
268                         switch(lexrc.lex()) {
269                         case LT_STATIC:
270                                 margintype = MARGIN_STATIC;
271                                 break;
272                         case LT_MANUAL:
273                                 margintype = MARGIN_MANUAL;
274                                 break;
275                         case LT_DYNAMIC:
276                                 margintype = MARGIN_DYNAMIC;
277                                 break;
278                         case LT_FIRST_DYNAMIC:
279                                 margintype = MARGIN_FIRST_DYNAMIC;
280                                 break;
281                         case LT_RIGHT_ADDRESS_BOX:
282                                 margintype = MARGIN_RIGHT_ADDRESS_BOX;
283                                 break;
284                         default:
285                                 lexrc.printError("Unknown margin type `$$Token'");
286                                 break;
287                         }
288                         break;
290                 case LT_LATEXTYPE:      // Latex style definition.
291                         switch (lexrc.lex()) {
292                         case LT_PARAGRAPH:
293                                 latextype=LATEX_PARAGRAPH;
294                                 break;
295                         case LT_COMMAND:
296                                 latextype=LATEX_COMMAND;
297                                 break;
298                         case LT_ENVIRONMENT:
299                                 latextype=LATEX_ENVIRONMENT;
300                                 break;
301                         case LT_ITEM_ENVIRONMENT:
302                                 latextype=LATEX_ITEM_ENVIRONMENT;
303                                 break;
304                         case LT_LIST_ENVIRONMENT:
305                                 latextype=LATEX_LIST_ENVIRONMENT;
306                                 break;
307                         default:
308                                 lexrc.printError("Unknown latextype `$$Token'");
309                                 break;
310                         }
311                         break;
313                 case LT_INTITLE:
314                         intitle = lexrc.next() && lexrc.GetInteger();
315                         break;
316                         
317                 case LT_NEED_PROTECT:
318                         needprotect = lexrc.next() && lexrc.GetInteger();
319                         break;
320                         
321                 case LT_KEEPEMPTY:
322                         keepempty = lexrc.next() && lexrc.GetInteger();
323                         break;
325                 case LT_FONT:
326                         font.lyxRead(lexrc);
327                         labelfont=font;
328                         break;
330                 case LT_TEXTFONT:
331                         font.lyxRead(lexrc);
332                         break;
334                 case LT_LABELFONT:
335                         labelfont.lyxRead(lexrc);
336                         break;
338                 case LT_NEXTNOINDENT:   // Indent next paragraph?
339                         if (lexrc.next() && lexrc.GetInteger())
340                                 nextnoindent = true;
341                         else
342                                 nextnoindent = false;
343                         break;
345                 case LT_LATEXNAME:
346                         if (lexrc.next())
347                                 latexname_ = lexrc.GetString();
348                         break;
349                         
350                 case LT_LATEXPARAM:
351                         if (lexrc.next())
352                                 latexparam_ = lexrc.GetString();
353                         break;
355                 case LT_PREAMBLE:
356                         preamble_ = lexrc.getLongString("EndPreamble");
357                         break;
359                 case LT_LABELTYPE:
360                         switch (lexrc.lex()) {
361                         case LT_NO_LABEL:
362                                 labeltype = LABEL_NO_LABEL;
363                                 break;
364                         case LT_MANUAL:
365                                 labeltype = LABEL_MANUAL;
366                                 break;
367                         case LT_TOP_ENVIRONMENT:
368                                 labeltype = LABEL_TOP_ENVIRONMENT;
369                                 break;
370                         case LT_CENTERED_TOP_ENVIRONMENT:
371                                 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
372                                 break;
373                         case LT_STATIC:
374                                 labeltype = LABEL_STATIC;
375                                 break;
376                         case LT_SENSITIVE:
377                                 labeltype = LABEL_SENSITIVE;
378                                 break;
379                         case LT_COUNTER_CHAPTER:
380                                 labeltype = LABEL_COUNTER_CHAPTER;
381                                 break;
382                         case LT_COUNTER_SECTION:
383                                 labeltype = LABEL_COUNTER_SECTION;
384                                 break;
385                         case LT_COUNTER_SUBSECTION:
386                                 labeltype = LABEL_COUNTER_SUBSECTION;
387                                 break;
388                         case LT_COUNTER_SUBSUBSECTION:
389                                 labeltype = LABEL_COUNTER_SUBSUBSECTION;
390                                 break;
391                         case LT_COUNTER_PARAGRAPH:
392                                 labeltype = LABEL_COUNTER_PARAGRAPH;
393                                 break;
394                         case LT_COUNTER_SUBPARAGRAPH:
395                                 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
396                                 break;
397                         case LT_COUNTER_ENUMI:
398                                 labeltype = LABEL_COUNTER_ENUMI;
399                                 break;
400                         case LT_COUNTER_ENUMII:
401                                 labeltype = LABEL_COUNTER_ENUMII;
402                                 break;
403                         case LT_COUNTER_ENUMIII:
404                                 labeltype = LABEL_COUNTER_ENUMIII;
405                                 break;
406                         case LT_COUNTER_ENUMIV:
407                                 labeltype = LABEL_COUNTER_ENUMIV;
408                                 break;
409                         case LT_BIBLIO:
410                                 labeltype = LABEL_BIBLIO;
411                                 break;
412                         default:
413                                 lexrc.printError("Unknown labeltype `$$Token'");
414                         }
415                         break;
417                 case LT_LEFTMARGIN:     // left margin type
418                         if (lexrc.next())
419                                 leftmargin = lexrc.GetString();
420                         break;                  
422                 case LT_RIGHTMARGIN:    // right margin type
423                         if (lexrc.next())
424                                 rightmargin = lexrc.GetString();
425                         break;
427                 case LT_LABELINDENT:    // label indenting flag
428                         if (lexrc.next())
429                                 labelindent = lexrc.GetString();
430                         break;
432                 case LT_PARINDENT:      // paragraph indent. flag
433                         if (lexrc.next())
434                                 parindent = lexrc.GetString();
435                         break;
437                 case LT_PARSKIP:        // paragraph skip size
438                         if (lexrc.next())
439                                 parskip = lexrc.GetFloat();
440                         break;
442                 case LT_ITEMSEP:        // item separation size
443                         if (lexrc.next())
444                                 itemsep = lexrc.GetFloat();
445                         break;
447                 case LT_TOPSEP:         // top separation size
448                         if (lexrc.next())
449                                 topsep = lexrc.GetFloat();
450                         break;
452                 case LT_BOTTOMSEP:      // bottom separation size
453                         if (lexrc.next())
454                                 bottomsep = lexrc.GetFloat();
455                         break;
457                 case LT_LABEL_BOTTOMSEP: // label bottom separation size
458                         if (lexrc.next())
459                                 labelbottomsep = lexrc.GetFloat();
460                         break;
462                 case LT_LABELSEP:       // label separator
463                         if (lexrc.next()) {
464                                 labelsep = subst(lexrc.GetString(), 'x', ' ');
465                         }
466                         break;
468                 case LT_PARSEP:         // par. separation size
469                         if (lexrc.next())
470                                 parsep = lexrc.GetFloat();
471                         break;
473                 case LT_FILL_TOP:       // fill top flag
474                         if (lexrc.next())
475                                 fill_top = lexrc.GetInteger();
476                         break;
478                 case LT_FILL_BOTTOM:    // fill bottom flag
479                         if (lexrc.next())
480                                 fill_bottom = lexrc.GetInteger();
481                         break;
483                 case LT_NEWLINE:        // newlines allowed?
484                         if (lexrc.next())
485                                 newline_allowed = lexrc.GetInteger();
486                         break;
488                 case LT_ALIGN:          // paragraph align
489                         switch (lexrc.lex()) {
490                         case LT_BLOCK:
491                                 align = LYX_ALIGN_BLOCK;
492                                 break;
493                         case LT_LEFT:
494                                 align = LYX_ALIGN_LEFT;
495                                 break;
496                         case LT_RIGHT:
497                                 align = LYX_ALIGN_RIGHT;
498                                 break;
499                         case LT_CENTER:
500                                 align = LYX_ALIGN_CENTER;
501                                 break;
502                         case LT_LAYOUT:
503                                 align = LYX_ALIGN_LAYOUT;
504                                 break;
505                         default:
506                                 lexrc.printError("Unknown alignment `$$Token'");
507                         }
508                         break;
510                 case LT_ALIGNPOSSIBLE:  // paragraph allowed align
511                 {       alignpossible = LYX_ALIGN_NONE;
512                       
513                 int lineno = lexrc.GetLineNo();
514                 do {
515                         switch (lexrc.lex()) {
516                         case LT_BLOCK:
517                                 alignpossible |= LYX_ALIGN_BLOCK;
518                                 break;
519                         case LT_LEFT:
520                                 alignpossible |= LYX_ALIGN_LEFT;
521                                 break;
522                         case LT_RIGHT:
523                                 alignpossible |= LYX_ALIGN_RIGHT;
524                                 break;
525                         case LT_CENTER:
526                                 alignpossible |= LYX_ALIGN_CENTER;
527                                 break;
528                         case LT_LAYOUT:
529                                 alignpossible |= LYX_ALIGN_LAYOUT;
530                                 break;
531                         default:
532                                 lexrc.printError("Unknown alignment `$$Token'");
534                         }
535                 } while (lineno == lexrc.GetLineNo());
536                 break;
537                 }
539                 case LT_LABELSTRING:    // label string definition
540                         if (lexrc.next())
541                                 labelstring_ = lexrc.GetString();
542                         break;
544                 case LT_LABELSTRING_APPENDIX: // label string appendix definition
545                         if (lexrc.next())
546                                 labelstring_appendix_ = lexrc.GetString();
547                         break;
549                 case LT_FREE_SPACING:   // Allow for free spacing.
550                         if (lexrc.next())
551                                 free_spacing = lexrc.GetInteger();
552                         break;
554                 case LT_SPACING: // setspace.sty
555                         switch(lexrc.lex()) {
556                         case LT_SPACING_SINGLE:
557                                 spacing.set(Spacing::Single);
558                                 break;
559                         case LT_SPACING_ONEHALF:
560                                 spacing.set(Spacing::Onehalf);
561                                 break;
562                         case LT_SPACING_DOUBLE:
563                                 spacing.set(Spacing::Double);
564                                 break;
565                         case LT_OTHER:
566                                 lexrc.next();
567                                 spacing.set(Spacing::Other, lexrc.GetFloat());
568                                 break;
569                         default:
570                                 lexrc.printError("Unknown spacing `$$Token'");
571                         }
572                         break;
573                 default:                /* context error */
574                         lexrc.printError("Tag `$$Token' is not "
575                                          "allowed in layout");
576                         error = true;
577                         break;
578                 }
579         }
581         return error;
585 /* ******************************************************************* */
587 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
588                            string const & desc)
589         : name_(fn), latexname_(cln), description_(desc)
591         outputType_ = LATEX;
592         columns_ = 1;
593         sides_ = OneSide;
594         secnumdepth_ = 3;
595         tocdepth_ = 3;
596         pagestyle_ = "default";
597         maxcounter_ = LABEL_COUNTER_CHAPTER;
598         defaultfont_ = LyXFont(LyXFont::ALL_SANE);
599         opt_fontsize_ = "10|11|12";
600         opt_pagestyle_ = "empty|plain|headings|fancy";
601         provides_ = nothing;
602         loaded = false;
606 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
608         lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
609         if (!lay.Read(lexrc, *this)) {
610                 // Reslove fonts
611                 lay.resfont = lay.font;
612                 lay.resfont.realize(defaultfont());
613                 lay.reslabelfont = lay.labelfont;
614                 lay.reslabelfont.realize(defaultfont());
615                 return false; // no errors
616         } 
617         lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
618         return true;
622 // Reads a textclass structure from file.
623 bool LyXTextClass::Read(string const & filename, bool merge)
625         if (!merge)
626                 lyxerr[Debug::TCLASS] << "Reading textclass "
627                                       << MakeDisplayPath(filename)
628                                       << endl;
629         else
630                 lyxerr[Debug::TCLASS] << "Reading input file "
631                                      << MakeDisplayPath(filename)
632                                      << endl;
633         
634         LyXLex lexrc(layoutTags, sizeof(layoutTags)/sizeof(keyword_item));
635         bool error = false;
637         lexrc.setFile(filename);
638         if (!lexrc.IsOK()) error = true; 
640         // parsing
641         while (lexrc.IsOK() && !error) {
642                 switch(lexrc.lex()) {
643                 case -2:
644                         break;
646                 case -1:                                 
647                         lexrc.printError("Unknown tag `$$Token'");
648                         error = true;
649                         break;
651                 case LT_OUTPUTTYPE:   // output type definition
652                         switch(lexrc.lex()) {
653                         case LT_OTLATEX:
654                                 outputType_ = LATEX;
655                                 break;
656                         case LT_OTLINUXDOC:
657                                 outputType_ = LINUXDOC;
658                                 break;
659                         case LT_OTDOCBOOK:
660                                 outputType_ = DOCBOOK;
661                                 break;
662                         case LT_OTLITERATE:
663                                 outputType_ = LITERATE;
664                                 break;
665                         default:
666                                 lexrc.printError("Unknown output type `$$Token'");
667                                 break;
668                         }
669                         break;
670                         
671                 case LT_INPUT: // Include file
672                         if (lexrc.next()) {
673                                 string tmp = LibFileSearch("layouts",
674                                                             lexrc.GetString(), 
675                                                             "layout");
676                                 
677                                 if (Read(tmp, true)) {
678                                         lexrc.printError("Error reading input"
679                                                          "file: "+tmp);
680                                         error = true;
681                                 }
682                         }
683                         break;
685                 case LT_STYLE:
686                         if (lexrc.next()) {
687                                 string name = subst(lexrc.GetString(),
688                                                     '_', ' ');
689                                 if (hasLayout(name)) {
690                                         LyXLayout & lay = GetLayout(name);
691                                         error = do_readStyle(lexrc, lay);
692                                 } else {
693                                         LyXLayout lay;
694                                         lay.name(name);
695                                         if (!(error =do_readStyle(lexrc, lay)))
696                                                 layoutlist.push_back(lay);
697                                 }
698                         }
699                         else {
700                                 lexrc.printError("No name given for style: `$$Token'.");
701                                 error = true;
702                         }
703                         break;
705                 case LT_NOSTYLE:
706                         if (lexrc.next()) {
707                                 string style = subst(lexrc.GetString(),
708                                                      '_', ' ');
709                                 if (!delete_layout(style))
710                                         lexrc.printError("Cannot delete style"
711                                                          " `$$Token'");
712                         }
713                         break;
715                 case LT_COLUMNS:
716                         if (lexrc.next())
717                                 columns_ = lexrc.GetInteger();
718                         break;
719                         
720                 case LT_SIDES:
721                         if (lexrc.next()) {
722                                 switch(lexrc.GetInteger()) {
723                                 case 1: sides_ = OneSide; break;
724                                 case 2: sides_ = TwoSides; break;
725                                 default:
726                                         lyxerr << "Impossible number of page"
727                                                 " sides, setting to one."
728                                                << endl;
729                                         sides_ = OneSide;
730                                         break;
731                                 }
732                         }
733                         break;
734                         
735                 case LT_PAGESTYLE:
736                         lexrc.next();
737                         pagestyle_ = strip(lexrc.GetString());
738                         break;
739                         
740                 case LT_DEFAULTFONT:
741                         defaultfont_.lyxRead(lexrc);
742                         if (!defaultfont_.resolved()) {
743                                 lexrc.printError("Warning: defaultfont should "
744                                                  "be fully instantiated!");
745                                 defaultfont_.realize(LyXFont::ALL_SANE);
746                         }
747                         break;
749                 case LT_MAXCOUNTER:
750                         switch (lexrc.lex()) {
751                         case LT_COUNTER_CHAPTER:
752                                 maxcounter_ = LABEL_COUNTER_CHAPTER;
753                                 break;
754                         case LT_COUNTER_SECTION:
755                                 maxcounter_ = LABEL_COUNTER_SECTION;
756                                 break;
757                         case LT_COUNTER_SUBSECTION:
758                                 maxcounter_ = LABEL_COUNTER_SUBSECTION;
759                                 break;
760                         case LT_COUNTER_SUBSUBSECTION:
761                                 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
762                                 break;
763                         case LT_COUNTER_PARAGRAPH:
764                                 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
765                                 break;
766                         case LT_COUNTER_SUBPARAGRAPH:
767                                 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
768                                 break;
769                         case LT_COUNTER_ENUMI:
770                                 maxcounter_ = LABEL_COUNTER_ENUMI;
771                                 break;
772                         case LT_COUNTER_ENUMII:
773                                 maxcounter_ = LABEL_COUNTER_ENUMII;
774                                 break;
775                         case LT_COUNTER_ENUMIII:
776                                 maxcounter_ = LABEL_COUNTER_ENUMIII;
777                                 break;
778                         case LT_COUNTER_ENUMIV:
779                                 maxcounter_ = LABEL_COUNTER_ENUMIV;
780                                 break;
781                         }
782                         break;
784                 case LT_SECNUMDEPTH:
785                         lexrc.next();
786                         secnumdepth_ = lexrc.GetInteger();
787                         break;
789                 case LT_TOCDEPTH:
790                         lexrc.next();
791                         tocdepth_ = lexrc.GetInteger();
792                         break;
794                         // First step to support options 
795                 case LT_CLASSOPTIONS:
796                 {
797                         bool getout = true;
798                         while (getout && lexrc.IsOK()) { 
799                                 switch (lexrc.lex()) {
800                                 case LT_FONTSIZE:
801                                         lexrc.next();
802                                         opt_fontsize_ = strip(lexrc.GetString());
803                                         break;
804                                 case LT_PAGESTYLE:
805                                         lexrc.next();
806                                         opt_pagestyle_ = strip(lexrc.GetString()); 
807                                         break;
808                                 case LT_OTHER:
809                                         lexrc.next();
810                                         options_ = lexrc.GetString();
811                                         break;
812                                 case LT_END: getout = false; break;
813                                 default:
814                                         lexrc.printError("Out of context tag `$$Token'");
815                                         break;
816                                 }
817                         }
818                         break;
819                 }
821                 case LT_PREAMBLE:
822                         preamble_ = lexrc.getLongString("EndPreamble");
823                         break;
825                 case LT_PROVIDESAMSMATH:
826                         if (lexrc.next() && lexrc.GetInteger())
827                                 provides_ |= amsmath;
828                         break;
830                 case LT_PROVIDESMAKEIDX:
831                         if (lexrc.next() && lexrc.GetInteger())
832                                 provides_ |= makeidx;
833                         break;
835                 case LT_PROVIDESURL:
836                         if (lexrc.next() && lexrc.GetInteger())
837                                 provides_ = url;
838                         break;
840                 case LT_LEFTMARGIN:     // left margin type
841                         if (lexrc.next())
842                                 leftmargin_ = lexrc.GetString();
843                         break;                  
845                 case LT_RIGHTMARGIN:    // right margin type
846                         if (lexrc.next())
847                                 rightmargin_ = lexrc.GetString();
848                         break;
850                 default:
851                         lexrc.printError("Out of context tag `$$Token'");
852                         break;
853                 }
854         }       
856         if (!merge) { // we are at top level here.
857                 lyxerr[Debug::TCLASS] << "Finished reading textclass " 
858                                       << MakeDisplayPath(filename)
859                                       << endl;
860         } else
861                 lyxerr[Debug::TCLASS] << "Finished reading input file " 
862                                       << MakeDisplayPath(filename)
863                                       << endl;
865         return error;
869 bool LyXTextClass::hasLayout(string const & name) const
871         for (LayoutList::const_iterator cit = layoutlist.begin();
872              cit != layoutlist.end(); ++cit) {
873                 if ((*cit).name() == name)
874                         return true;
875         }
876         return false;
880 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
882         for (LayoutList::const_iterator cit = layoutlist.begin();
883              cit != layoutlist.end(); ++cit) {
884                 if ((*cit).name() == name)
885                         return (*cit);
886         }
887         Assert(false); // we actually require the name to exist.
888         return layoutlist.front();
892 LyXLayout & LyXTextClass::GetLayout(string const & name)
894         for (LayoutList::iterator it = layoutlist.begin();
895              it != layoutlist.end(); ++it) {
896                 if ((*it).name() == name)
897                         return (*it);
898         }
899         Assert(false); // we actually require the name to exist.
900         return layoutlist.front();
904 bool LyXTextClass::delete_layout (string const & name)
906         for(LayoutList::iterator it = layoutlist.begin();
907             it != layoutlist.end(); ++it) {
908                 if ((*it).name() == name) {
909                         layoutlist.erase(it);
910                         return true;
911                 }
912         }
913         return false;
917 // Load textclass info if not loaded yet
918 void LyXTextClass::load()
920         if (loaded) return;
922         // Read style-file
923         string real_file = LibFileSearch("layouts", name_, "layout");
925         if (Read(real_file)) {
926                 lyxerr << "Error reading `"
927                        << MakeDisplayPath(real_file)
928                        << "'\n(Check `" << name_
929                        << "')\nCheck your installation and "
930                         "try Options/Reconfigure..." << endl;
931         }
932         loaded = true;
936 //////////////////////////////////////////
938 // Gets textclass number from name
939 pair<bool, LyXTextClassList::ClassList::size_type>
940 LyXTextClassList::NumberOfClass(string const & textclass) const
942         for (ClassList::const_iterator cit = classlist.begin();
943              cit != classlist.end(); ++cit) {
944                 if ((*cit).name() == textclass)
945                         return make_pair(true, cit - classlist.begin());
946         }
947         return make_pair(false, 0);
951 // Gets layout structure from style number and textclass number
952 LyXLayout const &
953 LyXTextClassList::Style(LyXTextClassList::ClassList::size_type textclass,
954                         LyXTextClass::LayoutList::size_type layout) const
956         classlist[textclass].load();
957         if (layout < classlist[textclass].numLayouts())
958                 return classlist[textclass][layout];
959         return classlist[textclass][0];
963 // Gets layout number from name and textclass number
964 pair<bool, LyXTextClass::LayoutList::size_type>
965 LyXTextClassList::NumberOfLayout(LyXTextClassList::ClassList::size_type textclass, string const & name) const
967         classlist[textclass].load();
968         for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
969                 if (classlist[textclass][i].name() == name)
970                         return make_pair(true, i);
971         }
972         if (name == "dummy")
973                 return make_pair(true, LYX_DUMMY_LAYOUT);
974         return make_pair(false, 0); // not found
978 // Gets a layout (style) name from layout number and textclass number
979 string const &
980 LyXTextClassList::NameOfLayout(LyXTextClassList::ClassList::size_type textclass,
981                                LyXTextClass::LayoutList::size_type layout) const
983         static string dummy("dummy");
984         static string end("@@end@@");
985         classlist[textclass].load();
986         if (layout < classlist[textclass].numLayouts())
987                 return classlist[textclass][layout].name();
988         else if (layout == LYX_DUMMY_LAYOUT)
989                 return dummy;
990         else
991                 return end;
995 // Gets a textclass name from number
996 string const &
997 LyXTextClassList::NameOfClass(LyXTextClassList::ClassList::size_type number) const
999         static string dummy("dummy");
1000         static string end("@@end@@");
1001         if (classlist.size() == 0) {
1002                 if (number == 0) return dummy;
1003                 else return end;
1004         }
1005         if (number < classlist.size())
1006                 return classlist[number].name();
1007         else
1008                 return end;
1012 // Gets a textclass latexname from number
1013 string const &
1014 LyXTextClassList::LatexnameOfClass(LyXTextClassList::ClassList::size_type number) const
1016         static string dummy("dummy");
1017         static string end("@@end@@");
1018         classlist[number].load();
1019         if (classlist.size() == 0) {
1020                 if (number == 0) return dummy;
1021                 else return end;
1022         }
1023         if (number < classlist.size())
1024                 return classlist[number].latexname();
1025         else
1026                 return end;
1030 // Gets a textclass description from number
1031 string const &
1032 LyXTextClassList::DescOfClass(LyXTextClassList::ClassList::size_type number) const
1034         static string dummy("dummy");
1035         static string end("@@end@@");
1036         if (classlist.size() == 0) {
1037                 if (number == 0) return dummy;
1038                 else return end;
1039         }
1040         if (number < classlist.size())
1041                 return classlist[number].description();
1042         else
1043                 return end;
1047 // Gets a textclass structure from number
1048 LyXTextClass const &
1049 LyXTextClassList::TextClass(LyXTextClassList::ClassList::size_type textclass) const
1051         classlist[textclass].load();
1052         if (textclass < classlist.size())
1053                 return classlist[textclass];
1054         else
1055                 return classlist[0];
1059 void LyXTextClassList::Add(LyXTextClass const & t)
1061         classlist.push_back(t);
1065 // used when sorting the textclass list.
1066 class less_textclass_desc {
1067 public:
1068         int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1069                 return tc1.description() < tc2.description();
1070         }
1074 // Reads LyX textclass definitions according to textclass config file
1075 bool LyXTextClassList::Read ()
1077         LyXLex lex(0, 0);
1078         string real_file = LibFileSearch("", "textclass.lst");
1079         lyxerr[Debug::TCLASS] << "Reading textclasses from "
1080                               << real_file << endl;
1082         if (real_file.empty()) {
1083                 lyxerr << "LyXTextClassList::Read: unable to find "
1084                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1085                        << "'. Exiting." << endl;
1087                 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1088                            _("Check that the file \"textclass.lst\""),
1089                            _("is installed correctly. Sorry, has to exit :-("));
1090                 return false;
1091                 // This causes LyX to end... Not a desirable behaviour. Lgb
1092                 // What do you propose? That the user gets a file dialog
1093                 // and is allowed to hunt for the file? (Asger)
1094         }
1096         lex.setFile(real_file);
1097         
1098         if (!lex.IsOK()) {
1099                 lyxerr << "LyXTextClassList::Read: unable to open "
1100                         "textclass file  `" << MakeDisplayPath(real_file, 1000)
1101                        << "\'\nCheck your installation. LyX can't continue."
1102                        << endl;
1103                 return false;
1104         }
1105         bool finished = false;
1106         string fname, clname, desc;
1107         // Parse config-file
1108         while (lex.IsOK() && !finished) {
1109                 switch (lex.lex()) {
1110                 case LyXLex::LEX_FEOF:
1111                         finished = true;
1112                         break;
1113                 default:
1114                         fname = lex.GetString();
1115                         lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1116                         if (lex.next()) {
1117                                 clname = lex.GetString();
1118                                 lyxerr[Debug::TCLASS]
1119                                         << "Clname: " << clname << endl;
1120                                 if (lex.next()) {
1121                                               desc = lex.GetString();
1122                                               lyxerr[Debug::TCLASS]
1123                                                       << "Desc: " << desc << endl;
1124                                               // This code is run when we have
1125                                               // fname, clname and desc
1126                                               LyXTextClass tmpl(fname,
1127                                                                 clname,
1128                                                                 desc);
1129                                               if (lyxerr.
1130                                                   debugging(Debug::TCLASS)) {
1131                                                       tmpl.load();
1132                                               }
1133                                               Add (tmpl);
1134                                 }
1135                         }
1136                 }
1137         }
1138         
1139         if (classlist.size() == 0) {
1140                 lyxerr << "LyXTextClassList::Read: no textclass found!"
1141                        << endl;
1142                 WriteAlert(_("LyX wasn't able to find any layout description!"),
1143                            _("Check the contents of  the file \"textclass.lst\""),
1144                            _("Sorry, has to exit :-("));
1145                 return false;
1146         }
1147         // Ok everything loaded ok, now sort the list.
1148         sort(classlist.begin(), classlist.end(), less_textclass_desc());
1149         return true;
1152         
1153 /* Load textclass
1154    Returns false if this fails
1156 bool
1157 LyXTextClassList::Load (LyXTextClassList::ClassList::size_type number) const
1159         bool result = true;
1160         if (number < classlist.size()) {
1161                 classlist[number].load();
1162                 if (classlist[number].numLayouts() == 0) {
1163                         result = false;
1164                 }
1165         } else {
1166                 result = false;
1167         }
1168         return result;