1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2001 The LyX Team.
9 * ======================================================
15 #pragma implementation
22 #include "support/filetools.h"
23 #include "frontends/Alert.h"
26 #include "support/LAssert.h"
27 #include "support/lyxfunctional.h"
28 #include "support/lstrings.h"
37 using lyx::layout_type;
38 using lyx::textclass_type;
41 // Global variable: textclass table.
42 LyXTextClassList textclasslist;
45 // Reads the style files
48 lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
50 if (!textclasslist.Read()) {
51 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
52 "during parsing.\n Exiting." << endl;
56 lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
60 // The order of the LayoutTags enum is no more important. [asierra300396]
71 //LT_ENVIRONMENT_DEFAULT,
88 LT_LABELSTRING_APPENDIX,
111 /////////////////////
113 // Constructor for layout
114 LyXLayout::LyXLayout ()
116 margintype = MARGIN_STATIC;
117 latextype = LATEX_PARAGRAPH;
121 font = LyXFont(LyXFont::ALL_INHERIT);
122 labelfont = LyXFont(LyXFont::ALL_INHERIT);
123 resfont = LyXFont(LyXFont::ALL_SANE);
124 reslabelfont = LyXFont(LyXFont::ALL_SANE);
125 nextnoindent = false;
130 labelbottomsep = 0.0;
132 align = LYX_ALIGN_BLOCK;
133 alignpossible = LYX_ALIGN_BLOCK;
134 labeltype = LABEL_NO_LABEL;
135 endlabeltype = END_LABEL_NO_LABEL;
136 // Should or should not. That is the question.
137 // spacing.set(Spacing::OneHalf);
140 newline_allowed = true;
141 free_spacing = false;
146 // Reads a layout definition from file
147 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
149 // This table is sorted alphabetically [asierra 30March96]
150 keyword_item layoutTags[] = {
151 { "align", LT_ALIGN },
152 { "alignpossible", LT_ALIGNPOSSIBLE },
153 { "bottomsep", LT_BOTTOMSEP },
154 { "copystyle", LT_COPYSTYLE },
156 { "endlabelstring", LT_ENDLABELSTRING },
157 { "endlabeltype", LT_ENDLABELTYPE },
158 { "fill_bottom", LT_FILL_BOTTOM },
159 { "fill_top", LT_FILL_TOP },
161 { "freespacing", LT_FREE_SPACING },
162 { "intitle", LT_INTITLE },
163 { "itemsep", LT_ITEMSEP },
164 { "keepempty", LT_KEEPEMPTY },
165 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
166 { "labelfont", LT_LABELFONT },
167 { "labelindent", LT_LABELINDENT },
168 { "labelsep", LT_LABELSEP },
169 { "labelstring", LT_LABELSTRING },
170 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
171 { "labeltype", LT_LABELTYPE },
172 { "latexname", LT_LATEXNAME },
173 { "latexparam", LT_LATEXPARAM },
174 { "latextype", LT_LATEXTYPE },
175 { "leftmargin", LT_LEFTMARGIN },
176 { "margin", LT_MARGIN },
177 { "needprotect", LT_NEED_PROTECT },
178 { "newline", LT_NEWLINE },
179 { "nextnoindent", LT_NEXTNOINDENT },
180 { "obsoletedby", LT_OBSOLETEDBY },
181 { "parindent", LT_PARINDENT },
182 { "parsep", LT_PARSEP },
183 { "parskip", LT_PARSKIP },
184 { "passthru", LT_PASS_THRU },
185 { "preamble", LT_PREAMBLE },
186 { "rightmargin", LT_RIGHTMARGIN },
187 { "spacing", LT_SPACING },
188 { "textfont", LT_TEXTFONT },
189 { "topsep", LT_TOPSEP }
193 bool finished = false;
194 lexrc.pushTable(layoutTags, LT_INTITLE);
195 // parse style section
196 while (!finished && lexrc.isOK() && !error) {
197 int le = lexrc.lex();
198 // See comment in lyxrc.C.
200 case LyXLex::LEX_FEOF:
203 case LyXLex::LEX_UNDEF: // parse error
204 lexrc.printError("Unknown layout tag `$$Token'");
209 switch (static_cast<LayoutTags>(le)) {
210 case LT_END: // end of structure
214 case LT_COPYSTYLE: // initialize with a known style
216 if (tclass.hasLayout(lexrc.getString())) {
217 string const tmpname = name_;
218 this->operator= (tclass.GetLayout(lexrc.getString()));
221 lexrc.printError("Cannot copy known "
227 case LT_OBSOLETEDBY: // replace with a known style
229 if (tclass.hasLayout(lexrc.getString())) {
230 string const tmpname = name_;
231 this->operator= (tclass.GetLayout(lexrc.getString()));
233 if (obsoleted_by().empty())
234 obsoleted_by_ = lexrc.getString();
236 lexrc.printError("Cannot replace with"
243 case LT_MARGIN: // Margin style definition.
247 case LT_LATEXTYPE: // Latex style definition.
248 readLatexType(lexrc);
252 intitle = lexrc.next() && lexrc.getInteger();
255 case LT_NEED_PROTECT:
256 needprotect = lexrc.next() && lexrc.getInteger();
260 keepempty = lexrc.next() && lexrc.getInteger();
273 labelfont.lyxRead(lexrc);
276 case LT_NEXTNOINDENT: // Indent next paragraph?
277 if (lexrc.next() && lexrc.getInteger())
280 nextnoindent = false;
285 latexname_ = lexrc.getString();
290 latexparam_ = lexrc.getString();
294 preamble_ = lexrc.getLongString("EndPreamble");
298 readLabelType(lexrc);
301 case LT_ENDLABELTYPE:
302 readEndLabelType(lexrc);
305 case LT_LEFTMARGIN: // left margin type
307 leftmargin = lexrc.getString();
310 case LT_RIGHTMARGIN: // right margin type
312 rightmargin = lexrc.getString();
315 case LT_LABELINDENT: // label indenting flag
317 labelindent = lexrc.getString();
320 case LT_PARINDENT: // paragraph indent. flag
322 parindent = lexrc.getString();
325 case LT_PARSKIP: // paragraph skip size
327 parskip = lexrc.getFloat();
330 case LT_ITEMSEP: // item separation size
332 itemsep = lexrc.getFloat();
335 case LT_TOPSEP: // top separation size
337 topsep = lexrc.getFloat();
340 case LT_BOTTOMSEP: // bottom separation size
342 bottomsep = lexrc.getFloat();
345 case LT_LABEL_BOTTOMSEP: // label bottom separation size
347 labelbottomsep = lexrc.getFloat();
350 case LT_LABELSEP: // label separator
352 labelsep = subst(lexrc.getString(), 'x', ' ');
356 case LT_PARSEP: // par. separation size
358 parsep = lexrc.getFloat();
361 case LT_FILL_TOP: // fill top flag
363 fill_top = lexrc.getInteger();
366 case LT_FILL_BOTTOM: // fill bottom flag
368 fill_bottom = lexrc.getInteger();
371 case LT_NEWLINE: // newlines allowed?
373 newline_allowed = lexrc.getInteger();
376 case LT_ALIGN: // paragraph align
379 case LT_ALIGNPOSSIBLE: // paragraph allowed align
380 readAlignPossible(lexrc);
383 case LT_LABELSTRING: // label string definition
385 labelstring_ = lexrc.getString();
388 case LT_ENDLABELSTRING: // endlabel string definition
390 endlabelstring_ = lexrc.getString();
393 case LT_LABELSTRING_APPENDIX: // label string appendix definition
395 labelstring_appendix_ = lexrc.getString();
398 case LT_FREE_SPACING: // Allow for free spacing.
400 free_spacing = lexrc.getInteger();
403 case LT_PASS_THRU: // Allow for pass thru.
405 pass_thru = lexrc.getInteger();
408 case LT_SPACING: // setspace.sty
427 void LyXLayout::readAlign(LyXLex & lexrc)
429 keyword_item alignTags[] = {
430 { "block", AT_BLOCK },
431 { "center", AT_CENTER },
432 { "layout", AT_LAYOUT },
434 { "right", AT_RIGHT }
437 pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
438 int le = lexrc.lex();
440 case LyXLex::LEX_UNDEF:
441 lexrc.printError("Unknown alignment `$$Token'");
445 switch (static_cast<AlignTags>(le)) {
447 align = LYX_ALIGN_BLOCK;
450 align = LYX_ALIGN_LEFT;
453 align = LYX_ALIGN_RIGHT;
456 align = LYX_ALIGN_CENTER;
459 align = LYX_ALIGN_LAYOUT;
465 void LyXLayout::readAlignPossible(LyXLex & lexrc)
467 keyword_item alignTags[] = {
468 { "block", AT_BLOCK },
469 { "center", AT_CENTER },
470 { "layout", AT_LAYOUT },
472 { "right", AT_RIGHT }
475 lexrc.pushTable(alignTags, AT_LAYOUT);
476 alignpossible = LYX_ALIGN_NONE;
477 int lineno = lexrc.getLineNo();
479 int le = lexrc.lex();
481 case LyXLex::LEX_UNDEF:
482 lexrc.printError("Unknown alignment `$$Token'");
486 switch (static_cast<AlignTags>(le)) {
488 alignpossible |= LYX_ALIGN_BLOCK;
491 alignpossible |= LYX_ALIGN_LEFT;
494 alignpossible |= LYX_ALIGN_RIGHT;
497 alignpossible |= LYX_ALIGN_CENTER;
500 alignpossible |= LYX_ALIGN_LAYOUT;
503 } while (lineno == lexrc.getLineNo());
512 LA_CENTERED_TOP_ENVIRONMENT,
517 LA_COUNTER_SUBSECTION,
518 LA_COUNTER_SUBSUBSECTION,
519 LA_COUNTER_PARAGRAPH,
520 LA_COUNTER_SUBPARAGRAPH,
529 void LyXLayout::readLabelType(LyXLex & lexrc)
531 keyword_item labelTypeTags[] = {
532 { "bibliography", LA_BIBLIO },
533 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
534 { "counter_chapter", LA_COUNTER_CHAPTER },
535 { "counter_enumi", LA_COUNTER_ENUMI },
536 { "counter_enumii", LA_COUNTER_ENUMII },
537 { "counter_enumiii", LA_COUNTER_ENUMIII },
538 { "counter_enumiv", LA_COUNTER_ENUMIV },
539 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
540 { "counter_section", LA_COUNTER_SECTION },
541 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
542 { "counter_subsection", LA_COUNTER_SUBSECTION },
543 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
544 { "manual", LA_MANUAL },
545 { "no_label", LA_NO_LABEL },
546 { "sensitive", LA_SENSITIVE },
547 { "static", LA_STATIC },
548 { "top_environment", LA_TOP_ENVIRONMENT }
551 pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
552 int le = lexrc.lex();
554 case LyXLex::LEX_UNDEF:
555 lexrc.printError("Unknown labeltype tag `$$Token'");
559 switch (static_cast<LabelTypeTags>(le)) {
561 labeltype = LABEL_NO_LABEL;
564 labeltype = LABEL_MANUAL;
566 case LA_TOP_ENVIRONMENT:
567 labeltype = LABEL_TOP_ENVIRONMENT;
569 case LA_CENTERED_TOP_ENVIRONMENT:
570 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
573 labeltype = LABEL_STATIC;
576 labeltype = LABEL_SENSITIVE;
578 case LA_COUNTER_CHAPTER:
579 labeltype = LABEL_COUNTER_CHAPTER;
581 case LA_COUNTER_SECTION:
582 labeltype = LABEL_COUNTER_SECTION;
584 case LA_COUNTER_SUBSECTION:
585 labeltype = LABEL_COUNTER_SUBSECTION;
587 case LA_COUNTER_SUBSUBSECTION:
588 labeltype = LABEL_COUNTER_SUBSUBSECTION;
590 case LA_COUNTER_PARAGRAPH:
591 labeltype = LABEL_COUNTER_PARAGRAPH;
593 case LA_COUNTER_SUBPARAGRAPH:
594 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
596 case LA_COUNTER_ENUMI:
597 labeltype = LABEL_COUNTER_ENUMI;
599 case LA_COUNTER_ENUMII:
600 labeltype = LABEL_COUNTER_ENUMII;
602 case LA_COUNTER_ENUMIII:
603 labeltype = LABEL_COUNTER_ENUMIII;
605 case LA_COUNTER_ENUMIV:
606 labeltype = LABEL_COUNTER_ENUMIV;
609 labeltype = LABEL_BIBLIO;
617 keyword_item endlabelTypeTags[] = {
618 { "box", END_LABEL_BOX },
619 { "filled_box", END_LABEL_FILLED_BOX },
620 { "no_label", END_LABEL_NO_LABEL },
621 { "static", END_LABEL_STATIC }
627 void LyXLayout::readEndLabelType(LyXLex & lexrc)
629 pushpophelper pph(lexrc, endlabelTypeTags,
630 END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
631 int le = lexrc.lex();
633 case LyXLex::LEX_UNDEF:
634 lexrc.printError("Unknown labeltype tag `$$Token'");
636 case END_LABEL_STATIC:
638 case END_LABEL_FILLED_BOX:
639 case END_LABEL_NO_LABEL:
640 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
643 lyxerr << "Unhandled value " << le
644 << " in LyXLayout::readEndLabelType." << endl;
650 void LyXLayout::readMargin(LyXLex & lexrc)
652 keyword_item marginTags[] = {
653 { "dynamic", MARGIN_DYNAMIC },
654 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
655 { "manual", MARGIN_MANUAL },
656 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
657 { "static", MARGIN_STATIC }
660 pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
662 int le = lexrc.lex();
664 case LyXLex::LEX_UNDEF:
665 lexrc.printError("Unknown margin type tag `$$Token'");
670 case MARGIN_FIRST_DYNAMIC:
671 case MARGIN_RIGHT_ADDRESS_BOX:
672 margintype = static_cast<LYX_MARGIN_TYPE>(le);
675 lyxerr << "Unhandled value " << le
676 << " in LyXLayout::readMargin." << endl;
682 void LyXLayout::readLatexType(LyXLex & lexrc)
684 keyword_item latexTypeTags[] = {
685 { "command", LATEX_COMMAND },
686 { "environment", LATEX_ENVIRONMENT },
687 { "item_environment", LATEX_ITEM_ENVIRONMENT },
688 { "list_environment", LATEX_LIST_ENVIRONMENT },
689 { "paragraph", LATEX_PARAGRAPH }
692 pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
693 int le = lexrc.lex();
695 case LyXLex::LEX_UNDEF:
696 lexrc.printError("Unknown latextype tag `$$Token'");
698 case LATEX_PARAGRAPH:
700 case LATEX_ENVIRONMENT:
701 case LATEX_ITEM_ENVIRONMENT:
702 case LATEX_LIST_ENVIRONMENT:
703 latextype = static_cast<LYX_LATEX_TYPES>(le);
706 lyxerr << "Unhandled value " << le
707 << " in LyXLayout::readLatexType." << endl;
714 ST_SPACING_SINGLE = 1,
721 void LyXLayout::readSpacing(LyXLex & lexrc)
723 keyword_item spacingTags[] = {
724 {"double", ST_SPACING_DOUBLE },
725 {"onehalf", ST_SPACING_ONEHALF },
726 {"other", ST_OTHER },
727 {"single", ST_SPACING_SINGLE }
730 pushpophelper pph(lexrc, spacingTags, ST_OTHER);
731 int le = lexrc.lex();
733 case LyXLex::LEX_UNDEF:
734 lexrc.printError("Unknown spacing token `$$Token'");
738 switch (static_cast<SpacingTags>(le)) {
739 case ST_SPACING_SINGLE:
740 spacing.set(Spacing::Single);
742 case ST_SPACING_ONEHALF:
743 spacing.set(Spacing::Onehalf);
745 case ST_SPACING_DOUBLE:
746 spacing.set(Spacing::Double);
750 spacing.set(Spacing::Other, lexrc.getFloat());
756 /* ******************************************************************* */
758 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
760 : name_(fn), latexname_(cln), description_(desc)
767 pagestyle_ = "default";
768 maxcounter_ = LABEL_COUNTER_CHAPTER;
769 defaultfont_ = LyXFont(LyXFont::ALL_SANE);
770 opt_fontsize_ = "10|11|12";
771 opt_pagestyle_ = "empty|plain|headings|fancy";
777 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
779 lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
780 if (!lay.Read(lexrc, *this)) {
782 lay.resfont = lay.font;
783 #ifndef INHERIT_LANGUAGE
784 lay.resfont.realize(defaultfont());
785 lay.reslabelfont = lay.labelfont;
786 lay.reslabelfont.realize(defaultfont());
788 lay.resfont.realize(defaultfont(), default_language);
789 lay.reslabelfont = lay.labelfont;
790 lay.reslabelfont.realize(defaultfont(), default_language);
792 return false; // no errors
794 lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
821 // Reads a textclass structure from file.
822 bool LyXTextClass::Read(string const & filename, bool merge)
824 keyword_item textClassTags[] = {
825 { "classoptions", TC_CLASSOPTIONS },
826 { "columns", TC_COLUMNS },
827 { "defaultfont", TC_DEFAULTFONT },
828 { "input", TC_INPUT },
829 { "leftmargin", TC_LEFTMARGIN },
830 { "maxcounter", TC_MAXCOUNTER },
831 { "nostyle", TC_NOSTYLE },
832 { "outputtype", TC_OUTPUTTYPE },
833 { "pagestyle", TC_PAGESTYLE },
834 { "preamble", TC_PREAMBLE },
835 { "providesamsmath", TC_PROVIDESAMSMATH },
836 { "providesmakeidx", TC_PROVIDESMAKEIDX },
837 { "providesurl", TC_PROVIDESURL },
838 { "rightmargin", TC_RIGHTMARGIN },
839 { "secnumdepth", TC_SECNUMDEPTH },
840 { "sides", TC_SIDES },
841 { "style", TC_STYLE },
842 { "tocdepth", TC_TOCDEPTH }
846 lyxerr[Debug::TCLASS] << "Reading textclass "
847 << MakeDisplayPath(filename)
850 lyxerr[Debug::TCLASS] << "Reading input file "
851 << MakeDisplayPath(filename)
854 LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
857 lexrc.setFile(filename);
858 if (!lexrc.isOK()) error = true;
861 while (lexrc.isOK() && !error) {
862 int le = lexrc.lex();
864 case LyXLex::LEX_FEOF:
867 case LyXLex::LEX_UNDEF:
868 lexrc.printError("Unknown TextClass tag `$$Token'");
873 switch (static_cast<TextClassTags>(le)) {
874 case TC_OUTPUTTYPE: // output type definition
875 readOutputType(lexrc);
878 case TC_INPUT: // Include file
880 string tmp = LibFileSearch("layouts",
884 if (Read(tmp, true)) {
885 lexrc.printError("Error reading input"
894 string name = subst(lexrc.getString(),
896 if (hasLayout(name)) {
897 LyXLayout & lay = GetLayout(name);
898 error = do_readStyle(lexrc, lay);
902 if (!(error = do_readStyle(lexrc, lay)))
903 layoutlist.push_back(lay);
907 lexrc.printError("No name given for style: `$$Token'.");
914 string const style = subst(lexrc.getString(),
916 if (!delete_layout(style))
917 lexrc.printError("Cannot delete style"
924 columns_ = lexrc.getInteger();
929 switch (lexrc.getInteger()) {
930 case 1: sides_ = OneSide; break;
931 case 2: sides_ = TwoSides; break;
933 lyxerr << "Impossible number of page"
934 " sides, setting to one."
944 pagestyle_ = strip(lexrc.getString());
948 defaultfont_.lyxRead(lexrc);
949 if (!defaultfont_.resolved()) {
950 lexrc.printError("Warning: defaultfont should "
951 "be fully instantiated!");
952 #ifndef INHERIT_LANGUAGE
953 defaultfont_.realize(LyXFont(LyXFont::ALL_SANE));
955 defaultfont_.realize(LyXFont(LyXFont::ALL_SANE),
962 readMaxCounter(lexrc);
967 secnumdepth_ = lexrc.getInteger();
972 tocdepth_ = lexrc.getInteger();
975 // First step to support options
976 case TC_CLASSOPTIONS:
977 readClassOptions(lexrc);
981 preamble_ = lexrc.getLongString("EndPreamble");
984 case TC_PROVIDESAMSMATH:
985 if (lexrc.next() && lexrc.getInteger())
986 provides_ |= amsmath;
989 case TC_PROVIDESMAKEIDX:
990 if (lexrc.next() && lexrc.getInteger())
991 provides_ |= makeidx;
995 if (lexrc.next() && lexrc.getInteger())
999 case TC_LEFTMARGIN: // left margin type
1001 leftmargin_ = lexrc.getString();
1004 case TC_RIGHTMARGIN: // right margin type
1006 rightmargin_ = lexrc.getString();
1011 if (!merge) { // we are at top level here.
1012 lyxerr[Debug::TCLASS] << "Finished reading textclass "
1013 << MakeDisplayPath(filename)
1016 lyxerr[Debug::TCLASS] << "Finished reading input file "
1017 << MakeDisplayPath(filename)
1024 void LyXTextClass::readOutputType(LyXLex & lexrc)
1026 keyword_item outputTypeTags[] = {
1027 { "docbook", DOCBOOK },
1029 { "linuxdoc", LINUXDOC },
1030 { "literate", LITERATE }
1033 pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1035 int le = lexrc.lex();
1037 case LyXLex::LEX_UNDEF:
1038 lexrc.printError("Unknown output type `$$Token'");
1044 outputType_ = static_cast<OutputType>(le);
1047 lyxerr << "Unhandled value " << le
1048 << " in LyXTextClass::readOutputType." << endl;
1055 enum MaxCounterTags {
1056 MC_COUNTER_CHAPTER = 1,
1058 MC_COUNTER_SUBSECTION,
1059 MC_COUNTER_SUBSUBSECTION,
1060 MC_COUNTER_PARAGRAPH,
1061 MC_COUNTER_SUBPARAGRAPH,
1069 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1071 keyword_item maxCounterTags[] = {
1072 {"counter_chapter", MC_COUNTER_CHAPTER },
1073 {"counter_enumi", MC_COUNTER_ENUMI },
1074 {"counter_enumii", MC_COUNTER_ENUMII },
1075 {"counter_enumiii", MC_COUNTER_ENUMIII },
1076 {"counter_enumiv", MC_COUNTER_ENUMIV },
1077 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1078 {"counter_section", MC_COUNTER_SECTION },
1079 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1080 {"counter_subsection", MC_COUNTER_SUBSECTION },
1081 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1084 pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1085 int le = lexrc.lex();
1087 case LyXLex::LEX_UNDEF:
1088 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1092 switch (static_cast<MaxCounterTags>(le)) {
1093 case MC_COUNTER_CHAPTER:
1094 maxcounter_ = LABEL_COUNTER_CHAPTER;
1096 case MC_COUNTER_SECTION:
1097 maxcounter_ = LABEL_COUNTER_SECTION;
1099 case MC_COUNTER_SUBSECTION:
1100 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1102 case MC_COUNTER_SUBSUBSECTION:
1103 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1105 case MC_COUNTER_PARAGRAPH:
1106 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1108 case MC_COUNTER_SUBPARAGRAPH:
1109 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1111 case MC_COUNTER_ENUMI:
1112 maxcounter_ = LABEL_COUNTER_ENUMI;
1114 case MC_COUNTER_ENUMII:
1115 maxcounter_ = LABEL_COUNTER_ENUMII;
1117 case MC_COUNTER_ENUMIII:
1118 maxcounter_ = LABEL_COUNTER_ENUMIII;
1120 case MC_COUNTER_ENUMIV:
1121 maxcounter_ = LABEL_COUNTER_ENUMIV;
1127 enum ClassOptionsTags {
1135 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1137 keyword_item classOptionsTags[] = {
1139 {"fontsize", CO_FONTSIZE },
1140 {"other", CO_OTHER },
1141 {"pagestyle", CO_PAGESTYLE }
1144 lexrc.pushTable(classOptionsTags, CO_END);
1145 bool getout = false;
1146 while (!getout && lexrc.isOK()) {
1147 int le = lexrc.lex();
1149 case LyXLex::LEX_UNDEF:
1150 lexrc.printError("Unknown ClassOption tag `$$Token'");
1154 switch (static_cast<ClassOptionsTags>(le)) {
1157 opt_fontsize_ = strip(lexrc.getString());
1161 opt_pagestyle_ = strip(lexrc.getString());
1165 options_ = lexrc.getString();
1176 bool LyXTextClass::hasLayout(string const & name) const
1178 return find_if(layoutlist.begin(), layoutlist.end(),
1179 lyx::compare_memfun(&LyXLayout::name, name))
1180 != layoutlist.end();
1184 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1186 LayoutList::const_iterator cit =
1187 find_if(layoutlist.begin(),
1189 lyx::compare_memfun(&LyXLayout::name, name));
1190 lyx::Assert(cit != layoutlist.end()); // we require the name to exist
1195 LyXLayout & LyXTextClass::GetLayout(string const & name)
1197 LayoutList::iterator it =
1198 find_if(layoutlist.begin(),
1200 lyx::compare_memfun(&LyXLayout::name, name));
1201 lyx::Assert(it != layoutlist.end()); // we require the name to exist
1206 bool LyXTextClass::delete_layout(string const & name)
1208 LayoutList::iterator it =
1209 remove_if(layoutlist.begin(), layoutlist.end(),
1210 lyx::compare_memfun(&LyXLayout::name, name));
1211 LayoutList::iterator end = layoutlist.end();
1212 bool const ret = (it != end);
1213 layoutlist.erase(it, end);
1218 // Load textclass info if not loaded yet
1219 void LyXTextClass::load()
1224 string const real_file = LibFileSearch("layouts", name_, "layout");
1226 if (Read(real_file)) {
1227 lyxerr << "Error reading `"
1228 << MakeDisplayPath(real_file)
1229 << "'\n(Check `" << name_
1230 << "')\nCheck your installation and "
1231 "try Options/Reconfigure..." << endl;
1237 //////////////////////////////////////////
1239 // Gets textclass number from name
1240 pair<bool, textclass_type> const
1241 LyXTextClassList::NumberOfClass(string const & textclass) const
1243 ClassList::const_iterator cit =
1244 find_if(classlist.begin(), classlist.end(),
1245 lyx::compare_memfun(&LyXTextClass::name, textclass));
1246 return cit != classlist.end() ?
1247 make_pair(true, textclass_type(cit - classlist.begin())) :
1248 make_pair(false, textclass_type(0));
1252 // Gets layout structure from style number and textclass number
1254 LyXTextClassList::Style(textclass_type textclass,
1255 layout_type layout) const
1257 classlist[textclass].load();
1258 if (layout < classlist[textclass].numLayouts())
1259 return classlist[textclass][layout];
1260 return classlist[textclass][0];
1264 // Gets layout number from name and textclass number
1265 pair<bool, layout_type> const
1266 LyXTextClassList::NumberOfLayout(textclass_type textclass,
1267 string const & name) const
1269 classlist[textclass].load();
1270 for (unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1271 if (classlist[textclass][i].name() == name)
1272 return make_pair(true, i);
1274 if (name == "dummy")
1275 return make_pair(true, layout_type(LYX_DUMMY_LAYOUT));
1276 return make_pair(false, layout_type(0)); // not found
1280 // Gets a layout (style) name from layout number and textclass number
1282 LyXTextClassList::NameOfLayout(textclass_type textclass,
1283 layout_type layout) const
1285 static string const dummy("dummy");
1286 classlist[textclass].load();
1287 if (layout < classlist[textclass].numLayouts())
1288 return classlist[textclass][layout].name();
1293 // Gets a textclass name from number
1295 LyXTextClassList::NameOfClass(textclass_type number) const
1297 static string const dummy("dummy");
1298 if (classlist.empty()) {
1301 lyx::Assert(number < classlist.size());
1302 return classlist[number].name();
1306 // Gets a textclass latexname from number
1308 LyXTextClassList::LatexnameOfClass(textclass_type number) const
1310 static string const dummy("dummy");
1311 classlist[number].load();
1312 if (classlist.empty()) {
1315 lyx::Assert(number < classlist.size());
1316 return classlist[number].latexname();
1320 // Gets a textclass description from number
1322 LyXTextClassList::DescOfClass(textclass_type number) const
1324 static string const dummy("dummy");
1325 if (classlist.empty()) {
1328 lyx::Assert(number < classlist.size());
1329 return classlist[number].description();
1333 // Gets a textclass structure from number
1334 LyXTextClass const &
1335 LyXTextClassList::TextClass(textclass_type textclass) const
1337 classlist[textclass].load();
1338 if (textclass < classlist.size())
1339 return classlist[textclass];
1341 return classlist[0];
1345 void LyXTextClassList::Add(LyXTextClass const & t)
1347 classlist.push_back(t);
1351 // used when sorting the textclass list.
1352 class less_textclass_desc {
1354 int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1355 return tc1.description() < tc2.description();
1360 // Reads LyX textclass definitions according to textclass config file
1361 bool LyXTextClassList::Read ()
1364 string real_file = LibFileSearch("", "textclass.lst");
1365 lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1366 << real_file << "'" << endl;
1368 if (real_file.empty()) {
1369 lyxerr << "LyXTextClassList::Read: unable to find "
1370 "textclass file `" << MakeDisplayPath(real_file, 1000)
1371 << "'. Exiting." << endl;
1373 Alert::alert(_("LyX wasn't able to find its layout descriptions!"),
1374 _("Check that the file \"textclass.lst\""),
1375 _("is installed correctly. Sorry, has to exit :-("));
1377 // This causes LyX to end... Not a desirable behaviour. Lgb
1378 // What do you propose? That the user gets a file dialog
1379 // and is allowed to hunt for the file? (Asger)
1380 // more that we have a layout for minimal.cls statically
1381 // compiled in... (Lgb)
1384 if (!lex.setFile(real_file)) {
1385 lyxerr << "LyXTextClassList::Read: "
1386 "lyxlex was not able to set file: "
1387 << real_file << endl;
1391 lyxerr << "LyXTextClassList::Read: unable to open "
1392 "textclass file `" << MakeDisplayPath(real_file, 1000)
1393 << "'\nCheck your installation. LyX can't continue."
1398 bool finished = false;
1399 // Parse config-file
1400 lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1401 while (lex.isOK() && !finished) {
1402 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1403 switch (lex.lex()) {
1404 case LyXLex::LEX_FEOF:
1408 string const fname = lex.getString();
1409 lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1411 string const clname = lex.getString();
1412 lyxerr[Debug::TCLASS]
1413 << "Clname: " << clname << endl;
1415 string const desc = lex.getString();
1416 lyxerr[Debug::TCLASS]
1417 << "Desc: " << desc << endl;
1418 // This code is run when we have
1419 // fname, clname and desc
1420 LyXTextClass tmpl(fname,
1424 debugging(Debug::TCLASS)) {
1432 lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1434 if (classlist.empty()) {
1435 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1437 Alert::alert(_("LyX wasn't able to find any layout description!"),
1438 _("Check the contents of the file \"textclass.lst\""),
1439 _("Sorry, has to exit :-("));
1442 // Ok everything loaded ok, now sort the list.
1443 sort(classlist.begin(), classlist.end(), less_textclass_desc());
1449 Returns false if this fails
1451 bool LyXTextClassList::Load(textclass_type number) const
1454 if (number < classlist.size()) {
1455 classlist[number].load();
1456 if (classlist[number].numLayouts() == 0) {
1466 std::ostream & operator<<(std::ostream & os, LyXTextClass::PageSides p)
1469 case LyXTextClass::OneSide:
1472 case LyXTextClass::TwoSides: