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