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
21 #include "support/filetools.h"
22 #include "lyx_gui_misc.h"
25 #include "support/LAssert.h"
32 // Global variable: textclass table.
33 LyXTextClassList textclasslist;
36 // Reads the style files
39 lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
41 if (!textclasslist.Read()) {
42 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
43 "during parsing.\n Exiting." << endl;
47 lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
51 // The order of the LayoutTags enum is no more important. [asierra300396]
62 //LT_ENVIRONMENT_DEFAULT,
78 LT_LABELSTRING_APPENDIX,
101 // This table is sorted alphabetically [asierra 30March96]
102 static keyword_item layoutTags[] = {
103 { "align", LT_ALIGN },
104 { "alignpossible", LT_ALIGNPOSSIBLE },
105 { "bottomsep", LT_BOTTOMSEP },
106 { "copystyle", LT_COPYSTYLE },
108 { "endlabeltype", LT_ENDLABELTYPE },
109 { "fill_bottom", LT_FILL_BOTTOM },
110 { "fill_top", LT_FILL_TOP },
112 { "freespacing", LT_FREE_SPACING },
113 { "intitle", LT_INTITLE },
114 { "itemsep", LT_ITEMSEP },
115 { "keepempty", LT_KEEPEMPTY },
116 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
117 { "labelfont", LT_LABELFONT },
118 { "labelindent", LT_LABELINDENT },
119 { "labelsep", LT_LABELSEP },
120 { "labelstring", LT_LABELSTRING },
121 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
122 { "labeltype", LT_LABELTYPE },
123 { "latexname", LT_LATEXNAME },
124 { "latexparam", LT_LATEXPARAM },
125 { "latextype", LT_LATEXTYPE },
126 { "leftmargin", LT_LEFTMARGIN },
127 { "margin", LT_MARGIN },
128 { "needprotect", LT_NEED_PROTECT },
129 { "newline", LT_NEWLINE },
130 { "nextnoindent", LT_NEXTNOINDENT },
131 { "obsoletedby", LT_OBSOLETEDBY },
132 { "parindent", LT_PARINDENT },
133 { "parsep", LT_PARSEP },
134 { "parskip", LT_PARSKIP },
135 { "preamble", LT_PREAMBLE },
136 { "rightmargin", LT_RIGHTMARGIN },
137 { "spacing", LT_SPACING },
138 { "textfont", LT_TEXTFONT },
139 { "topsep", LT_TOPSEP }
144 /////////////////////
146 // Constructor for layout
147 LyXLayout::LyXLayout ()
149 margintype = MARGIN_STATIC;
150 latextype = LATEX_PARAGRAPH;
154 font = LyXFont(LyXFont::ALL_INHERIT);
155 labelfont = LyXFont(LyXFont::ALL_INHERIT);
156 resfont = LyXFont(LyXFont::ALL_SANE);
157 reslabelfont = LyXFont(LyXFont::ALL_SANE);
158 nextnoindent = false;
163 labelbottomsep = 0.0;
165 align = LYX_ALIGN_BLOCK;
166 alignpossible = LYX_ALIGN_BLOCK;
167 labeltype = LABEL_NO_LABEL;
168 endlabeltype = END_LABEL_NO_LABEL;
169 // Should or should not. That is the question.
170 // spacing.set(Spacing::OneHalf);
173 newline_allowed = true;
174 free_spacing = false;
178 // Reads a layout definition from file
179 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
182 // This table is sorted alphabetically [asierra 30March96]
183 keyword_item layoutTags[] = {
184 { "align", LT_ALIGN },
185 { "alignpossible", LT_ALIGNPOSSIBLE },
186 { "bottomsep", LT_BOTTOMSEP },
187 { "copystyle", LT_COPYSTYLE },
189 { "endlabeltype", LT_ENDLABELTYPE },
190 { "fill_bottom", LT_FILL_BOTTOM },
191 { "fill_top", LT_FILL_TOP },
193 { "freespacing", LT_FREE_SPACING },
194 { "intitle", LT_INTITLE },
195 { "itemsep", LT_ITEMSEP },
196 { "keepempty", LT_KEEPEMPTY },
197 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
198 { "labelfont", LT_LABELFONT },
199 { "labelindent", LT_LABELINDENT },
200 { "labelsep", LT_LABELSEP },
201 { "labelstring", LT_LABELSTRING },
202 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
203 { "labeltype", LT_LABELTYPE },
204 { "latexname", LT_LATEXNAME },
205 { "latexparam", LT_LATEXPARAM },
206 { "latextype", LT_LATEXTYPE },
207 { "leftmargin", LT_LEFTMARGIN },
208 { "margin", LT_MARGIN },
209 { "needprotect", LT_NEED_PROTECT },
210 { "newline", LT_NEWLINE },
211 { "nextnoindent", LT_NEXTNOINDENT },
212 { "obsoletedby", LT_OBSOLETEDBY },
213 { "parindent", LT_PARINDENT },
214 { "parsep", LT_PARSEP },
215 { "parskip", LT_PARSKIP },
216 { "preamble", LT_PREAMBLE },
217 { "rightmargin", LT_RIGHTMARGIN },
218 { "spacing", LT_SPACING },
219 { "textfont", LT_TEXTFONT },
220 { "topsep", LT_TOPSEP }
224 bool finished = false;
225 lexrc.pushTable(layoutTags, LT_INTITLE);
226 // parse style section
227 while (!finished && lexrc.IsOK() && !error) {
228 int le = lexrc.lex();
229 // See comment in lyxrc.C.
231 case LyXLex::LEX_FEOF:
234 case LyXLex::LEX_UNDEF: // parse error
235 lexrc.printError("Unknown layout tag `$$Token'");
240 switch(static_cast<LayoutTags>(le)) {
241 case LT_END: // end of structure
245 case LT_COPYSTYLE: // initialize with a known style
247 if (tclass.hasLayout(lexrc.GetString())) {
248 string tmpname = name_;
249 this->operator= (tclass.GetLayout(lexrc.GetString()));
252 lexrc.printError("Cannot copy known "
258 case LT_OBSOLETEDBY: // replace with a known style
260 if (tclass.hasLayout(lexrc.GetString())) {
261 string tmpname = name_;
262 this->operator= (tclass.GetLayout(lexrc.GetString()));
264 if (obsoleted_by().empty())
265 obsoleted_by_ = lexrc.GetString();
267 lexrc.printError("Cannot replace with"
274 case LT_MARGIN: // Margin style definition.
278 case LT_LATEXTYPE: // Latex style definition.
279 readLatexType(lexrc);
283 intitle = lexrc.next() && lexrc.GetInteger();
286 case LT_NEED_PROTECT:
287 needprotect = lexrc.next() && lexrc.GetInteger();
291 keepempty = lexrc.next() && lexrc.GetInteger();
304 labelfont.lyxRead(lexrc);
307 case LT_NEXTNOINDENT: // Indent next paragraph?
308 if (lexrc.next() && lexrc.GetInteger())
311 nextnoindent = false;
316 latexname_ = lexrc.GetString();
321 latexparam_ = lexrc.GetString();
325 preamble_ = lexrc.getLongString("EndPreamble");
329 readLabelType(lexrc);
332 case LT_ENDLABELTYPE:
333 readEndLabelType(lexrc);
336 case LT_LEFTMARGIN: // left margin type
338 leftmargin = lexrc.GetString();
341 case LT_RIGHTMARGIN: // right margin type
343 rightmargin = lexrc.GetString();
346 case LT_LABELINDENT: // label indenting flag
348 labelindent = lexrc.GetString();
351 case LT_PARINDENT: // paragraph indent. flag
353 parindent = lexrc.GetString();
356 case LT_PARSKIP: // paragraph skip size
358 parskip = lexrc.GetFloat();
361 case LT_ITEMSEP: // item separation size
363 itemsep = lexrc.GetFloat();
366 case LT_TOPSEP: // top separation size
368 topsep = lexrc.GetFloat();
371 case LT_BOTTOMSEP: // bottom separation size
373 bottomsep = lexrc.GetFloat();
376 case LT_LABEL_BOTTOMSEP: // label bottom separation size
378 labelbottomsep = lexrc.GetFloat();
381 case LT_LABELSEP: // label separator
383 labelsep = subst(lexrc.GetString(), 'x', ' ');
387 case LT_PARSEP: // par. separation size
389 parsep = lexrc.GetFloat();
392 case LT_FILL_TOP: // fill top flag
394 fill_top = lexrc.GetInteger();
397 case LT_FILL_BOTTOM: // fill bottom flag
399 fill_bottom = lexrc.GetInteger();
402 case LT_NEWLINE: // newlines allowed?
404 newline_allowed = lexrc.GetInteger();
407 case LT_ALIGN: // paragraph align
410 case LT_ALIGNPOSSIBLE: // paragraph allowed align
411 readAlignPossible(lexrc);
414 case LT_LABELSTRING: // label string definition
416 labelstring_ = lexrc.GetString();
419 case LT_LABELSTRING_APPENDIX: // label string appendix definition
421 labelstring_appendix_ = lexrc.GetString();
424 case LT_FREE_SPACING: // Allow for free spacing.
426 free_spacing = lexrc.GetInteger();
429 case LT_SPACING: // setspace.sty
449 static keyword_item alignTags[] = {
450 { "block", AT_BLOCK },
451 { "center", AT_CENTER },
452 { "layout", AT_LAYOUT },
454 { "right", AT_RIGHT }
458 void LyXLayout::readAlign(LyXLex & lexrc)
461 keyword_item alignTags[] = {
462 { "block", AT_BLOCK },
463 { "center", AT_CENTER },
464 { "layout", AT_LAYOUT },
466 { "right", AT_RIGHT }
469 pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
470 int le = lexrc.lex();
472 case LyXLex::LEX_UNDEF:
473 lexrc.printError("Unknown alignment `$$Token'");
477 switch(static_cast<AlignTags>(le)) {
479 align = LYX_ALIGN_BLOCK;
482 align = LYX_ALIGN_LEFT;
485 align = LYX_ALIGN_RIGHT;
488 align = LYX_ALIGN_CENTER;
491 align = LYX_ALIGN_LAYOUT;
497 void LyXLayout::readAlignPossible(LyXLex & lexrc)
500 keyword_item alignTags[] = {
501 { "block", AT_BLOCK },
502 { "center", AT_CENTER },
503 { "layout", AT_LAYOUT },
505 { "right", AT_RIGHT }
508 lexrc.pushTable(alignTags, AT_LAYOUT);
509 alignpossible = LYX_ALIGN_NONE;
510 int lineno = lexrc.GetLineNo();
512 int le = lexrc.lex();
514 case LyXLex::LEX_UNDEF:
515 lexrc.printError("Unknown alignment `$$Token'");
519 switch (static_cast<AlignTags>(le)) {
521 alignpossible |= LYX_ALIGN_BLOCK;
524 alignpossible |= LYX_ALIGN_LEFT;
527 alignpossible |= LYX_ALIGN_RIGHT;
530 alignpossible |= LYX_ALIGN_CENTER;
533 alignpossible |= LYX_ALIGN_LAYOUT;
536 } while (lineno == lexrc.GetLineNo());
545 LA_CENTERED_TOP_ENVIRONMENT,
550 LA_COUNTER_SUBSECTION,
551 LA_COUNTER_SUBSUBSECTION,
552 LA_COUNTER_PARAGRAPH,
553 LA_COUNTER_SUBPARAGRAPH,
563 static keyword_item labelTypeTags[] = {
564 { "bibliography", LA_BIBLIO },
565 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
566 { "counter_chapter", LA_COUNTER_CHAPTER },
567 { "counter_enumi", LA_COUNTER_ENUMI },
568 { "counter_enumii", LA_COUNTER_ENUMII },
569 { "counter_enumiii", LA_COUNTER_ENUMIII },
570 { "counter_enumiv", LA_COUNTER_ENUMIV },
571 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
572 { "counter_section", LA_COUNTER_SECTION },
573 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
574 { "counter_subsection", LA_COUNTER_SUBSECTION },
575 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
576 { "manual", LA_MANUAL },
577 { "no_label", LA_NO_LABEL },
578 { "sensitive", LA_SENSITIVE },
579 { "static", LA_STATIC },
580 { "top_environment", LA_TOP_ENVIRONMENT }
585 void LyXLayout::readLabelType(LyXLex & lexrc)
588 keyword_item labelTypeTags[] = {
589 { "bibliography", LA_BIBLIO },
590 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
591 { "counter_chapter", LA_COUNTER_CHAPTER },
592 { "counter_enumi", LA_COUNTER_ENUMI },
593 { "counter_enumii", LA_COUNTER_ENUMII },
594 { "counter_enumiii", LA_COUNTER_ENUMIII },
595 { "counter_enumiv", LA_COUNTER_ENUMIV },
596 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
597 { "counter_section", LA_COUNTER_SECTION },
598 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
599 { "counter_subsection", LA_COUNTER_SUBSECTION },
600 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
601 { "manual", LA_MANUAL },
602 { "no_label", LA_NO_LABEL },
603 { "sensitive", LA_SENSITIVE },
604 { "static", LA_STATIC },
605 { "top_environment", LA_TOP_ENVIRONMENT }
608 pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
609 int le = lexrc.lex();
611 case LyXLex::LEX_UNDEF:
612 lexrc.printError("Unknown labeltype tag `$$Token'");
616 switch (static_cast<LabelTypeTags>(le)) {
618 labeltype = LABEL_NO_LABEL;
621 labeltype = LABEL_MANUAL;
623 case LA_TOP_ENVIRONMENT:
624 labeltype = LABEL_TOP_ENVIRONMENT;
626 case LA_CENTERED_TOP_ENVIRONMENT:
627 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
630 labeltype = LABEL_STATIC;
633 labeltype = LABEL_SENSITIVE;
635 case LA_COUNTER_CHAPTER:
636 labeltype = LABEL_COUNTER_CHAPTER;
638 case LA_COUNTER_SECTION:
639 labeltype = LABEL_COUNTER_SECTION;
641 case LA_COUNTER_SUBSECTION:
642 labeltype = LABEL_COUNTER_SUBSECTION;
644 case LA_COUNTER_SUBSUBSECTION:
645 labeltype = LABEL_COUNTER_SUBSUBSECTION;
647 case LA_COUNTER_PARAGRAPH:
648 labeltype = LABEL_COUNTER_PARAGRAPH;
650 case LA_COUNTER_SUBPARAGRAPH:
651 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
653 case LA_COUNTER_ENUMI:
654 labeltype = LABEL_COUNTER_ENUMI;
656 case LA_COUNTER_ENUMII:
657 labeltype = LABEL_COUNTER_ENUMII;
659 case LA_COUNTER_ENUMIII:
660 labeltype = LABEL_COUNTER_ENUMIII;
662 case LA_COUNTER_ENUMIV:
663 labeltype = LABEL_COUNTER_ENUMIV;
666 labeltype = LABEL_BIBLIO;
671 static keyword_item endlabelTypeTags[] = {
672 { "box", END_LABEL_BOX },
673 { "filled_box", END_LABEL_FILLED_BOX },
674 { "no_label", END_LABEL_NO_LABEL }
677 void LyXLayout::readEndLabelType(LyXLex & lexrc)
679 pushpophelper pph(lexrc, endlabelTypeTags,
680 END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
681 int le = lexrc.lex();
683 case LyXLex::LEX_UNDEF:
684 lexrc.printError("Unknown labeltype tag `$$Token'");
687 case END_LABEL_FILLED_BOX:
688 case END_LABEL_NO_LABEL:
689 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
692 lyxerr << "Unhandled value " << le
693 << " in LyXLayout::readEndLabelType." << endl;
699 static keyword_item marginTags[] = {
700 { "dynamic", MARGIN_DYNAMIC },
701 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
702 { "manual", MARGIN_MANUAL },
703 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
704 { "static", MARGIN_STATIC }
708 void LyXLayout::readMargin(LyXLex & lexrc)
711 keyword_item marginTags[] = {
712 { "dynamic", MARGIN_DYNAMIC },
713 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
714 { "manual", MARGIN_MANUAL },
715 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
716 { "static", MARGIN_STATIC }
719 pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
721 int le = lexrc.lex();
723 case LyXLex::LEX_UNDEF:
724 lexrc.printError("Unknown margin type tag `$$Token'");
729 case MARGIN_FIRST_DYNAMIC:
730 case MARGIN_RIGHT_ADDRESS_BOX:
731 margintype = static_cast<LYX_MARGIN_TYPE>(le);
734 lyxerr << "Unhandled value " << le
735 << " in LyXLayout::readMargin." << endl;
742 static keyword_item latexTypeTags[] = {
743 { "command", LATEX_COMMAND },
744 { "environment", LATEX_ENVIRONMENT },
745 { "item_environment", LATEX_ITEM_ENVIRONMENT },
746 { "list_environment", LATEX_LIST_ENVIRONMENT },
747 { "paragraph", LATEX_PARAGRAPH }
752 void LyXLayout::readLatexType(LyXLex & lexrc)
755 keyword_item latexTypeTags[] = {
756 { "command", LATEX_COMMAND },
757 { "environment", LATEX_ENVIRONMENT },
758 { "item_environment", LATEX_ITEM_ENVIRONMENT },
759 { "list_environment", LATEX_LIST_ENVIRONMENT },
760 { "paragraph", LATEX_PARAGRAPH }
763 pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
764 int le = lexrc.lex();
766 case LyXLex::LEX_UNDEF:
767 lexrc.printError("Unknown latextype tag `$$Token'");
769 case LATEX_PARAGRAPH:
771 case LATEX_ENVIRONMENT:
772 case LATEX_ITEM_ENVIRONMENT:
773 case LATEX_LIST_ENVIRONMENT:
774 latextype = static_cast<LYX_LATEX_TYPES>(le);
777 lyxerr << "Unhandled value " << le
778 << " in LyXLayout::readLatexType." << endl;
785 ST_SPACING_SINGLE = 1,
793 static keyword_item spacingTags[] = {
794 {"double", ST_SPACING_DOUBLE },
795 {"onehalf", ST_SPACING_ONEHALF },
796 {"other", ST_OTHER },
797 {"single", ST_SPACING_SINGLE }
802 void LyXLayout::readSpacing(LyXLex & lexrc)
805 keyword_item spacingTags[] = {
806 {"double", ST_SPACING_DOUBLE },
807 {"onehalf", ST_SPACING_ONEHALF },
808 {"other", ST_OTHER },
809 {"single", ST_SPACING_SINGLE }
812 pushpophelper pph(lexrc, spacingTags, ST_OTHER);
813 int le = lexrc.lex();
815 case LyXLex::LEX_UNDEF:
816 lexrc.printError("Unknown spacing token `$$Token'");
820 switch(static_cast<SpacingTags>(le)) {
821 case ST_SPACING_SINGLE:
822 spacing.set(Spacing::Single);
824 case ST_SPACING_ONEHALF:
825 spacing.set(Spacing::Onehalf);
827 case ST_SPACING_DOUBLE:
828 spacing.set(Spacing::Double);
832 spacing.set(Spacing::Other, lexrc.GetFloat());
838 /* ******************************************************************* */
840 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
842 : name_(fn), latexname_(cln), description_(desc)
849 pagestyle_ = "default";
850 maxcounter_ = LABEL_COUNTER_CHAPTER;
851 defaultfont_ = LyXFont(LyXFont::ALL_SANE);
852 opt_fontsize_ = "10|11|12";
853 opt_pagestyle_ = "empty|plain|headings|fancy";
859 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
861 lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
862 if (!lay.Read(lexrc, *this)) {
864 lay.resfont = lay.font;
865 lay.resfont.realize(defaultfont());
866 lay.reslabelfont = lay.labelfont;
867 lay.reslabelfont.realize(defaultfont());
868 return false; // no errors
870 lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
898 static keyword_item textClassTags[] = {
899 { "classoptions", TC_CLASSOPTIONS },
900 { "columns", TC_COLUMNS },
901 { "defaultfont", TC_DEFAULTFONT },
902 { "input", TC_INPUT },
903 { "leftmargin", TC_LEFTMARGIN },
904 { "maxcounter", TC_MAXCOUNTER },
905 { "nostyle", TC_NOSTYLE },
906 { "outputtype", TC_OUTPUTTYPE },
907 { "pagestyle", TC_PAGESTYLE },
908 { "preamble", TC_PREAMBLE },
909 { "providesamsmath", TC_PROVIDESAMSMATH },
910 { "providesmakeidx", TC_PROVIDESMAKEIDX },
911 { "providesurl", TC_PROVIDESURL },
912 { "rightmargin", TC_RIGHTMARGIN },
913 { "secnumdepth", TC_SECNUMDEPTH },
914 { "sides", TC_SIDES },
915 { "style", TC_STYLE },
916 { "tocdepth", TC_TOCDEPTH }
921 // Reads a textclass structure from file.
922 bool LyXTextClass::Read(string const & filename, bool merge)
925 keyword_item textClassTags[] = {
926 { "classoptions", TC_CLASSOPTIONS },
927 { "columns", TC_COLUMNS },
928 { "defaultfont", TC_DEFAULTFONT },
929 { "input", TC_INPUT },
930 { "leftmargin", TC_LEFTMARGIN },
931 { "maxcounter", TC_MAXCOUNTER },
932 { "nostyle", TC_NOSTYLE },
933 { "outputtype", TC_OUTPUTTYPE },
934 { "pagestyle", TC_PAGESTYLE },
935 { "preamble", TC_PREAMBLE },
936 { "providesamsmath", TC_PROVIDESAMSMATH },
937 { "providesmakeidx", TC_PROVIDESMAKEIDX },
938 { "providesurl", TC_PROVIDESURL },
939 { "rightmargin", TC_RIGHTMARGIN },
940 { "secnumdepth", TC_SECNUMDEPTH },
941 { "sides", TC_SIDES },
942 { "style", TC_STYLE },
943 { "tocdepth", TC_TOCDEPTH }
947 lyxerr[Debug::TCLASS] << "Reading textclass "
948 << MakeDisplayPath(filename)
951 lyxerr[Debug::TCLASS] << "Reading input file "
952 << MakeDisplayPath(filename)
955 LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
958 lexrc.setFile(filename);
959 if (!lexrc.IsOK()) error = true;
962 while (lexrc.IsOK() && !error) {
963 int le = lexrc.lex();
965 case LyXLex::LEX_FEOF:
968 case LyXLex::LEX_UNDEF:
969 lexrc.printError("Unknown TextClass tag `$$Token'");
974 switch(static_cast<TextClassTags>(le)) {
975 case TC_OUTPUTTYPE: // output type definition
976 readOutputType(lexrc);
979 case TC_INPUT: // Include file
981 string tmp = LibFileSearch("layouts",
985 if (Read(tmp, true)) {
986 lexrc.printError("Error reading input"
995 string name = subst(lexrc.GetString(),
997 if (hasLayout(name)) {
998 LyXLayout & lay = GetLayout(name);
999 error = do_readStyle(lexrc, lay);
1003 if (!(error = do_readStyle(lexrc, lay)))
1004 layoutlist.push_back(lay);
1008 lexrc.printError("No name given for style: `$$Token'.");
1015 string style = subst(lexrc.GetString(),
1017 if (!delete_layout(style))
1018 lexrc.printError("Cannot delete style"
1025 columns_ = lexrc.GetInteger();
1030 switch(lexrc.GetInteger()) {
1031 case 1: sides_ = OneSide; break;
1032 case 2: sides_ = TwoSides; break;
1034 lyxerr << "Impossible number of page"
1035 " sides, setting to one."
1045 pagestyle_ = strip(lexrc.GetString());
1048 case TC_DEFAULTFONT:
1049 defaultfont_.lyxRead(lexrc);
1050 if (!defaultfont_.resolved()) {
1051 lexrc.printError("Warning: defaultfont should "
1052 "be fully instantiated!");
1053 defaultfont_.realize(LyXFont::ALL_SANE);
1058 readMaxCounter(lexrc);
1061 case TC_SECNUMDEPTH:
1063 secnumdepth_ = lexrc.GetInteger();
1068 tocdepth_ = lexrc.GetInteger();
1071 // First step to support options
1072 case TC_CLASSOPTIONS:
1073 readClassOptions(lexrc);
1077 preamble_ = lexrc.getLongString("EndPreamble");
1080 case TC_PROVIDESAMSMATH:
1081 if (lexrc.next() && lexrc.GetInteger())
1082 provides_ |= amsmath;
1085 case TC_PROVIDESMAKEIDX:
1086 if (lexrc.next() && lexrc.GetInteger())
1087 provides_ |= makeidx;
1090 case TC_PROVIDESURL:
1091 if (lexrc.next() && lexrc.GetInteger())
1095 case TC_LEFTMARGIN: // left margin type
1097 leftmargin_ = lexrc.GetString();
1100 case TC_RIGHTMARGIN: // right margin type
1102 rightmargin_ = lexrc.GetString();
1107 if (!merge) { // we are at top level here.
1108 lyxerr[Debug::TCLASS] << "Finished reading textclass "
1109 << MakeDisplayPath(filename)
1112 lyxerr[Debug::TCLASS] << "Finished reading input file "
1113 << MakeDisplayPath(filename)
1121 static keyword_item outputTypeTags[] = {
1122 { "docbook", DOCBOOK },
1124 { "linuxdoc", LINUXDOC },
1125 { "literate", LITERATE }
1129 void LyXTextClass::readOutputType(LyXLex & lexrc)
1132 keyword_item outputTypeTags[] = {
1133 { "docbook", DOCBOOK },
1135 { "linuxdoc", LINUXDOC },
1136 { "literate", LITERATE }
1139 pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1141 int le = lexrc.lex();
1143 case LyXLex::LEX_UNDEF:
1144 lexrc.printError("Unknown output type `$$Token'");
1150 outputType_ = static_cast<OutputType>(le);
1153 lyxerr << "Unhandled value " << le
1154 << " in LyXTextClass::readOutputType." << endl;
1161 enum MaxCounterTags {
1162 MC_COUNTER_CHAPTER = 1,
1164 MC_COUNTER_SUBSECTION,
1165 MC_COUNTER_SUBSUBSECTION,
1166 MC_COUNTER_PARAGRAPH,
1167 MC_COUNTER_SUBPARAGRAPH,
1176 static keyword_item maxCounterTags[] = {
1177 {"counter_chapter", MC_COUNTER_CHAPTER },
1178 {"counter_enumi", MC_COUNTER_ENUMI },
1179 {"counter_enumii", MC_COUNTER_ENUMII },
1180 {"counter_enumiii", MC_COUNTER_ENUMIII },
1181 {"counter_enumiv", MC_COUNTER_ENUMIV },
1182 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1183 {"counter_section", MC_COUNTER_SECTION },
1184 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1185 {"counter_subsection", MC_COUNTER_SUBSECTION },
1186 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1191 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1194 keyword_item maxCounterTags[] = {
1195 {"counter_chapter", MC_COUNTER_CHAPTER },
1196 {"counter_enumi", MC_COUNTER_ENUMI },
1197 {"counter_enumii", MC_COUNTER_ENUMII },
1198 {"counter_enumiii", MC_COUNTER_ENUMIII },
1199 {"counter_enumiv", MC_COUNTER_ENUMIV },
1200 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1201 {"counter_section", MC_COUNTER_SECTION },
1202 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1203 {"counter_subsection", MC_COUNTER_SUBSECTION },
1204 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1207 pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1208 int le = lexrc.lex();
1210 case LyXLex::LEX_UNDEF:
1211 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1215 switch (static_cast<MaxCounterTags>(le)) {
1216 case MC_COUNTER_CHAPTER:
1217 maxcounter_ = LABEL_COUNTER_CHAPTER;
1219 case MC_COUNTER_SECTION:
1220 maxcounter_ = LABEL_COUNTER_SECTION;
1222 case MC_COUNTER_SUBSECTION:
1223 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1225 case MC_COUNTER_SUBSUBSECTION:
1226 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1228 case MC_COUNTER_PARAGRAPH:
1229 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1231 case MC_COUNTER_SUBPARAGRAPH:
1232 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1234 case MC_COUNTER_ENUMI:
1235 maxcounter_ = LABEL_COUNTER_ENUMI;
1237 case MC_COUNTER_ENUMII:
1238 maxcounter_ = LABEL_COUNTER_ENUMII;
1240 case MC_COUNTER_ENUMIII:
1241 maxcounter_ = LABEL_COUNTER_ENUMIII;
1243 case MC_COUNTER_ENUMIV:
1244 maxcounter_ = LABEL_COUNTER_ENUMIV;
1250 enum ClassOptionsTags {
1259 static keyword_item classOptionsTags[] = {
1261 {"fontsize", CO_FONTSIZE },
1262 {"other", CO_OTHER },
1263 {"pagestyle", CO_PAGESTYLE }
1268 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1271 keyword_item classOptionsTags[] = {
1273 {"fontsize", CO_FONTSIZE },
1274 {"other", CO_OTHER },
1275 {"pagestyle", CO_PAGESTYLE }
1278 lexrc.pushTable(classOptionsTags, CO_END);
1279 bool getout = false;
1280 while (!getout && lexrc.IsOK()) {
1281 int le = lexrc.lex();
1283 case LyXLex::LEX_UNDEF:
1284 lexrc.printError("Unknown ClassOption tag `$$Token'");
1288 switch (static_cast<ClassOptionsTags>(le)) {
1291 opt_fontsize_ = strip(lexrc.GetString());
1295 opt_pagestyle_ = strip(lexrc.GetString());
1299 options_ = lexrc.GetString();
1310 bool LyXTextClass::hasLayout(string const & name) const
1312 for (LayoutList::const_iterator cit = layoutlist.begin();
1313 cit != layoutlist.end(); ++cit) {
1314 if ((*cit).name() == name)
1321 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1323 for (LayoutList::const_iterator cit = layoutlist.begin();
1324 cit != layoutlist.end(); ++cit) {
1325 if ((*cit).name() == name)
1328 Assert(false); // we actually require the name to exist.
1329 return layoutlist.front();
1333 LyXLayout & LyXTextClass::GetLayout(string const & name)
1335 for (LayoutList::iterator it = layoutlist.begin();
1336 it != layoutlist.end(); ++it) {
1337 if ((*it).name() == name)
1340 Assert(false); // we actually require the name to exist.
1341 return layoutlist.front();
1345 bool LyXTextClass::delete_layout (string const & name)
1347 for(LayoutList::iterator it = layoutlist.begin();
1348 it != layoutlist.end(); ++it) {
1349 if ((*it).name() == name) {
1350 layoutlist.erase(it);
1358 // Load textclass info if not loaded yet
1359 void LyXTextClass::load()
1364 string real_file = LibFileSearch("layouts", name_, "layout");
1366 if (Read(real_file)) {
1367 lyxerr << "Error reading `"
1368 << MakeDisplayPath(real_file)
1369 << "'\n(Check `" << name_
1370 << "')\nCheck your installation and "
1371 "try Options/Reconfigure..." << endl;
1377 //////////////////////////////////////////
1379 // Gets textclass number from name
1380 pair<bool, LyXTextClassList::size_type>
1381 LyXTextClassList::NumberOfClass(string const & textclass) const
1383 for (ClassList::const_iterator cit = classlist.begin();
1384 cit != classlist.end(); ++cit) {
1385 if ((*cit).name() == textclass)
1386 return make_pair(true, cit - classlist.begin());
1388 return make_pair(false, size_type(0));
1392 // Gets layout structure from style number and textclass number
1394 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1395 LyXTextClass::size_type layout) const
1397 classlist[textclass].load();
1398 if (layout < classlist[textclass].numLayouts())
1399 return classlist[textclass][layout];
1400 return classlist[textclass][0];
1404 // Gets layout number from name and textclass number
1405 pair<bool, LyXTextClass::size_type>
1406 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1407 string const & name) const
1409 classlist[textclass].load();
1410 for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1411 if (classlist[textclass][i].name() == name)
1412 return make_pair(true, i);
1414 if (name == "dummy")
1415 return make_pair(true, LYX_DUMMY_LAYOUT);
1416 return make_pair(false, LyXTextClass::LayoutList::size_type(0)); // not found
1420 // Gets a layout (style) name from layout number and textclass number
1422 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1423 LyXTextClass::size_type layout) const
1425 static string dummy("dummy");
1426 classlist[textclass].load();
1427 if (layout < classlist[textclass].numLayouts())
1428 return classlist[textclass][layout].name();
1433 // Gets a textclass name from number
1435 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1437 static string dummy("dummy");
1438 if (classlist.size() == 0) {
1441 Assert(number < classlist.size());
1442 return classlist[number].name();
1446 // Gets a textclass latexname from number
1448 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1450 static string dummy("dummy");
1451 classlist[number].load();
1452 if (classlist.size() == 0) {
1455 Assert(number < classlist.size());
1456 return classlist[number].latexname();
1460 // Gets a textclass description from number
1462 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1464 static string dummy("dummy");
1465 if (classlist.size() == 0) {
1468 Assert(number < classlist.size());
1469 return classlist[number].description();
1473 // Gets a textclass structure from number
1474 LyXTextClass const &
1475 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1477 classlist[textclass].load();
1478 if (textclass < classlist.size())
1479 return classlist[textclass];
1481 return classlist[0];
1485 void LyXTextClassList::Add(LyXTextClass const & t)
1487 classlist.push_back(t);
1491 // used when sorting the textclass list.
1492 class less_textclass_desc {
1494 int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1495 return tc1.description() < tc2.description();
1500 // Reads LyX textclass definitions according to textclass config file
1501 bool LyXTextClassList::Read ()
1504 string real_file = LibFileSearch("", "textclass.lst");
1505 lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1506 << real_file << "'" << endl;
1508 if (real_file.empty()) {
1509 lyxerr << "LyXTextClassList::Read: unable to find "
1510 "textclass file `" << MakeDisplayPath(real_file, 1000)
1511 << "'. Exiting." << endl;
1513 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1514 _("Check that the file \"textclass.lst\""),
1515 _("is installed correctly. Sorry, has to exit :-("));
1517 // This causes LyX to end... Not a desirable behaviour. Lgb
1518 // What do you propose? That the user gets a file dialog
1519 // and is allowed to hunt for the file? (Asger)
1520 // more that we have a layout for minimal.cls statically
1521 // compiled in... (Lgb)
1524 if (!lex.setFile(real_file)) {
1525 lyxerr << "LyXTextClassList::Read: "
1526 "lyxlex was not able to set file: "
1527 << real_file << endl;
1531 lyxerr << "LyXTextClassList::Read: unable to open "
1532 "textclass file `" << MakeDisplayPath(real_file, 1000)
1533 << "'\nCheck your installation. LyX can't continue."
1537 bool finished = false;
1538 string fname, clname, desc;
1539 // Parse config-file
1540 lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1541 while (lex.IsOK() && !finished) {
1542 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1543 switch (lex.lex()) {
1544 case LyXLex::LEX_FEOF:
1548 fname = lex.GetString();
1549 lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1551 clname = lex.GetString();
1552 lyxerr[Debug::TCLASS]
1553 << "Clname: " << clname << endl;
1555 desc = lex.GetString();
1556 lyxerr[Debug::TCLASS]
1557 << "Desc: " << desc << endl;
1558 // This code is run when we have
1559 // fname, clname and desc
1560 LyXTextClass tmpl(fname,
1564 debugging(Debug::TCLASS)) {
1572 lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1574 if (classlist.size() == 0) {
1575 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1577 WriteAlert(_("LyX wasn't able to find any layout description!"),
1578 _("Check the contents of the file \"textclass.lst\""),
1579 _("Sorry, has to exit :-("));
1582 // Ok everything loaded ok, now sort the list.
1583 sort(classlist.begin(), classlist.end(), less_textclass_desc());
1589 Returns false if this fails
1592 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1595 if (number < classlist.size()) {
1596 classlist[number].load();
1597 if (classlist[number].numLayouts() == 0) {