]> git.lyx.org Git - lyx.git/blob - src/lyxtextclass.C
more code in the menu backend == less code in the menu frontends; add support for...
[lyx.git] / src / lyxtextclass.C
1 /* This file is part of
2  * ======================================================
3  *
4  *           LyX, The Document Processor
5  *
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-2001 The LyX Team.
8  *
9  * ======================================================
10  */
11
12 #include <config.h>
13
14 #include "lyxtextclass.h"
15 #include "debug.h"
16 #include "lyxlex.h"
17 #include "counters.h"
18 #include "FloatList.h"
19
20 #include "support/lstrings.h"
21 #include "support/LAssert.h"
22 #include "support/lyxfunctional.h"
23 #include "support/filetools.h"
24
25 #include <algorithm>
26
27 using std::endl;
28 using std::find_if;
29 using std::remove_if;
30 using std::ostream;
31
32 namespace { // anon
33
34 struct compare_name {
35         compare_name(string const & name)
36                 : name_(name) {}
37         template <class C>
38         bool operator()(C & c) {
39                 return c->name() == name_;
40         }
41         string name_;
42 };
43
44 } // anon
45
46
47 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
48                            string const & desc)
49         : name_(fn), latexname_(cln), description_(desc),
50           floatlist_(new FloatList), ctrs_(new Counters)
51 {
52         outputType_ = LATEX;
53         columns_ = 1;
54         sides_ = OneSide;
55         secnumdepth_ = 3;
56         tocdepth_ = 3;
57         pagestyle_ = "default";
58         maxcounter_ = LABEL_COUNTER_CHAPTER;
59         defaultfont_ = LyXFont(LyXFont::ALL_SANE);
60         opt_fontsize_ = "10|11|12";
61         opt_pagestyle_ = "empty|plain|headings|fancy";
62         provides_ = nothing;
63         titletype_ = TITLE_COMMAND_AFTER;
64         titlename_ = "maketitle";
65         loaded = false;
66 }
67
68
69 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
70 {
71         lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
72         if (!lay.Read(lexrc, *this)) {
73                 // Resolve fonts
74                 lay.resfont = lay.font;
75                 lay.resfont.realize(defaultfont());
76                 lay.reslabelfont = lay.labelfont;
77                 lay.reslabelfont.realize(defaultfont());
78                 return false; // no errors
79         }
80         lyxerr << "Error parsing style `" << lay.name() << '\'' << endl;
81         return true;
82 }
83
84
85 enum TextClassTags {
86         TC_OUTPUTTYPE = 1,
87         TC_INPUT,
88         TC_STYLE,
89         TC_DEFAULTSTYLE,
90         TC_NOSTYLE,
91         TC_COLUMNS,
92         TC_SIDES,
93         TC_PAGESTYLE,
94         TC_DEFAULTFONT,
95         TC_MAXCOUNTER,
96         TC_SECNUMDEPTH,
97         TC_TOCDEPTH,
98         TC_CLASSOPTIONS,
99         TC_PREAMBLE,
100         TC_PROVIDESAMSMATH,
101         TC_PROVIDESNATBIB,
102         TC_PROVIDESMAKEIDX,
103         TC_PROVIDESURL,
104         TC_LEFTMARGIN,
105         TC_RIGHTMARGIN,
106         TC_FLOAT,
107         TC_COUNTER,
108         TC_NOFLOAT,
109         TC_TITLELATEXNAME,
110         TC_TITLELATEXTYPE
111 };
112
113 // Reads a textclass structure from file.
114 bool LyXTextClass::Read(string const & filename, bool merge)
115 {
116         keyword_item textClassTags[] = {
117                 { "classoptions",    TC_CLASSOPTIONS },
118                 { "columns",         TC_COLUMNS },
119                 { "counter",         TC_COUNTER },
120                 { "defaultfont",     TC_DEFAULTFONT },
121                 { "defaultstyle",    TC_DEFAULTSTYLE },
122                 { "float",           TC_FLOAT },
123                 { "input",           TC_INPUT },
124                 { "leftmargin",      TC_LEFTMARGIN },
125                 { "maxcounter",      TC_MAXCOUNTER },
126                 { "nofloat",         TC_NOFLOAT },
127                 { "nostyle",         TC_NOSTYLE },
128                 { "outputtype",      TC_OUTPUTTYPE },
129                 { "pagestyle",       TC_PAGESTYLE },
130                 { "preamble",        TC_PREAMBLE },
131                 { "providesamsmath", TC_PROVIDESAMSMATH },
132                 { "providesmakeidx", TC_PROVIDESMAKEIDX },
133                 { "providesnatbib",  TC_PROVIDESNATBIB },
134                 { "providesurl",     TC_PROVIDESURL },
135                 { "rightmargin",     TC_RIGHTMARGIN },
136                 { "secnumdepth",     TC_SECNUMDEPTH },
137                 { "sides",           TC_SIDES },
138                 { "style",           TC_STYLE },
139                 { "titlelatexname",  TC_TITLELATEXNAME },
140                 { "titlelatextype",  TC_TITLELATEXTYPE },
141                 { "tocdepth",        TC_TOCDEPTH }
142         };
143
144         if (!merge)
145                 lyxerr[Debug::TCLASS] << "Reading textclass "
146                                       << MakeDisplayPath(filename)
147                                       << endl;
148         else
149                 lyxerr[Debug::TCLASS] << "Reading input file "
150                                      << MakeDisplayPath(filename)
151                                      << endl;
152
153         LyXLex lexrc(textClassTags, TC_TITLELATEXTYPE);
154         bool error = false;
155
156         lexrc.setFile(filename);
157         if (!lexrc.isOK()) error = true;
158
159         // parsing
160         while (lexrc.isOK() && !error) {
161                 int le = lexrc.lex();
162                 switch (le) {
163                 case LyXLex::LEX_FEOF:
164                         continue;
165
166                 case LyXLex::LEX_UNDEF:
167                         lexrc.printError("Unknown TextClass tag `$$Token'");
168                         error = true;
169                         continue;
170                 default: break;
171                 }
172                 switch (static_cast<TextClassTags>(le)) {
173                 case TC_OUTPUTTYPE:   // output type definition
174                         readOutputType(lexrc);
175                         break;
176
177                 case TC_INPUT: // Include file
178                         if (lexrc.next()) {
179                                 string tmp = LibFileSearch("layouts",
180                                                             lexrc.getString(),
181                                                             "layout");
182
183                                 if (Read(tmp, true)) {
184                                         lexrc.printError("Error reading input"
185                                                          "file: "+tmp);
186                                         error = true;
187                                 }
188                         }
189                         break;
190
191                 case TC_DEFAULTSTYLE:
192                         if (lexrc.next()) {
193                                 string const name = subst(lexrc.getString(),
194                                                           '_', ' ');
195                                 defaultlayout_ = name;
196                         }
197                         break;
198
199                 case TC_STYLE:
200                         if (lexrc.next()) {
201                                 string const name = subst(lexrc.getString(),
202                                                     '_', ' ');
203                                 if (hasLayout(name)) {
204                                         LyXLayout * lay =
205                                                 operator[](name).get();
206                                         error = do_readStyle(lexrc, *lay);
207                                 } else {
208                                         LyXLayout lay;
209                                         lay.setName(name);
210                                         if (!(error = do_readStyle(lexrc, lay)))
211                                                 layoutlist_.push_back(boost::shared_ptr<LyXLayout>(new LyXLayout(lay)));
212                                         if (defaultlayout_.empty()) {
213                                                 // We do not have a default
214                                                 // layout yet, so we choose
215                                                 // the first layout we
216                                                 // encounter.
217                                                 defaultlayout_ = name;
218                                         }
219                                 }
220                         }
221                         else {
222                                 lexrc.printError("No name given for style: `$$Token'.");
223                                 error = true;
224                         }
225                         break;
226
227                 case TC_NOSTYLE:
228                         if (lexrc.next()) {
229                                 string const style = subst(lexrc.getString(),
230                                                      '_', ' ');
231                                 if (!delete_layout(style))
232                                         lyxerr << "Cannot delete style `"
233                                                << style << '\'' << endl;
234 //                                      lexrc.printError("Cannot delete style"
235 //                                                       " `$$Token'");
236                         }
237                         break;
238
239                 case TC_COLUMNS:
240                         if (lexrc.next())
241                                 columns_ = lexrc.getInteger();
242                         break;
243
244                 case TC_SIDES:
245                         if (lexrc.next()) {
246                                 switch (lexrc.getInteger()) {
247                                 case 1: sides_ = OneSide; break;
248                                 case 2: sides_ = TwoSides; break;
249                                 default:
250                                         lyxerr << "Impossible number of page"
251                                                 " sides, setting to one."
252                                                << endl;
253                                         sides_ = OneSide;
254                                         break;
255                                 }
256                         }
257                         break;
258
259                 case TC_PAGESTYLE:
260                         lexrc.next();
261                         pagestyle_ = rtrim(lexrc.getString());
262                         break;
263
264                 case TC_DEFAULTFONT:
265                         defaultfont_.lyxRead(lexrc);
266                         if (!defaultfont_.resolved()) {
267                                 lexrc.printError("Warning: defaultfont should "
268                                                  "be fully instantiated!");
269                                 defaultfont_.realize(LyXFont(LyXFont::ALL_SANE));
270                         }
271                         break;
272
273                 case TC_MAXCOUNTER:
274                         readMaxCounter(lexrc);
275                         break;
276
277                 case TC_SECNUMDEPTH:
278                         lexrc.next();
279                         secnumdepth_ = lexrc.getInteger();
280                         break;
281
282                 case TC_TOCDEPTH:
283                         lexrc.next();
284                         tocdepth_ = lexrc.getInteger();
285                         break;
286
287                         // First step to support options
288                 case TC_CLASSOPTIONS:
289                         readClassOptions(lexrc);
290                         break;
291
292                 case TC_PREAMBLE:
293                         preamble_ = lexrc.getLongString("EndPreamble");
294                         break;
295
296                 case TC_PROVIDESAMSMATH:
297                         if (lexrc.next() && lexrc.getInteger())
298                                 provides_ |= amsmath;
299                         break;
300
301                 case TC_PROVIDESNATBIB:
302                         if (lexrc.next() && lexrc.getInteger())
303                                 provides_ |= natbib;
304                         break;
305
306                 case TC_PROVIDESMAKEIDX:
307                         if (lexrc.next() && lexrc.getInteger())
308                                 provides_ |= makeidx;
309                         break;
310
311                 case TC_PROVIDESURL:
312                         if (lexrc.next() && lexrc.getInteger())
313                                 provides_ |= url;
314                         break;
315
316                 case TC_LEFTMARGIN:     // left margin type
317                         if (lexrc.next())
318                                 leftmargin_ = lexrc.getString();
319                         break;
320
321                 case TC_RIGHTMARGIN:    // right margin type
322                         if (lexrc.next())
323                                 rightmargin_ = lexrc.getString();
324                         break;
325                 case TC_FLOAT:
326                         readFloat(lexrc);
327                         break;
328                 case TC_COUNTER:
329                         readCounter(lexrc);
330                         break;
331                 case TC_TITLELATEXTYPE:
332                         readTitleType(lexrc);
333                         break;
334                 case TC_TITLELATEXNAME:
335                         if (lexrc.next())
336                                 titlename_ = lexrc.getString();
337                         break;
338                 case TC_NOFLOAT:
339                         if (lexrc.next()) {
340                                 string const nofloat = lexrc.getString();
341                                 floatlist_->erase(nofloat);
342                         }
343                         break;
344                 }
345         }
346
347         if (!merge) { // we are at top level here.
348                 lyxerr[Debug::TCLASS] << "Finished reading textclass "
349                                       << MakeDisplayPath(filename)
350                                       << endl;
351                 if (defaultlayout_.empty()) {
352                         lyxerr << "Error: Textclass '" << name_
353                                << "' is missing a defaultstyle." << endl;
354                         error = true;
355                 }
356         } else
357                 lyxerr[Debug::TCLASS] << "Finished reading input file "
358                                       << MakeDisplayPath(filename)
359                                       << endl;
360
361         return error;
362 }
363
364
365 void LyXTextClass::readTitleType(LyXLex & lexrc)
366 {
367         keyword_item titleTypeTags[] = {
368                 { "commandafter", TITLE_COMMAND_AFTER },
369                 { "environment", TITLE_ENVIRONMENT }
370         };
371
372         pushpophelper pph(lexrc, titleTypeTags, TITLE_ENVIRONMENT);
373
374         int le = lexrc.lex();
375         switch (le) {
376         case LyXLex::LEX_UNDEF:
377                 lexrc.printError("Unknown output type `$$Token'");
378                 return;
379         case TITLE_COMMAND_AFTER:
380         case TITLE_ENVIRONMENT:
381                 titletype_ = static_cast<LYX_TITLE_LATEX_TYPES>(le);
382                 break;
383         default:
384                 lyxerr << "Unhandled value " << le
385                        << " in LyXTextClass::readTitleType." << endl;
386
387                 break;
388         }
389 }
390
391
392 void LyXTextClass::readOutputType(LyXLex & lexrc)
393 {
394         keyword_item outputTypeTags[] = {
395                 { "docbook", DOCBOOK },
396                 { "latex", LATEX },
397                 { "linuxdoc", LINUXDOC },
398                 { "literate", LITERATE }
399         };
400
401         pushpophelper pph(lexrc, outputTypeTags, LITERATE);
402
403         int le = lexrc.lex();
404         switch (le) {
405         case LyXLex::LEX_UNDEF:
406                 lexrc.printError("Unknown output type `$$Token'");
407                 return;
408         case LATEX:
409         case LINUXDOC:
410         case DOCBOOK:
411         case LITERATE:
412                 outputType_ = static_cast<OutputType>(le);
413                 break;
414         default:
415                 lyxerr << "Unhandled value " << le
416                        << " in LyXTextClass::readOutputType." << endl;
417
418                 break;
419         }
420 }
421
422
423 enum MaxCounterTags {
424         MC_COUNTER_CHAPTER = 1,
425         MC_COUNTER_SECTION,
426         MC_COUNTER_SUBSECTION,
427         MC_COUNTER_SUBSUBSECTION,
428         MC_COUNTER_PARAGRAPH,
429         MC_COUNTER_SUBPARAGRAPH,
430         MC_COUNTER_ENUMI,
431         MC_COUNTER_ENUMII,
432         MC_COUNTER_ENUMIII,
433         MC_COUNTER_ENUMIV
434 };
435
436
437 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
438 {
439         keyword_item maxCounterTags[] = {
440                 {"counter_chapter", MC_COUNTER_CHAPTER },
441                 {"counter_enumi", MC_COUNTER_ENUMI },
442                 {"counter_enumii", MC_COUNTER_ENUMII },
443                 {"counter_enumiii", MC_COUNTER_ENUMIII },
444                 {"counter_enumiv", MC_COUNTER_ENUMIV },
445                 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
446                 {"counter_section", MC_COUNTER_SECTION },
447                 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
448                 {"counter_subsection", MC_COUNTER_SUBSECTION },
449                 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
450         };
451
452         pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
453         int le = lexrc.lex();
454         switch (le) {
455         case LyXLex::LEX_UNDEF:
456                 lexrc.printError("Unknown MaxCounter tag `$$Token'");
457                 return;
458         default: break;
459         }
460         switch (static_cast<MaxCounterTags>(le)) {
461         case MC_COUNTER_CHAPTER:
462                 maxcounter_ = LABEL_COUNTER_CHAPTER;
463                 break;
464         case MC_COUNTER_SECTION:
465                 maxcounter_ = LABEL_COUNTER_SECTION;
466                 break;
467         case MC_COUNTER_SUBSECTION:
468                 maxcounter_ = LABEL_COUNTER_SUBSECTION;
469                 break;
470         case MC_COUNTER_SUBSUBSECTION:
471                 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
472                 break;
473         case MC_COUNTER_PARAGRAPH:
474                 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
475                 break;
476         case MC_COUNTER_SUBPARAGRAPH:
477                 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
478                 break;
479         case MC_COUNTER_ENUMI:
480                 maxcounter_ = LABEL_COUNTER_ENUMI;
481                 break;
482         case MC_COUNTER_ENUMII:
483                 maxcounter_ = LABEL_COUNTER_ENUMII;
484                 break;
485         case MC_COUNTER_ENUMIII:
486                 maxcounter_ = LABEL_COUNTER_ENUMIII;
487                 break;
488         case MC_COUNTER_ENUMIV:
489                 maxcounter_ = LABEL_COUNTER_ENUMIV;
490                 break;
491         }
492 }
493
494
495 enum ClassOptionsTags {
496         CO_FONTSIZE = 1,
497         CO_PAGESTYLE,
498         CO_OTHER,
499         CO_END
500 };
501
502
503 void LyXTextClass::readClassOptions(LyXLex & lexrc)
504 {
505         keyword_item classOptionsTags[] = {
506                 {"end", CO_END },
507                 {"fontsize", CO_FONTSIZE },
508                 {"other", CO_OTHER },
509                 {"pagestyle", CO_PAGESTYLE }
510         };
511
512         lexrc.pushTable(classOptionsTags, CO_END);
513         bool getout = false;
514         while (!getout && lexrc.isOK()) {
515                 int le = lexrc.lex();
516                 switch (le) {
517                 case LyXLex::LEX_UNDEF:
518                         lexrc.printError("Unknown ClassOption tag `$$Token'");
519                         continue;
520                 default: break;
521                 }
522                 switch (static_cast<ClassOptionsTags>(le)) {
523                 case CO_FONTSIZE:
524                         lexrc.next();
525                         opt_fontsize_ = rtrim(lexrc.getString());
526                         break;
527                 case CO_PAGESTYLE:
528                         lexrc.next();
529                         opt_pagestyle_ = rtrim(lexrc.getString());
530                         break;
531                 case CO_OTHER:
532                         lexrc.next();
533                         options_ = lexrc.getString();
534                         break;
535                 case CO_END:
536                         getout = true;
537                         break;
538                 }
539         }
540         lexrc.popTable();
541 }
542
543
544 enum FloatTags {
545         FT_TYPE = 1,
546         FT_NAME,
547         FT_PLACEMENT,
548         FT_EXT,
549         FT_WITHIN,
550         FT_STYLE,
551         FT_LISTNAME,
552         FT_BUILTIN,
553         FT_END
554 };
555
556 void LyXTextClass::readFloat(LyXLex & lexrc)
557 {
558         keyword_item floatTags[] = {
559                 { "end", FT_END },
560                 { "extension", FT_EXT },
561                 { "guiname", FT_NAME },
562                 { "latexbuiltin", FT_BUILTIN },
563                 { "listname", FT_LISTNAME },
564                 { "numberwithin", FT_WITHIN },
565                 { "placement", FT_PLACEMENT },
566                 { "style", FT_STYLE },
567                 { "type", FT_TYPE }
568         };
569
570         lexrc.pushTable(floatTags, FT_END);
571
572         string type;
573         string placement;
574         string ext;
575         string within;
576         string style;
577         string name;
578         string listname;
579         bool builtin = false;
580
581         bool getout = false;
582         while (!getout && lexrc.isOK()) {
583                 int le = lexrc.lex();
584                 switch (le) {
585                 case LyXLex::LEX_UNDEF:
586                         lexrc.printError("Unknown ClassOption tag `$$Token'");
587                         continue;
588                 default: break;
589                 }
590                 switch (static_cast<FloatTags>(le)) {
591                 case FT_TYPE:
592                         lexrc.next();
593                         type = lexrc.getString();
594                         // Here we could check if this type is already defined
595                         // and modify it with the rest of the vars instead.
596                         break;
597                 case FT_NAME:
598                         lexrc.next();
599                         name = lexrc.getString();
600                         break;
601                 case FT_PLACEMENT:
602                         lexrc.next();
603                         placement = lexrc.getString();
604                         break;
605                 case FT_EXT:
606                         lexrc.next();
607                         ext = lexrc.getString();
608                         break;
609                 case FT_WITHIN:
610                         lexrc.next();
611                         within = lexrc.getString();
612                         if (within == "none")
613                                 within.erase();
614                         break;
615                 case FT_STYLE:
616                         lexrc.next();
617                         style = lexrc.getString();
618                         break;
619                 case FT_LISTNAME:
620                         lexrc.next();
621                         listname = lexrc.getString();
622                         break;
623                 case FT_BUILTIN:
624                         lexrc.next();
625                         builtin = lexrc.getBool();
626                         break;
627                 case FT_END:
628                         getout = true;
629                         break;
630                 }
631         }
632
633         // Here if have a full float if getout == true
634         if (getout) {
635                 Floating newfloat(type, placement, ext, within,
636                                   style, name, listname, builtin);
637                 floatlist_->newFloat(newfloat);
638         }
639
640         lexrc.popTable();
641 }
642
643
644 enum CounterTags {
645         CT_NAME = 1,
646         CT_WITHIN,
647         CT_END
648 };
649
650 void LyXTextClass::readCounter(LyXLex & lexrc)
651 {
652         keyword_item counterTags[] = {
653                 { "end", CT_END },
654                 { "name", CT_NAME },
655                 { "within", CT_WITHIN }
656         };
657
658         lexrc.pushTable(counterTags, CT_END);
659
660         string name;
661         string within;
662
663         bool getout = false;
664         while (!getout && lexrc.isOK()) {
665                 int le = lexrc.lex();
666                 switch (le) {
667                 case LyXLex::LEX_UNDEF:
668                         lexrc.printError("Unknown ClassOption tag `$$Token'");
669                         continue;
670                 default: break;
671                 }
672                 switch (static_cast<CounterTags>(le)) {
673                 case CT_NAME:
674                         lexrc.next();
675                         name = lexrc.getString();
676                         break;
677                 case CT_WITHIN:
678                         lexrc.next();
679                         within = lexrc.getString();
680                         if (within == "none")
681                                 within.erase();
682                         break;
683                 case CT_END:
684                         getout = true;
685                         break;
686                 }
687         }
688
689         // Here if have a full float if getout == true
690         if (getout) {
691                 if (within.empty()) {
692                         ctrs_->newCounter(name);
693                 } else {
694                         ctrs_->newCounter(name, within);
695                 }
696         }
697
698         lexrc.popTable();
699 }
700
701
702 LyXFont const & LyXTextClass::defaultfont() const
703 {
704         return defaultfont_;
705 }
706
707
708 string const & LyXTextClass::leftmargin() const
709 {
710         return leftmargin_;
711 }
712
713
714 string const & LyXTextClass::rightmargin() const
715 {
716         return rightmargin_;
717 }
718
719
720 bool LyXTextClass::hasLayout(string const & n) const
721 {
722         string const name = (n.empty() ? defaultLayoutName() : n);
723
724         return find_if(layoutlist_.begin(), layoutlist_.end(),
725                        compare_name(name))
726                 != layoutlist_.end();
727 }
728
729
730 LyXLayout_ptr const & LyXTextClass::operator[](string const & n) const
731 {
732         lyx::Assert(!n.empty());
733
734         if (n.empty())
735                 lyxerr << "Operator[] called with empty n" << endl;
736
737         string const name = (n.empty() ? defaultLayoutName() : n);
738
739         static string lastLayoutName;
740         static LayoutList::difference_type lastLayoutIndex;
741
742         if (name == lastLayoutName)
743                 return layoutlist_[lastLayoutIndex];
744
745         LayoutList::const_iterator cit =
746                 find_if(layoutlist_.begin(),
747                         layoutlist_.end(),
748                         compare_name(name));
749
750         if (cit == layoutlist_.end()) {
751                 lyxerr << "We failed to find the layout '" << name
752                        << "' in the layout list. You MUST investigate!"
753                        << endl;
754
755                 // we require the name to exist
756                 lyx::Assert(false);
757         }
758
759         lastLayoutName = name;
760         lastLayoutIndex = std::distance(layoutlist_.begin(), cit);
761
762         return (*cit);
763 }
764
765
766 bool LyXTextClass::delete_layout(string const & name)
767 {
768         if (name == defaultLayoutName())
769                 return false;
770
771         LayoutList::iterator it =
772                 remove_if(layoutlist_.begin(), layoutlist_.end(),
773                           compare_name(name));
774
775         LayoutList::iterator end = layoutlist_.end();
776         bool const ret = (it != end);
777         layoutlist_.erase(it, end);
778         return ret;
779 }
780
781
782 // Load textclass info if not loaded yet
783 bool LyXTextClass::load() const
784 {
785         if (loaded)
786                 return true;
787
788         // Read style-file
789         string const real_file = LibFileSearch("layouts", name_, "layout");
790
791         if (const_cast<LyXTextClass*>(this)->Read(real_file)) {
792                 lyxerr << "Error reading `"
793                        << MakeDisplayPath(real_file)
794                        << "'\n(Check `" << name_
795                        << "')\nCheck your installation and "
796                         "try Options/Reconfigure..." << endl;
797                 loaded = false;
798         }
799         loaded = true;
800         return loaded;
801 }
802
803
804 FloatList & LyXTextClass::floats()
805 {
806         return *floatlist_.get();
807 }
808
809
810 FloatList const & LyXTextClass::floats() const
811 {
812         return *floatlist_.get();
813 }
814
815
816 Counters & LyXTextClass::counters() const
817 {
818         return *ctrs_.get();
819 }
820
821
822 string const & LyXTextClass::defaultLayoutName() const
823 {
824         // This really should come from the actual layout... (Lgb)
825         return defaultlayout_;
826 }
827
828
829 LyXLayout_ptr const & LyXTextClass::defaultLayout() const
830 {
831         return operator[](defaultLayoutName());
832 }
833
834
835 string const & LyXTextClass::name() const
836 {
837         return name_;
838 }
839
840
841 string const & LyXTextClass::latexname() const
842 {
843         const_cast<LyXTextClass*>(this)->load();
844         return latexname_;
845 }
846
847
848 string const & LyXTextClass::description() const
849 {
850         return description_;
851 }
852
853
854 string const & LyXTextClass::opt_fontsize() const
855 {
856         return opt_fontsize_;
857 }
858
859
860 string const & LyXTextClass::opt_pagestyle() const
861 {
862         return opt_pagestyle_;
863 }
864
865
866 string const & LyXTextClass::options() const
867 {
868         return options_;
869 }
870
871
872 string const & LyXTextClass::pagestyle() const
873 {
874         return pagestyle_;
875 }
876
877
878 string const & LyXTextClass::preamble() const
879 {
880         return preamble_;
881 }
882
883
884 LyXTextClass::PageSides LyXTextClass::sides() const
885 {
886         return sides_;
887 }
888
889
890 int LyXTextClass::secnumdepth() const
891 {
892         return secnumdepth_;
893 }
894
895
896 int LyXTextClass::tocdepth() const
897 {
898         return tocdepth_;
899 }
900
901
902 OutputType LyXTextClass::outputType() const
903 {
904         return outputType_;
905 }
906
907
908 bool LyXTextClass::provides(LyXTextClass::Provides p) const
909 {
910         return provides_ & p;
911 }
912
913
914 unsigned int LyXTextClass::columns() const
915 {
916         return columns_;
917 }
918
919
920 int LyXTextClass::maxcounter() const
921 {
922         return maxcounter_;
923 }
924
925
926 LYX_TITLE_LATEX_TYPES LyXTextClass::titletype() const
927 {
928         return titletype_;
929 }
930
931
932 string const & LyXTextClass::titlename() const
933 {
934         return titlename_;
935 }
936
937
938
939
940
941 int LyXTextClass::size() const
942 {
943         return layoutlist_.size();
944 }
945
946
947 ostream & operator<<(ostream & os, LyXTextClass::PageSides p)
948 {
949         switch (p) {
950         case LyXTextClass::OneSide:
951                 os << '1';
952                 break;
953         case LyXTextClass::TwoSides:
954                 os << '2';
955                 break;
956         }
957         return os;
958 }