1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 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,
99 // This table is sorted alphabetically [asierra 30March96]
100 static keyword_item layoutTags[] = {
101 { "align", LT_ALIGN },
102 { "alignpossible", LT_ALIGNPOSSIBLE },
103 { "bottomsep", LT_BOTTOMSEP },
104 { "copystyle", LT_COPYSTYLE },
106 { "endlabeltype", LT_ENDLABELTYPE },
107 { "fill_bottom", LT_FILL_BOTTOM },
108 { "fill_top", LT_FILL_TOP },
110 { "freespacing", LT_FREE_SPACING },
111 { "intitle", LT_INTITLE },
112 { "itemsep", LT_ITEMSEP },
113 { "keepempty", LT_KEEPEMPTY },
114 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
115 { "labelfont", LT_LABELFONT },
116 { "labelindent", LT_LABELINDENT },
117 { "labelsep", LT_LABELSEP },
118 { "labelstring", LT_LABELSTRING },
119 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
120 { "labeltype", LT_LABELTYPE },
121 { "latexname", LT_LATEXNAME },
122 { "latexparam", LT_LATEXPARAM },
123 { "latextype", LT_LATEXTYPE },
124 { "leftmargin", LT_LEFTMARGIN },
125 { "margin", LT_MARGIN },
126 { "needprotect", LT_NEED_PROTECT },
127 { "newline", LT_NEWLINE },
128 { "nextnoindent", LT_NEXTNOINDENT },
129 { "obsoletedby", LT_OBSOLETEDBY },
130 { "parindent", LT_PARINDENT },
131 { "parsep", LT_PARSEP },
132 { "parskip", LT_PARSKIP },
133 { "preamble", LT_PREAMBLE },
134 { "rightmargin", LT_RIGHTMARGIN },
135 { "spacing", LT_SPACING },
136 { "textfont", LT_TEXTFONT },
137 { "topsep", LT_TOPSEP }
142 /////////////////////
144 // Constructor for layout
145 LyXLayout::LyXLayout ()
147 margintype = MARGIN_STATIC;
148 latextype = LATEX_PARAGRAPH;
152 font = LyXFont(LyXFont::ALL_INHERIT);
153 labelfont = LyXFont(LyXFont::ALL_INHERIT);
154 resfont = LyXFont(LyXFont::ALL_SANE);
155 reslabelfont = LyXFont(LyXFont::ALL_SANE);
156 nextnoindent = false;
161 labelbottomsep = 0.0;
163 align = LYX_ALIGN_BLOCK;
164 alignpossible = LYX_ALIGN_BLOCK;
165 labeltype = LABEL_NO_LABEL;
166 endlabeltype = END_LABEL_NO_LABEL;
167 // Should or should not. That is the question.
168 // spacing.set(Spacing::OneHalf);
171 newline_allowed = true;
172 free_spacing = false;
176 // Reads a layout definition from file
177 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
180 // This table is sorted alphabetically [asierra 30March96]
181 keyword_item layoutTags[] = {
182 { "align", LT_ALIGN },
183 { "alignpossible", LT_ALIGNPOSSIBLE },
184 { "bottomsep", LT_BOTTOMSEP },
185 { "copystyle", LT_COPYSTYLE },
187 { "endlabeltype", LT_ENDLABELTYPE },
188 { "fill_bottom", LT_FILL_BOTTOM },
189 { "fill_top", LT_FILL_TOP },
191 { "freespacing", LT_FREE_SPACING },
192 { "intitle", LT_INTITLE },
193 { "itemsep", LT_ITEMSEP },
194 { "keepempty", LT_KEEPEMPTY },
195 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
196 { "labelfont", LT_LABELFONT },
197 { "labelindent", LT_LABELINDENT },
198 { "labelsep", LT_LABELSEP },
199 { "labelstring", LT_LABELSTRING },
200 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
201 { "labeltype", LT_LABELTYPE },
202 { "latexname", LT_LATEXNAME },
203 { "latexparam", LT_LATEXPARAM },
204 { "latextype", LT_LATEXTYPE },
205 { "leftmargin", LT_LEFTMARGIN },
206 { "margin", LT_MARGIN },
207 { "needprotect", LT_NEED_PROTECT },
208 { "newline", LT_NEWLINE },
209 { "nextnoindent", LT_NEXTNOINDENT },
210 { "obsoletedby", LT_OBSOLETEDBY },
211 { "parindent", LT_PARINDENT },
212 { "parsep", LT_PARSEP },
213 { "parskip", LT_PARSKIP },
214 { "preamble", LT_PREAMBLE },
215 { "rightmargin", LT_RIGHTMARGIN },
216 { "spacing", LT_SPACING },
217 { "textfont", LT_TEXTFONT },
218 { "topsep", LT_TOPSEP }
222 bool finished = false;
223 lexrc.pushTable(layoutTags, LT_INTITLE);
224 // parse style section
225 while (!finished && lexrc.IsOK() && !error) {
226 int le = lexrc.lex();
227 // See comment in lyxrc.C.
229 case LyXLex::LEX_FEOF:
232 case LyXLex::LEX_UNDEF: // parse error
233 lexrc.printError("Unknown layout tag `$$Token'");
238 switch(static_cast<LayoutTags>(le)) {
239 case LT_END: // end of structure
243 case LT_COPYSTYLE: // initialize with a known style
245 if (tclass.hasLayout(lexrc.GetString())) {
246 string tmpname = name_;
247 this->operator= (tclass.GetLayout(lexrc.GetString()));
250 lexrc.printError("Cannot copy known "
256 case LT_OBSOLETEDBY: // replace with a known style
258 if (tclass.hasLayout(lexrc.GetString())) {
259 string tmpname = name_;
260 this->operator= (tclass.GetLayout(lexrc.GetString()));
262 if (obsoleted_by().empty())
263 obsoleted_by_ = lexrc.GetString();
265 lexrc.printError("Cannot replace with"
272 case LT_MARGIN: // Margin style definition.
276 case LT_LATEXTYPE: // Latex style definition.
277 readLatexType(lexrc);
281 intitle = lexrc.next() && lexrc.GetInteger();
284 case LT_NEED_PROTECT:
285 needprotect = lexrc.next() && lexrc.GetInteger();
289 keepempty = lexrc.next() && lexrc.GetInteger();
302 labelfont.lyxRead(lexrc);
305 case LT_NEXTNOINDENT: // Indent next paragraph?
306 if (lexrc.next() && lexrc.GetInteger())
309 nextnoindent = false;
314 latexname_ = lexrc.GetString();
319 latexparam_ = lexrc.GetString();
323 preamble_ = lexrc.getLongString("EndPreamble");
327 readLabelType(lexrc);
330 case LT_ENDLABELTYPE:
331 readEndLabelType(lexrc);
334 case LT_LEFTMARGIN: // left margin type
336 leftmargin = lexrc.GetString();
339 case LT_RIGHTMARGIN: // right margin type
341 rightmargin = lexrc.GetString();
344 case LT_LABELINDENT: // label indenting flag
346 labelindent = lexrc.GetString();
349 case LT_PARINDENT: // paragraph indent. flag
351 parindent = lexrc.GetString();
354 case LT_PARSKIP: // paragraph skip size
356 parskip = lexrc.GetFloat();
359 case LT_ITEMSEP: // item separation size
361 itemsep = lexrc.GetFloat();
364 case LT_TOPSEP: // top separation size
366 topsep = lexrc.GetFloat();
369 case LT_BOTTOMSEP: // bottom separation size
371 bottomsep = lexrc.GetFloat();
374 case LT_LABEL_BOTTOMSEP: // label bottom separation size
376 labelbottomsep = lexrc.GetFloat();
379 case LT_LABELSEP: // label separator
381 labelsep = subst(lexrc.GetString(), 'x', ' ');
385 case LT_PARSEP: // par. separation size
387 parsep = lexrc.GetFloat();
390 case LT_FILL_TOP: // fill top flag
392 fill_top = lexrc.GetInteger();
395 case LT_FILL_BOTTOM: // fill bottom flag
397 fill_bottom = lexrc.GetInteger();
400 case LT_NEWLINE: // newlines allowed?
402 newline_allowed = lexrc.GetInteger();
405 case LT_ALIGN: // paragraph align
408 case LT_ALIGNPOSSIBLE: // paragraph allowed align
409 readAlignPossible(lexrc);
412 case LT_LABELSTRING: // label string definition
414 labelstring_ = lexrc.GetString();
417 case LT_LABELSTRING_APPENDIX: // label string appendix definition
419 labelstring_appendix_ = lexrc.GetString();
422 case LT_FREE_SPACING: // Allow for free spacing.
424 free_spacing = lexrc.GetInteger();
427 case LT_SPACING: // setspace.sty
447 static keyword_item alignTags[] = {
448 { "block", AT_BLOCK },
449 { "center", AT_CENTER },
450 { "layout", AT_LAYOUT },
452 { "right", AT_RIGHT }
456 void LyXLayout::readAlign(LyXLex & lexrc)
459 keyword_item alignTags[] = {
460 { "block", AT_BLOCK },
461 { "center", AT_CENTER },
462 { "layout", AT_LAYOUT },
464 { "right", AT_RIGHT }
467 pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
468 int le = lexrc.lex();
470 case LyXLex::LEX_UNDEF:
471 lexrc.printError("Unknown alignment `$$Token'");
475 switch(static_cast<AlignTags>(le)) {
477 align = LYX_ALIGN_BLOCK;
480 align = LYX_ALIGN_LEFT;
483 align = LYX_ALIGN_RIGHT;
486 align = LYX_ALIGN_CENTER;
489 align = LYX_ALIGN_LAYOUT;
495 void LyXLayout::readAlignPossible(LyXLex & lexrc)
498 keyword_item alignTags[] = {
499 { "block", AT_BLOCK },
500 { "center", AT_CENTER },
501 { "layout", AT_LAYOUT },
503 { "right", AT_RIGHT }
506 lexrc.pushTable(alignTags, AT_LAYOUT);
507 alignpossible = LYX_ALIGN_NONE;
508 int lineno = lexrc.GetLineNo();
510 int le = lexrc.lex();
512 case LyXLex::LEX_UNDEF:
513 lexrc.printError("Unknown alignment `$$Token'");
517 switch (static_cast<AlignTags>(le)) {
519 alignpossible |= LYX_ALIGN_BLOCK;
522 alignpossible |= LYX_ALIGN_LEFT;
525 alignpossible |= LYX_ALIGN_RIGHT;
528 alignpossible |= LYX_ALIGN_CENTER;
531 alignpossible |= LYX_ALIGN_LAYOUT;
534 } while (lineno == lexrc.GetLineNo());
543 LA_CENTERED_TOP_ENVIRONMENT,
548 LA_COUNTER_SUBSECTION,
549 LA_COUNTER_SUBSUBSECTION,
550 LA_COUNTER_PARAGRAPH,
551 LA_COUNTER_SUBPARAGRAPH,
561 static keyword_item labelTypeTags[] = {
562 { "bibliography", LA_BIBLIO },
563 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
564 { "counter_chapter", LA_COUNTER_CHAPTER },
565 { "counter_enumi", LA_COUNTER_ENUMI },
566 { "counter_enumii", LA_COUNTER_ENUMII },
567 { "counter_enumiii", LA_COUNTER_ENUMIII },
568 { "counter_enumiv", LA_COUNTER_ENUMIV },
569 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
570 { "counter_section", LA_COUNTER_SECTION },
571 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
572 { "counter_subsection", LA_COUNTER_SUBSECTION },
573 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
574 { "manual", LA_MANUAL },
575 { "no_label", LA_NO_LABEL },
576 { "sensitive", LA_SENSITIVE },
577 { "static", LA_STATIC },
578 { "top_environment", LA_TOP_ENVIRONMENT }
583 void LyXLayout::readLabelType(LyXLex & lexrc)
586 keyword_item labelTypeTags[] = {
587 { "bibliography", LA_BIBLIO },
588 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
589 { "counter_chapter", LA_COUNTER_CHAPTER },
590 { "counter_enumi", LA_COUNTER_ENUMI },
591 { "counter_enumii", LA_COUNTER_ENUMII },
592 { "counter_enumiii", LA_COUNTER_ENUMIII },
593 { "counter_enumiv", LA_COUNTER_ENUMIV },
594 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
595 { "counter_section", LA_COUNTER_SECTION },
596 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
597 { "counter_subsection", LA_COUNTER_SUBSECTION },
598 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
599 { "manual", LA_MANUAL },
600 { "no_label", LA_NO_LABEL },
601 { "sensitive", LA_SENSITIVE },
602 { "static", LA_STATIC },
603 { "top_environment", LA_TOP_ENVIRONMENT }
606 pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
607 int le = lexrc.lex();
609 case LyXLex::LEX_UNDEF:
610 lexrc.printError("Unknown labeltype tag `$$Token'");
614 switch (static_cast<LabelTypeTags>(le)) {
616 labeltype = LABEL_NO_LABEL;
619 labeltype = LABEL_MANUAL;
621 case LA_TOP_ENVIRONMENT:
622 labeltype = LABEL_TOP_ENVIRONMENT;
624 case LA_CENTERED_TOP_ENVIRONMENT:
625 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
628 labeltype = LABEL_STATIC;
631 labeltype = LABEL_SENSITIVE;
633 case LA_COUNTER_CHAPTER:
634 labeltype = LABEL_COUNTER_CHAPTER;
636 case LA_COUNTER_SECTION:
637 labeltype = LABEL_COUNTER_SECTION;
639 case LA_COUNTER_SUBSECTION:
640 labeltype = LABEL_COUNTER_SUBSECTION;
642 case LA_COUNTER_SUBSUBSECTION:
643 labeltype = LABEL_COUNTER_SUBSUBSECTION;
645 case LA_COUNTER_PARAGRAPH:
646 labeltype = LABEL_COUNTER_PARAGRAPH;
648 case LA_COUNTER_SUBPARAGRAPH:
649 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
651 case LA_COUNTER_ENUMI:
652 labeltype = LABEL_COUNTER_ENUMI;
654 case LA_COUNTER_ENUMII:
655 labeltype = LABEL_COUNTER_ENUMII;
657 case LA_COUNTER_ENUMIII:
658 labeltype = LABEL_COUNTER_ENUMIII;
660 case LA_COUNTER_ENUMIV:
661 labeltype = LABEL_COUNTER_ENUMIV;
664 labeltype = LABEL_BIBLIO;
669 static keyword_item endlabelTypeTags[] = {
670 { "box", END_LABEL_BOX },
671 { "filled_box", END_LABEL_FILLED_BOX },
672 { "no_label", END_LABEL_NO_LABEL }
675 void LyXLayout::readEndLabelType(LyXLex & lexrc)
677 pushpophelper pph(lexrc, endlabelTypeTags,
678 END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
679 int le = lexrc.lex();
681 case LyXLex::LEX_UNDEF:
682 lexrc.printError("Unknown labeltype tag `$$Token'");
685 case END_LABEL_FILLED_BOX:
686 case END_LABEL_NO_LABEL:
687 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
690 lyxerr << "Unhandled value " << le
691 << " in LyXLayout::readEndLabelType." << endl;
697 static keyword_item marginTags[] = {
698 { "dynamic", MARGIN_DYNAMIC },
699 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
700 { "manual", MARGIN_MANUAL },
701 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
702 { "static", MARGIN_STATIC }
706 void LyXLayout::readMargin(LyXLex & lexrc)
709 keyword_item marginTags[] = {
710 { "dynamic", MARGIN_DYNAMIC },
711 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
712 { "manual", MARGIN_MANUAL },
713 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
714 { "static", MARGIN_STATIC }
717 pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
719 int le = lexrc.lex();
721 case LyXLex::LEX_UNDEF:
722 lexrc.printError("Unknown margin type tag `$$Token'");
727 case MARGIN_FIRST_DYNAMIC:
728 case MARGIN_RIGHT_ADDRESS_BOX:
729 margintype = static_cast<LYX_MARGIN_TYPE>(le);
732 lyxerr << "Unhandled value " << le
733 << " in LyXLayout::readMargin." << endl;
740 static keyword_item latexTypeTags[] = {
741 { "command", LATEX_COMMAND },
742 { "environment", LATEX_ENVIRONMENT },
743 { "item_environment", LATEX_ITEM_ENVIRONMENT },
744 { "list_environment", LATEX_LIST_ENVIRONMENT },
745 { "paragraph", LATEX_PARAGRAPH }
750 void LyXLayout::readLatexType(LyXLex & lexrc)
753 keyword_item latexTypeTags[] = {
754 { "command", LATEX_COMMAND },
755 { "environment", LATEX_ENVIRONMENT },
756 { "item_environment", LATEX_ITEM_ENVIRONMENT },
757 { "list_environment", LATEX_LIST_ENVIRONMENT },
758 { "paragraph", LATEX_PARAGRAPH }
761 pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
762 int le = lexrc.lex();
764 case LyXLex::LEX_UNDEF:
765 lexrc.printError("Unknown latextype tag `$$Token'");
767 case LATEX_PARAGRAPH:
769 case LATEX_ENVIRONMENT:
770 case LATEX_ITEM_ENVIRONMENT:
771 case LATEX_LIST_ENVIRONMENT:
772 latextype = static_cast<LYX_LATEX_TYPES>(le);
775 lyxerr << "Unhandled value " << le
776 << " in LyXLayout::readLatexType." << endl;
783 ST_SPACING_SINGLE = 1,
791 static keyword_item spacingTags[] = {
792 {"double", ST_SPACING_DOUBLE },
793 {"onehalf", ST_SPACING_ONEHALF },
794 {"other", ST_OTHER },
795 {"single", ST_SPACING_SINGLE }
800 void LyXLayout::readSpacing(LyXLex & lexrc)
803 keyword_item spacingTags[] = {
804 {"double", ST_SPACING_DOUBLE },
805 {"onehalf", ST_SPACING_ONEHALF },
806 {"other", ST_OTHER },
807 {"single", ST_SPACING_SINGLE }
810 pushpophelper pph(lexrc, spacingTags, ST_OTHER);
811 int le = lexrc.lex();
813 case LyXLex::LEX_UNDEF:
814 lexrc.printError("Unknown spacing token `$$Token'");
818 switch(static_cast<SpacingTags>(le)) {
819 case ST_SPACING_SINGLE:
820 spacing.set(Spacing::Single);
822 case ST_SPACING_ONEHALF:
823 spacing.set(Spacing::Onehalf);
825 case ST_SPACING_DOUBLE:
826 spacing.set(Spacing::Double);
830 spacing.set(Spacing::Other, lexrc.GetFloat());
836 /* ******************************************************************* */
838 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
840 : name_(fn), latexname_(cln), description_(desc)
847 pagestyle_ = "default";
848 maxcounter_ = LABEL_COUNTER_CHAPTER;
849 defaultfont_ = LyXFont(LyXFont::ALL_SANE);
850 opt_fontsize_ = "10|11|12";
851 opt_pagestyle_ = "empty|plain|headings|fancy";
857 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
859 lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
860 if (!lay.Read(lexrc, *this)) {
862 lay.resfont = lay.font;
863 lay.resfont.realize(defaultfont());
864 lay.reslabelfont = lay.labelfont;
865 lay.reslabelfont.realize(defaultfont());
866 return false; // no errors
868 lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
896 static keyword_item textClassTags[] = {
897 { "classoptions", TC_CLASSOPTIONS },
898 { "columns", TC_COLUMNS },
899 { "defaultfont", TC_DEFAULTFONT },
900 { "input", TC_INPUT },
901 { "leftmargin", TC_LEFTMARGIN },
902 { "maxcounter", TC_MAXCOUNTER },
903 { "nostyle", TC_NOSTYLE },
904 { "outputtype", TC_OUTPUTTYPE },
905 { "pagestyle", TC_PAGESTYLE },
906 { "preamble", TC_PREAMBLE },
907 { "providesamsmath", TC_PROVIDESAMSMATH },
908 { "providesmakeidx", TC_PROVIDESMAKEIDX },
909 { "providesurl", TC_PROVIDESURL },
910 { "rightmargin", TC_RIGHTMARGIN },
911 { "secnumdepth", TC_SECNUMDEPTH },
912 { "sides", TC_SIDES },
913 { "style", TC_STYLE },
914 { "tocdepth", TC_TOCDEPTH }
919 // Reads a textclass structure from file.
920 bool LyXTextClass::Read(string const & filename, bool merge)
923 keyword_item textClassTags[] = {
924 { "classoptions", TC_CLASSOPTIONS },
925 { "columns", TC_COLUMNS },
926 { "defaultfont", TC_DEFAULTFONT },
927 { "input", TC_INPUT },
928 { "leftmargin", TC_LEFTMARGIN },
929 { "maxcounter", TC_MAXCOUNTER },
930 { "nostyle", TC_NOSTYLE },
931 { "outputtype", TC_OUTPUTTYPE },
932 { "pagestyle", TC_PAGESTYLE },
933 { "preamble", TC_PREAMBLE },
934 { "providesamsmath", TC_PROVIDESAMSMATH },
935 { "providesmakeidx", TC_PROVIDESMAKEIDX },
936 { "providesurl", TC_PROVIDESURL },
937 { "rightmargin", TC_RIGHTMARGIN },
938 { "secnumdepth", TC_SECNUMDEPTH },
939 { "sides", TC_SIDES },
940 { "style", TC_STYLE },
941 { "tocdepth", TC_TOCDEPTH }
945 lyxerr[Debug::TCLASS] << "Reading textclass "
946 << MakeDisplayPath(filename)
949 lyxerr[Debug::TCLASS] << "Reading input file "
950 << MakeDisplayPath(filename)
953 LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
956 lexrc.setFile(filename);
957 if (!lexrc.IsOK()) error = true;
960 while (lexrc.IsOK() && !error) {
961 int le = lexrc.lex();
963 case LyXLex::LEX_FEOF:
966 case LyXLex::LEX_UNDEF:
967 lexrc.printError("Unknown TextClass tag `$$Token'");
972 switch(static_cast<TextClassTags>(le)) {
973 case TC_OUTPUTTYPE: // output type definition
974 readOutputType(lexrc);
977 case TC_INPUT: // Include file
979 string tmp = LibFileSearch("layouts",
983 if (Read(tmp, true)) {
984 lexrc.printError("Error reading input"
993 string name = subst(lexrc.GetString(),
995 if (hasLayout(name)) {
996 LyXLayout & lay = GetLayout(name);
997 error = do_readStyle(lexrc, lay);
1001 if (!(error = do_readStyle(lexrc, lay)))
1002 layoutlist.push_back(lay);
1006 lexrc.printError("No name given for style: `$$Token'.");
1013 string style = subst(lexrc.GetString(),
1015 if (!delete_layout(style))
1016 lexrc.printError("Cannot delete style"
1023 columns_ = lexrc.GetInteger();
1028 switch(lexrc.GetInteger()) {
1029 case 1: sides_ = OneSide; break;
1030 case 2: sides_ = TwoSides; break;
1032 lyxerr << "Impossible number of page"
1033 " sides, setting to one."
1043 pagestyle_ = strip(lexrc.GetString());
1046 case TC_DEFAULTFONT:
1047 defaultfont_.lyxRead(lexrc);
1048 if (!defaultfont_.resolved()) {
1049 lexrc.printError("Warning: defaultfont should "
1050 "be fully instantiated!");
1051 defaultfont_.realize(LyXFont::ALL_SANE);
1056 readMaxCounter(lexrc);
1059 case TC_SECNUMDEPTH:
1061 secnumdepth_ = lexrc.GetInteger();
1066 tocdepth_ = lexrc.GetInteger();
1069 // First step to support options
1070 case TC_CLASSOPTIONS:
1071 readClassOptions(lexrc);
1075 preamble_ = lexrc.getLongString("EndPreamble");
1078 case TC_PROVIDESAMSMATH:
1079 if (lexrc.next() && lexrc.GetInteger())
1080 provides_ |= amsmath;
1083 case TC_PROVIDESMAKEIDX:
1084 if (lexrc.next() && lexrc.GetInteger())
1085 provides_ |= makeidx;
1088 case TC_PROVIDESURL:
1089 if (lexrc.next() && lexrc.GetInteger())
1093 case TC_LEFTMARGIN: // left margin type
1095 leftmargin_ = lexrc.GetString();
1098 case TC_RIGHTMARGIN: // right margin type
1100 rightmargin_ = lexrc.GetString();
1105 if (!merge) { // we are at top level here.
1106 lyxerr[Debug::TCLASS] << "Finished reading textclass "
1107 << MakeDisplayPath(filename)
1110 lyxerr[Debug::TCLASS] << "Finished reading input file "
1111 << MakeDisplayPath(filename)
1119 static keyword_item outputTypeTags[] = {
1120 { "docbook", DOCBOOK },
1122 { "linuxdoc", LINUXDOC },
1123 { "literate", LITERATE }
1127 void LyXTextClass::readOutputType(LyXLex & lexrc)
1130 keyword_item outputTypeTags[] = {
1131 { "docbook", DOCBOOK },
1133 { "linuxdoc", LINUXDOC },
1134 { "literate", LITERATE }
1137 pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1139 int le = lexrc.lex();
1141 case LyXLex::LEX_UNDEF:
1142 lexrc.printError("Unknown output type `$$Token'");
1148 outputType_ = static_cast<OutputType>(le);
1151 lyxerr << "Unhandled value " << le
1152 << " in LyXTextClass::readOutputType." << endl;
1159 enum MaxCounterTags {
1160 MC_COUNTER_CHAPTER = 1,
1162 MC_COUNTER_SUBSECTION,
1163 MC_COUNTER_SUBSUBSECTION,
1164 MC_COUNTER_PARAGRAPH,
1165 MC_COUNTER_SUBPARAGRAPH,
1174 static keyword_item maxCounterTags[] = {
1175 {"counter_chapter", MC_COUNTER_CHAPTER },
1176 {"counter_enumi", MC_COUNTER_ENUMI },
1177 {"counter_enumii", MC_COUNTER_ENUMII },
1178 {"counter_enumiii", MC_COUNTER_ENUMIII },
1179 {"counter_enumiv", MC_COUNTER_ENUMIV },
1180 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1181 {"counter_section", MC_COUNTER_SECTION },
1182 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1183 {"counter_subsection", MC_COUNTER_SUBSECTION },
1184 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1189 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1192 keyword_item maxCounterTags[] = {
1193 {"counter_chapter", MC_COUNTER_CHAPTER },
1194 {"counter_enumi", MC_COUNTER_ENUMI },
1195 {"counter_enumii", MC_COUNTER_ENUMII },
1196 {"counter_enumiii", MC_COUNTER_ENUMIII },
1197 {"counter_enumiv", MC_COUNTER_ENUMIV },
1198 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1199 {"counter_section", MC_COUNTER_SECTION },
1200 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1201 {"counter_subsection", MC_COUNTER_SUBSECTION },
1202 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1205 pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1206 int le = lexrc.lex();
1208 case LyXLex::LEX_UNDEF:
1209 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1213 switch (static_cast<MaxCounterTags>(le)) {
1214 case MC_COUNTER_CHAPTER:
1215 maxcounter_ = LABEL_COUNTER_CHAPTER;
1217 case MC_COUNTER_SECTION:
1218 maxcounter_ = LABEL_COUNTER_SECTION;
1220 case MC_COUNTER_SUBSECTION:
1221 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1223 case MC_COUNTER_SUBSUBSECTION:
1224 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1226 case MC_COUNTER_PARAGRAPH:
1227 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1229 case MC_COUNTER_SUBPARAGRAPH:
1230 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1232 case MC_COUNTER_ENUMI:
1233 maxcounter_ = LABEL_COUNTER_ENUMI;
1235 case MC_COUNTER_ENUMII:
1236 maxcounter_ = LABEL_COUNTER_ENUMII;
1238 case MC_COUNTER_ENUMIII:
1239 maxcounter_ = LABEL_COUNTER_ENUMIII;
1241 case MC_COUNTER_ENUMIV:
1242 maxcounter_ = LABEL_COUNTER_ENUMIV;
1248 enum ClassOptionsTags {
1257 static keyword_item classOptionsTags[] = {
1259 {"fontsize", CO_FONTSIZE },
1260 {"other", CO_OTHER },
1261 {"pagestyle", CO_PAGESTYLE }
1266 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1269 keyword_item classOptionsTags[] = {
1271 {"fontsize", CO_FONTSIZE },
1272 {"other", CO_OTHER },
1273 {"pagestyle", CO_PAGESTYLE }
1276 lexrc.pushTable(classOptionsTags, CO_END);
1277 bool getout = false;
1278 while (!getout && lexrc.IsOK()) {
1279 int le = lexrc.lex();
1281 case LyXLex::LEX_UNDEF:
1282 lexrc.printError("Unknown ClassOption tag `$$Token'");
1286 switch (static_cast<ClassOptionsTags>(le)) {
1289 opt_fontsize_ = strip(lexrc.GetString());
1293 opt_pagestyle_ = strip(lexrc.GetString());
1297 options_ = lexrc.GetString();
1308 bool LyXTextClass::hasLayout(string const & name) const
1310 for (LayoutList::const_iterator cit = layoutlist.begin();
1311 cit != layoutlist.end(); ++cit) {
1312 if ((*cit).name() == name)
1319 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1321 for (LayoutList::const_iterator cit = layoutlist.begin();
1322 cit != layoutlist.end(); ++cit) {
1323 if ((*cit).name() == name)
1326 Assert(false); // we actually require the name to exist.
1327 return layoutlist.front();
1331 LyXLayout & LyXTextClass::GetLayout(string const & name)
1333 for (LayoutList::iterator it = layoutlist.begin();
1334 it != layoutlist.end(); ++it) {
1335 if ((*it).name() == name)
1338 Assert(false); // we actually require the name to exist.
1339 return layoutlist.front();
1343 bool LyXTextClass::delete_layout (string const & name)
1345 for(LayoutList::iterator it = layoutlist.begin();
1346 it != layoutlist.end(); ++it) {
1347 if ((*it).name() == name) {
1348 layoutlist.erase(it);
1356 // Load textclass info if not loaded yet
1357 void LyXTextClass::load()
1362 string real_file = LibFileSearch("layouts", name_, "layout");
1364 if (Read(real_file)) {
1365 lyxerr << "Error reading `"
1366 << MakeDisplayPath(real_file)
1367 << "'\n(Check `" << name_
1368 << "')\nCheck your installation and "
1369 "try Options/Reconfigure..." << endl;
1375 //////////////////////////////////////////
1377 // Gets textclass number from name
1378 pair<bool, LyXTextClassList::size_type>
1379 LyXTextClassList::NumberOfClass(string const & textclass) const
1381 for (ClassList::const_iterator cit = classlist.begin();
1382 cit != classlist.end(); ++cit) {
1383 if ((*cit).name() == textclass)
1384 return make_pair(true, cit - classlist.begin());
1386 return make_pair(false, size_type(0));
1390 // Gets layout structure from style number and textclass number
1392 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1393 LyXTextClass::size_type layout) const
1395 classlist[textclass].load();
1396 if (layout < classlist[textclass].numLayouts())
1397 return classlist[textclass][layout];
1398 return classlist[textclass][0];
1402 // Gets layout number from name and textclass number
1403 pair<bool, LyXTextClass::size_type>
1404 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1405 string const & name) const
1407 classlist[textclass].load();
1408 for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1409 if (classlist[textclass][i].name() == name)
1410 return make_pair(true, i);
1412 if (name == "dummy")
1413 return make_pair(true, LYX_DUMMY_LAYOUT);
1414 return make_pair(false, LyXTextClass::LayoutList::size_type(0)); // not found
1418 // Gets a layout (style) name from layout number and textclass number
1420 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1421 LyXTextClass::size_type layout) const
1423 static string dummy("dummy");
1424 classlist[textclass].load();
1425 if (layout < classlist[textclass].numLayouts())
1426 return classlist[textclass][layout].name();
1431 // Gets a textclass name from number
1433 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1435 static string dummy("dummy");
1436 if (classlist.size() == 0) {
1439 Assert(number < classlist.size());
1440 return classlist[number].name();
1444 // Gets a textclass latexname from number
1446 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1448 static string dummy("dummy");
1449 classlist[number].load();
1450 if (classlist.size() == 0) {
1453 Assert(number < classlist.size());
1454 return classlist[number].latexname();
1458 // Gets a textclass description from number
1460 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1462 static string dummy("dummy");
1463 if (classlist.size() == 0) {
1466 Assert(number < classlist.size());
1467 return classlist[number].description();
1471 // Gets a textclass structure from number
1472 LyXTextClass const &
1473 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1475 classlist[textclass].load();
1476 if (textclass < classlist.size())
1477 return classlist[textclass];
1479 return classlist[0];
1483 void LyXTextClassList::Add(LyXTextClass const & t)
1485 classlist.push_back(t);
1489 // used when sorting the textclass list.
1490 class less_textclass_desc {
1492 int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1493 return tc1.description() < tc2.description();
1498 // Reads LyX textclass definitions according to textclass config file
1499 bool LyXTextClassList::Read ()
1502 string real_file = LibFileSearch("", "textclass.lst");
1503 lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1504 << real_file << "'" << endl;
1506 if (real_file.empty()) {
1507 lyxerr << "LyXTextClassList::Read: unable to find "
1508 "textclass file `" << MakeDisplayPath(real_file, 1000)
1509 << "'. Exiting." << endl;
1511 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1512 _("Check that the file \"textclass.lst\""),
1513 _("is installed correctly. Sorry, has to exit :-("));
1515 // This causes LyX to end... Not a desirable behaviour. Lgb
1516 // What do you propose? That the user gets a file dialog
1517 // and is allowed to hunt for the file? (Asger)
1518 // more that we have a layout for minimal.cls statically
1519 // compiled in... (Lgb)
1522 if (!lex.setFile(real_file)) {
1523 lyxerr << "LyXTextClassList::Read: "
1524 "lyxlex was not able to set file: "
1525 << real_file << endl;
1529 lyxerr << "LyXTextClassList::Read: unable to open "
1530 "textclass file `" << MakeDisplayPath(real_file, 1000)
1531 << "'\nCheck your installation. LyX can't continue."
1535 bool finished = false;
1536 string fname, clname, desc;
1537 // Parse config-file
1538 lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1539 while (lex.IsOK() && !finished) {
1540 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1541 switch (lex.lex()) {
1542 case LyXLex::LEX_FEOF:
1546 fname = lex.GetString();
1547 lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1549 clname = lex.GetString();
1550 lyxerr[Debug::TCLASS]
1551 << "Clname: " << clname << endl;
1553 desc = lex.GetString();
1554 lyxerr[Debug::TCLASS]
1555 << "Desc: " << desc << endl;
1556 // This code is run when we have
1557 // fname, clname and desc
1558 LyXTextClass tmpl(fname,
1562 debugging(Debug::TCLASS)) {
1570 lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1572 if (classlist.size() == 0) {
1573 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1575 WriteAlert(_("LyX wasn't able to find any layout description!"),
1576 _("Check the contents of the file \"textclass.lst\""),
1577 _("Sorry, has to exit :-("));
1580 // Ok everything loaded ok, now sort the list.
1581 sort(classlist.begin(), classlist.end(), less_textclass_desc());
1587 Returns false if this fails
1590 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1593 if (number < classlist.size()) {
1594 classlist[number].load();
1595 if (classlist[number].numLayouts() == 0) {