1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1999 The LyX Team.
9 * ====================================================== */
14 #pragma implementation
23 #include "support/filetools.h"
24 #include "lyx_gui_misc.h"
27 #include "support/LAssert.h"
30 // Global variable: textclass table.
31 LyXTextClassList textclasslist;
34 // Reads the style files
37 lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
39 if (!textclasslist.Read()) {
40 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
41 "during parsing.\n Exiting." << endl;
45 lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
49 // The order of the LayoutTags enum is no more important. [asierra300396]
60 //LT_ENVIRONMENT_DEFAULT,
76 LT_LABELSTRING_APPENDIX,
97 // This table is sorted alphabetically [asierra 30March96]
98 static keyword_item layoutTags[] = {
99 { "align", LT_ALIGN },
100 { "alignpossible", LT_ALIGNPOSSIBLE },
101 { "bottomsep", LT_BOTTOMSEP },
102 { "copystyle", LT_COPYSTYLE },
104 { "fill_bottom", LT_FILL_BOTTOM },
105 { "fill_top", LT_FILL_TOP },
107 { "freespacing", LT_FREE_SPACING },
108 { "intitle", LT_INTITLE },
109 { "itemsep", LT_ITEMSEP },
110 { "keepempty", LT_KEEPEMPTY },
111 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
112 { "labelfont", LT_LABELFONT },
113 { "labelindent", LT_LABELINDENT },
114 { "labelsep", LT_LABELSEP },
115 { "labelstring", LT_LABELSTRING },
116 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
117 { "labeltype", LT_LABELTYPE },
118 { "latexname", LT_LATEXNAME },
119 { "latexparam", LT_LATEXPARAM },
120 { "latextype", LT_LATEXTYPE },
121 { "leftmargin", LT_LEFTMARGIN },
122 { "margin", LT_MARGIN },
123 { "needprotect", LT_NEED_PROTECT },
124 { "newline", LT_NEWLINE },
125 { "nextnoindent", LT_NEXTNOINDENT },
126 { "obsoletedby", LT_OBSOLETEDBY },
127 { "parindent", LT_PARINDENT },
128 { "parsep", LT_PARSEP },
129 { "parskip", LT_PARSKIP },
130 { "preamble", LT_PREAMBLE },
131 { "rightmargin", LT_RIGHTMARGIN },
132 { "spacing", LT_SPACING },
133 { "textfont", LT_TEXTFONT },
134 { "topsep", LT_TOPSEP }
138 /////////////////////
140 // Constructor for layout
141 LyXLayout::LyXLayout ()
143 margintype = MARGIN_STATIC;
144 latextype = LATEX_PARAGRAPH;
148 font = LyXFont(LyXFont::ALL_INHERIT);
149 labelfont = LyXFont(LyXFont::ALL_INHERIT);
150 resfont = LyXFont(LyXFont::ALL_SANE);
151 reslabelfont = LyXFont(LyXFont::ALL_SANE);
152 nextnoindent = false;
157 labelbottomsep = 0.0;
159 align = LYX_ALIGN_BLOCK;
160 alignpossible = LYX_ALIGN_BLOCK;
161 labeltype = LABEL_NO_LABEL;
162 // Should or should not. That is the question.
163 // spacing.set(Spacing::OneHalf);
166 newline_allowed = true;
167 free_spacing = false;
171 // Reads a layout definition from file
172 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
175 bool finished = false;
176 lexrc.pushTable(layoutTags, LT_INTITLE);
177 // parse style section
178 while (!finished && lexrc.IsOK() && !error) {
179 int le = lexrc.lex();
180 // See comment in lyxrc.C.
182 case LyXLex::LEX_FEOF:
185 case LyXLex::LEX_UNDEF: // parse error
186 lexrc.printError("Unknown layout tag `$$Token'");
191 switch(static_cast<LayoutTags>(le)) {
192 case LT_END: // end of structure
196 case LT_COPYSTYLE: // initialize with a known style
198 if (tclass.hasLayout(lexrc.GetString())) {
199 string tmpname = name_;
200 this->operator= (tclass.GetLayout(lexrc.GetString()));
203 lexrc.printError("Cannot copy known "
209 case LT_OBSOLETEDBY: // replace with a known style
211 if (tclass.hasLayout(lexrc.GetString())) {
212 string tmpname = name_;
213 this->operator= (tclass.GetLayout(lexrc.GetString()));
215 if (obsoleted_by().empty())
216 obsoleted_by_ = lexrc.GetString();
218 lexrc.printError("Cannot replace with"
225 case LT_MARGIN: // Margin style definition.
229 case LT_LATEXTYPE: // Latex style definition.
230 readLatexType(lexrc);
234 intitle = lexrc.next() && lexrc.GetInteger();
237 case LT_NEED_PROTECT:
238 needprotect = lexrc.next() && lexrc.GetInteger();
242 keepempty = lexrc.next() && lexrc.GetInteger();
255 labelfont.lyxRead(lexrc);
258 case LT_NEXTNOINDENT: // Indent next paragraph?
259 if (lexrc.next() && lexrc.GetInteger())
262 nextnoindent = false;
267 latexname_ = lexrc.GetString();
272 latexparam_ = lexrc.GetString();
276 preamble_ = lexrc.getLongString("EndPreamble");
280 readLabelType(lexrc);
283 case LT_LEFTMARGIN: // left margin type
285 leftmargin = lexrc.GetString();
288 case LT_RIGHTMARGIN: // right margin type
290 rightmargin = lexrc.GetString();
293 case LT_LABELINDENT: // label indenting flag
295 labelindent = lexrc.GetString();
298 case LT_PARINDENT: // paragraph indent. flag
300 parindent = lexrc.GetString();
303 case LT_PARSKIP: // paragraph skip size
305 parskip = lexrc.GetFloat();
308 case LT_ITEMSEP: // item separation size
310 itemsep = lexrc.GetFloat();
313 case LT_TOPSEP: // top separation size
315 topsep = lexrc.GetFloat();
318 case LT_BOTTOMSEP: // bottom separation size
320 bottomsep = lexrc.GetFloat();
323 case LT_LABEL_BOTTOMSEP: // label bottom separation size
325 labelbottomsep = lexrc.GetFloat();
328 case LT_LABELSEP: // label separator
330 labelsep = subst(lexrc.GetString(), 'x', ' ');
334 case LT_PARSEP: // par. separation size
336 parsep = lexrc.GetFloat();
339 case LT_FILL_TOP: // fill top flag
341 fill_top = lexrc.GetInteger();
344 case LT_FILL_BOTTOM: // fill bottom flag
346 fill_bottom = lexrc.GetInteger();
349 case LT_NEWLINE: // newlines allowed?
351 newline_allowed = lexrc.GetInteger();
354 case LT_ALIGN: // paragraph align
357 case LT_ALIGNPOSSIBLE: // paragraph allowed align
358 readAlignPossible(lexrc);
361 case LT_LABELSTRING: // label string definition
363 labelstring_ = lexrc.GetString();
366 case LT_LABELSTRING_APPENDIX: // label string appendix definition
368 labelstring_appendix_ = lexrc.GetString();
371 case LT_FREE_SPACING: // Allow for free spacing.
373 free_spacing = lexrc.GetInteger();
376 case LT_SPACING: // setspace.sty
395 static keyword_item alignTags[] = {
396 { "block", AT_BLOCK },
397 { "center", AT_CENTER },
398 { "layout", AT_LAYOUT },
400 { "right", AT_RIGHT }
404 void LyXLayout::readAlign(LyXLex & lexrc)
406 pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
407 int le = lexrc.lex();
409 case LyXLex::LEX_UNDEF:
410 lexrc.printError("Unknown alignment `$$Token'");
414 switch(static_cast<AlignTags>(le)) {
416 align = LYX_ALIGN_BLOCK;
419 align = LYX_ALIGN_LEFT;
422 align = LYX_ALIGN_RIGHT;
425 align = LYX_ALIGN_CENTER;
428 align = LYX_ALIGN_LAYOUT;
434 void LyXLayout::readAlignPossible(LyXLex & lexrc)
436 lexrc.pushTable(alignTags, AT_LAYOUT);
437 alignpossible = LYX_ALIGN_NONE;
438 int lineno = lexrc.GetLineNo();
440 int le = lexrc.lex();
442 case LyXLex::LEX_UNDEF:
443 lexrc.printError("Unknown alignment `$$Token'");
447 switch (static_cast<AlignTags>(le)) {
449 alignpossible |= LYX_ALIGN_BLOCK;
452 alignpossible |= LYX_ALIGN_LEFT;
455 alignpossible |= LYX_ALIGN_RIGHT;
458 alignpossible |= LYX_ALIGN_CENTER;
461 alignpossible |= LYX_ALIGN_LAYOUT;
464 } while (lineno == lexrc.GetLineNo());
473 LA_CENTERED_TOP_ENVIRONMENT,
478 LA_COUNTER_SUBSECTION,
479 LA_COUNTER_SUBSUBSECTION,
480 LA_COUNTER_PARAGRAPH,
481 LA_COUNTER_SUBPARAGRAPH,
490 static keyword_item labelTypeTags[] = {
491 { "bibliography", LA_BIBLIO },
492 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
493 { "counter_chapter", LA_COUNTER_CHAPTER },
494 { "counter_enumi", LA_COUNTER_ENUMI },
495 { "counter_enumii", LA_COUNTER_ENUMII },
496 { "counter_enumiii", LA_COUNTER_ENUMIII },
497 { "counter_enumiv", LA_COUNTER_ENUMIV },
498 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
499 { "counter_section", LA_COUNTER_SECTION },
500 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
501 { "counter_subsection", LA_COUNTER_SUBSECTION },
502 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
503 { "manual", LA_MANUAL },
504 { "no_label", LA_NO_LABEL },
505 { "sensitive", LA_SENSITIVE },
506 { "static", LA_STATIC },
507 { "top_environment", LA_TOP_ENVIRONMENT }
511 void LyXLayout::readLabelType(LyXLex & lexrc)
513 pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
514 int le = lexrc.lex();
516 case LyXLex::LEX_UNDEF:
517 lexrc.printError("Unknown labeltype tag `$$Token'");
521 switch (static_cast<LabelTypeTags>(le)) {
523 labeltype = LABEL_NO_LABEL;
526 labeltype = LABEL_MANUAL;
528 case LA_TOP_ENVIRONMENT:
529 labeltype = LABEL_TOP_ENVIRONMENT;
531 case LA_CENTERED_TOP_ENVIRONMENT:
532 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
535 labeltype = LABEL_STATIC;
538 labeltype = LABEL_SENSITIVE;
540 case LA_COUNTER_CHAPTER:
541 labeltype = LABEL_COUNTER_CHAPTER;
543 case LA_COUNTER_SECTION:
544 labeltype = LABEL_COUNTER_SECTION;
546 case LA_COUNTER_SUBSECTION:
547 labeltype = LABEL_COUNTER_SUBSECTION;
549 case LA_COUNTER_SUBSUBSECTION:
550 labeltype = LABEL_COUNTER_SUBSUBSECTION;
552 case LA_COUNTER_PARAGRAPH:
553 labeltype = LABEL_COUNTER_PARAGRAPH;
555 case LA_COUNTER_SUBPARAGRAPH:
556 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
558 case LA_COUNTER_ENUMI:
559 labeltype = LABEL_COUNTER_ENUMI;
561 case LA_COUNTER_ENUMII:
562 labeltype = LABEL_COUNTER_ENUMII;
564 case LA_COUNTER_ENUMIII:
565 labeltype = LABEL_COUNTER_ENUMIII;
567 case LA_COUNTER_ENUMIV:
568 labeltype = LABEL_COUNTER_ENUMIV;
571 labeltype = LABEL_BIBLIO;
586 static keyword_item marginTags[] = {
587 { "dynamic", MT_DYNAMIC },
588 { "first_dynamic", MT_FIRST_DYNAMIC },
589 { "manual", MT_MANUAL },
590 { "right_address_box", MT_RIGHT_ADDRESS_BOX },
591 { "static", MT_STATIC }
595 void LyXLayout::readMargin(LyXLex & lexrc)
597 pushpophelper pph(lexrc, marginTags, MT_RIGHT_ADDRESS_BOX);
598 int le = lexrc.lex();
600 case LyXLex::LEX_UNDEF:
601 lexrc.printError("Unknown margin type tag `$$Token'");
605 switch(static_cast<MarginTags>(le)) {
607 margintype = MARGIN_STATIC;
610 margintype = MARGIN_MANUAL;
613 margintype = MARGIN_DYNAMIC;
615 case MT_FIRST_DYNAMIC:
616 margintype = MARGIN_FIRST_DYNAMIC;
618 case MT_RIGHT_ADDRESS_BOX:
619 margintype = MARGIN_RIGHT_ADDRESS_BOX;
634 static keyword_item latexTypeTags[] = {
635 { "command", LX_COMMAND },
636 { "environment", LX_ENVIRONMENT },
637 { "item_environment", LX_ITEM_ENVIRONMENT },
638 { "list_environment", LX_LIST_ENVIRONMENT },
639 { "paragraph", LX_PARAGRAPH }
643 void LyXLayout::readLatexType(LyXLex & lexrc)
645 pushpophelper pph(lexrc, latexTypeTags, LX_LIST_ENVIRONMENT);
646 int le = lexrc.lex();
648 case LyXLex::LEX_UNDEF:
649 lexrc.printError("Unknown latextype tag `$$Token'");
653 switch (static_cast<LatexTypeTags>(le)) {
655 latextype= LATEX_PARAGRAPH;
658 latextype= LATEX_COMMAND;
661 latextype= LATEX_ENVIRONMENT;
663 case LX_ITEM_ENVIRONMENT:
664 latextype= LATEX_ITEM_ENVIRONMENT;
666 case LX_LIST_ENVIRONMENT:
667 latextype= LATEX_LIST_ENVIRONMENT;
674 ST_SPACING_SINGLE = 1,
681 static keyword_item spacingTags[] = {
682 {"double", ST_SPACING_DOUBLE },
683 {"onehalf", ST_SPACING_ONEHALF },
684 {"other", ST_OTHER },
685 {"single", ST_SPACING_SINGLE }
689 void LyXLayout::readSpacing(LyXLex & lexrc)
691 pushpophelper pph(lexrc, spacingTags, ST_OTHER);
692 int le = lexrc.lex();
694 case LyXLex::LEX_UNDEF:
695 lexrc.printError("Unknown spacing token `$$Token'");
699 switch(static_cast<SpacingTags>(le)) {
700 case ST_SPACING_SINGLE:
701 spacing.set(Spacing::Single);
703 case ST_SPACING_ONEHALF:
704 spacing.set(Spacing::Onehalf);
706 case ST_SPACING_DOUBLE:
707 spacing.set(Spacing::Double);
711 spacing.set(Spacing::Other, lexrc.GetFloat());
717 /* ******************************************************************* */
719 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
721 : name_(fn), latexname_(cln), description_(desc)
728 pagestyle_ = "default";
729 maxcounter_ = LABEL_COUNTER_CHAPTER;
730 defaultfont_ = LyXFont(LyXFont::ALL_SANE);
731 opt_fontsize_ = "10|11|12";
732 opt_pagestyle_ = "empty|plain|headings|fancy";
738 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
740 lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
741 if (!lay.Read(lexrc, *this)) {
743 lay.resfont = lay.font;
744 lay.resfont.realize(defaultfont());
745 lay.reslabelfont = lay.labelfont;
746 lay.reslabelfont.realize(defaultfont());
747 return false; // no errors
749 lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
776 static keyword_item textClassTags[] = {
777 { "classoptions", TC_CLASSOPTIONS },
778 { "columns", TC_COLUMNS },
779 { "defaultfont", TC_DEFAULTFONT },
780 { "input", TC_INPUT },
781 { "leftmargin", TC_LEFTMARGIN },
782 { "maxcounter", TC_MAXCOUNTER },
783 { "nostyle", TC_NOSTYLE },
784 { "outputtype", TC_OUTPUTTYPE },
785 { "pagestyle", TC_PAGESTYLE },
786 { "preamble", TC_PREAMBLE },
787 { "providesamsmath", TC_PROVIDESAMSMATH },
788 { "providesmakeidx", TC_PROVIDESMAKEIDX },
789 { "providesurl", TC_PROVIDESURL },
790 { "rightmargin", TC_RIGHTMARGIN },
791 { "secnumdepth", TC_SECNUMDEPTH },
792 { "sides", TC_SIDES },
793 { "style", TC_STYLE },
794 { "tocdepth", TC_TOCDEPTH }
798 // Reads a textclass structure from file.
799 bool LyXTextClass::Read(string const & filename, bool merge)
802 lyxerr[Debug::TCLASS] << "Reading textclass "
803 << MakeDisplayPath(filename)
806 lyxerr[Debug::TCLASS] << "Reading input file "
807 << MakeDisplayPath(filename)
810 LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
813 lexrc.setFile(filename);
814 if (!lexrc.IsOK()) error = true;
817 while (lexrc.IsOK() && !error) {
818 int le = lexrc.lex();
820 case LyXLex::LEX_FEOF:
823 case LyXLex::LEX_UNDEF:
824 lexrc.printError("Unknown TextClass tag `$$Token'");
829 switch(static_cast<TextClassTags>(le)) {
830 case TC_OUTPUTTYPE: // output type definition
831 readOutputType(lexrc);
834 case TC_INPUT: // Include file
836 string tmp = LibFileSearch("layouts",
840 if (Read(tmp, true)) {
841 lexrc.printError("Error reading input"
850 string name = subst(lexrc.GetString(),
852 if (hasLayout(name)) {
853 LyXLayout & lay = GetLayout(name);
854 error = do_readStyle(lexrc, lay);
858 if (!(error = do_readStyle(lexrc, lay)))
859 layoutlist.push_back(lay);
863 lexrc.printError("No name given for style: `$$Token'.");
870 string style = subst(lexrc.GetString(),
872 if (!delete_layout(style))
873 lexrc.printError("Cannot delete style"
880 columns_ = lexrc.GetInteger();
885 switch(lexrc.GetInteger()) {
886 case 1: sides_ = OneSide; break;
887 case 2: sides_ = TwoSides; break;
889 lyxerr << "Impossible number of page"
890 " sides, setting to one."
900 pagestyle_ = strip(lexrc.GetString());
904 defaultfont_.lyxRead(lexrc);
905 if (!defaultfont_.resolved()) {
906 lexrc.printError("Warning: defaultfont should "
907 "be fully instantiated!");
908 defaultfont_.realize(LyXFont::ALL_SANE);
913 readMaxCounter(lexrc);
918 secnumdepth_ = lexrc.GetInteger();
923 tocdepth_ = lexrc.GetInteger();
926 // First step to support options
927 case TC_CLASSOPTIONS:
928 readClassOptions(lexrc);
932 preamble_ = lexrc.getLongString("EndPreamble");
935 case TC_PROVIDESAMSMATH:
936 if (lexrc.next() && lexrc.GetInteger())
937 provides_ |= amsmath;
940 case TC_PROVIDESMAKEIDX:
941 if (lexrc.next() && lexrc.GetInteger())
942 provides_ |= makeidx;
946 if (lexrc.next() && lexrc.GetInteger())
950 case TC_LEFTMARGIN: // left margin type
952 leftmargin_ = lexrc.GetString();
955 case TC_RIGHTMARGIN: // right margin type
957 rightmargin_ = lexrc.GetString();
962 if (!merge) { // we are at top level here.
963 lyxerr[Debug::TCLASS] << "Finished reading textclass "
964 << MakeDisplayPath(filename)
967 lyxerr[Debug::TCLASS] << "Finished reading input file "
968 << MakeDisplayPath(filename)
975 enum OutputTypeTags {
983 static keyword_item outputTypeTags[] = {
984 { "docbook", OT_OTDOCBOOK },
985 { "latex", OT_OTLATEX },
986 { "linuxdoc", OT_OTLINUXDOC },
987 { "literate", OT_OTLITERATE }
991 void LyXTextClass::readOutputType(LyXLex & lexrc)
993 pushpophelper pph(lexrc, outputTypeTags, OT_OTLITERATE);
994 int le = lexrc.lex();
996 case LyXLex::LEX_UNDEF:
997 lexrc.printError("Unknown output type `$$Token'");
1001 switch(static_cast<OutputTypeTags>(le)) {
1003 outputType_ = LATEX;
1006 outputType_ = LINUXDOC;
1009 outputType_ = DOCBOOK;
1012 outputType_ = LITERATE;
1018 enum MaxCounterTags {
1019 MC_COUNTER_CHAPTER = 1,
1021 MC_COUNTER_SUBSECTION,
1022 MC_COUNTER_SUBSUBSECTION,
1023 MC_COUNTER_PARAGRAPH,
1024 MC_COUNTER_SUBPARAGRAPH,
1032 static keyword_item maxCounterTags[] = {
1033 {"counter_chapter", MC_COUNTER_CHAPTER },
1034 {"counter_enumi", MC_COUNTER_ENUMI },
1035 {"counter_enumii", MC_COUNTER_ENUMII },
1036 {"counter_enumiii", MC_COUNTER_ENUMIII },
1037 {"counter_enumiv", MC_COUNTER_ENUMIV },
1038 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1039 {"counter_section", MC_COUNTER_SECTION },
1040 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1041 {"counter_subsection", MC_COUNTER_SUBSECTION },
1042 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1046 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1048 pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1049 int le = lexrc.lex();
1051 case LyXLex::LEX_UNDEF:
1052 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1056 switch (static_cast<MaxCounterTags>(le)) {
1057 case MC_COUNTER_CHAPTER:
1058 maxcounter_ = LABEL_COUNTER_CHAPTER;
1060 case MC_COUNTER_SECTION:
1061 maxcounter_ = LABEL_COUNTER_SECTION;
1063 case MC_COUNTER_SUBSECTION:
1064 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1066 case MC_COUNTER_SUBSUBSECTION:
1067 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1069 case MC_COUNTER_PARAGRAPH:
1070 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1072 case MC_COUNTER_SUBPARAGRAPH:
1073 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1075 case MC_COUNTER_ENUMI:
1076 maxcounter_ = LABEL_COUNTER_ENUMI;
1078 case MC_COUNTER_ENUMII:
1079 maxcounter_ = LABEL_COUNTER_ENUMII;
1081 case MC_COUNTER_ENUMIII:
1082 maxcounter_ = LABEL_COUNTER_ENUMIII;
1084 case MC_COUNTER_ENUMIV:
1085 maxcounter_ = LABEL_COUNTER_ENUMIV;
1091 enum ClassOptionsTags {
1099 static keyword_item classOptionsTags[] = {
1101 {"fontsize", CO_FONTSIZE },
1102 {"other", CO_OTHER },
1103 {"pagestyle", CO_PAGESTYLE }
1107 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1109 lexrc.pushTable(classOptionsTags, CO_END);
1110 bool getout = false;
1111 while (!getout && lexrc.IsOK()) {
1112 int le = lexrc.lex();
1114 case LyXLex::LEX_UNDEF:
1115 lexrc.printError("Unknown ClassOption tag `$$Token'");
1119 switch (static_cast<ClassOptionsTags>(le)) {
1122 opt_fontsize_ = strip(lexrc.GetString());
1126 opt_pagestyle_ = strip(lexrc.GetString());
1130 options_ = lexrc.GetString();
1141 bool LyXTextClass::hasLayout(string const & name) const
1143 for (LayoutList::const_iterator cit = layoutlist.begin();
1144 cit != layoutlist.end(); ++cit) {
1145 if ((*cit).name() == name)
1152 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1154 for (LayoutList::const_iterator cit = layoutlist.begin();
1155 cit != layoutlist.end(); ++cit) {
1156 if ((*cit).name() == name)
1159 Assert(false); // we actually require the name to exist.
1160 return layoutlist.front();
1164 LyXLayout & LyXTextClass::GetLayout(string const & name)
1166 for (LayoutList::iterator it = layoutlist.begin();
1167 it != layoutlist.end(); ++it) {
1168 if ((*it).name() == name)
1171 Assert(false); // we actually require the name to exist.
1172 return layoutlist.front();
1176 bool LyXTextClass::delete_layout (string const & name)
1178 for(LayoutList::iterator it = layoutlist.begin();
1179 it != layoutlist.end(); ++it) {
1180 if ((*it).name() == name) {
1181 layoutlist.erase(it);
1189 // Load textclass info if not loaded yet
1190 void LyXTextClass::load()
1195 string real_file = LibFileSearch("layouts", name_, "layout");
1197 if (Read(real_file)) {
1198 lyxerr << "Error reading `"
1199 << MakeDisplayPath(real_file)
1200 << "'\n(Check `" << name_
1201 << "')\nCheck your installation and "
1202 "try Options/Reconfigure..." << endl;
1208 //////////////////////////////////////////
1210 // Gets textclass number from name
1211 pair<bool, LyXTextClassList::size_type>
1212 LyXTextClassList::NumberOfClass(string const & textclass) const
1214 for (ClassList::const_iterator cit = classlist.begin();
1215 cit != classlist.end(); ++cit) {
1216 if ((*cit).name() == textclass)
1217 return make_pair(true, cit - classlist.begin());
1219 return make_pair(false, size_type(0));
1223 // Gets layout structure from style number and textclass number
1225 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1226 LyXTextClass::size_type layout) const
1228 classlist[textclass].load();
1229 if (layout < classlist[textclass].numLayouts())
1230 return classlist[textclass][layout];
1231 return classlist[textclass][0];
1235 // Gets layout number from name and textclass number
1236 pair<bool, LyXTextClass::size_type>
1237 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1238 string const & name) const
1240 classlist[textclass].load();
1241 for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1242 if (classlist[textclass][i].name() == name)
1243 return make_pair(true, i);
1245 if (name == "dummy")
1246 return make_pair(true, LYX_DUMMY_LAYOUT);
1247 return make_pair(false, LyXTextClass::LayoutList::size_type(0)); // not found
1251 // Gets a layout (style) name from layout number and textclass number
1253 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1254 LyXTextClass::size_type layout) const
1256 static string dummy("dummy");
1257 classlist[textclass].load();
1258 if (layout < classlist[textclass].numLayouts())
1259 return classlist[textclass][layout].name();
1264 // Gets a textclass name from number
1266 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1268 static string dummy("dummy");
1269 if (classlist.size() == 0) {
1272 Assert(number < classlist.size());
1273 return classlist[number].name();
1277 // Gets a textclass latexname from number
1279 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1281 static string dummy("dummy");
1282 classlist[number].load();
1283 if (classlist.size() == 0) {
1286 Assert(number < classlist.size());
1287 return classlist[number].latexname();
1291 // Gets a textclass description from number
1293 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1295 static string dummy("dummy");
1296 if (classlist.size() == 0) {
1299 Assert(number < classlist.size());
1300 return classlist[number].description();
1304 // Gets a textclass structure from number
1305 LyXTextClass const &
1306 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1308 classlist[textclass].load();
1309 if (textclass < classlist.size())
1310 return classlist[textclass];
1312 return classlist[0];
1316 void LyXTextClassList::Add(LyXTextClass const & t)
1318 classlist.push_back(t);
1322 // used when sorting the textclass list.
1323 class less_textclass_desc {
1325 int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1326 return tc1.description() < tc2.description();
1331 // Reads LyX textclass definitions according to textclass config file
1332 bool LyXTextClassList::Read ()
1335 string real_file = LibFileSearch("", "textclass.lst");
1336 lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1337 << real_file << "'" << endl;
1339 if (real_file.empty()) {
1340 lyxerr << "LyXTextClassList::Read: unable to find "
1341 "textclass file `" << MakeDisplayPath(real_file, 1000)
1342 << "'. Exiting." << endl;
1344 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1345 _("Check that the file \"textclass.lst\""),
1346 _("is installed correctly. Sorry, has to exit :-("));
1348 // This causes LyX to end... Not a desirable behaviour. Lgb
1349 // What do you propose? That the user gets a file dialog
1350 // and is allowed to hunt for the file? (Asger)
1351 // more that we have a layout for minimal.cls statically
1352 // compiled in... (Lgb)
1355 if (!lex.setFile(real_file)) {
1356 lyxerr << "LyXTextClassList::Read: "
1357 "lyxlex was not able to set file: "
1358 << real_file << endl;
1362 lyxerr << "LyXTextClassList::Read: unable to open "
1363 "textclass file `" << MakeDisplayPath(real_file, 1000)
1364 << "'\nCheck your installation. LyX can't continue."
1368 bool finished = false;
1369 string fname, clname, desc;
1370 // Parse config-file
1371 lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1372 while (lex.IsOK() && !finished) {
1373 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1374 switch (lex.lex()) {
1375 case LyXLex::LEX_FEOF:
1379 fname = lex.GetString();
1380 lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1382 clname = lex.GetString();
1383 lyxerr[Debug::TCLASS]
1384 << "Clname: " << clname << endl;
1386 desc = lex.GetString();
1387 lyxerr[Debug::TCLASS]
1388 << "Desc: " << desc << endl;
1389 // This code is run when we have
1390 // fname, clname and desc
1391 LyXTextClass tmpl(fname,
1395 debugging(Debug::TCLASS)) {
1403 lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1405 if (classlist.size() == 0) {
1406 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1408 WriteAlert(_("LyX wasn't able to find any layout description!"),
1409 _("Check the contents of the file \"textclass.lst\""),
1410 _("Sorry, has to exit :-("));
1413 // Ok everything loaded ok, now sort the list.
1414 sort(classlist.begin(), classlist.end(), less_textclass_desc());
1420 Returns false if this fails
1423 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1426 if (number < classlist.size()) {
1427 classlist[number].load();
1428 if (classlist[number].numLayouts() == 0) {