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