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