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