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"
31 // Global variable: textclass table.
32 LyXTextClassList textclasslist;
35 // Reads the style files
38 lyxerr[Debug::TCLASS] << "LyXSetStyle: parsing configuration...\n";
40 if (!textclasslist.Read()) {
41 lyxerr[Debug::TCLASS] << "LyXSetStyle: an error occured "
42 "during parsing.\n Exiting." << endl;
46 lyxerr[Debug::TCLASS] << "LyXSetStyle: configuration parsed." << endl;
50 // The order of the LayoutTags enum is no more important. [asierra300396]
61 //LT_ENVIRONMENT_DEFAULT,
77 LT_LABELSTRING_APPENDIX,
100 // This table is sorted alphabetically [asierra 30March96]
101 static keyword_item layoutTags[] = {
102 { "align", LT_ALIGN },
103 { "alignpossible", LT_ALIGNPOSSIBLE },
104 { "bottomsep", LT_BOTTOMSEP },
105 { "copystyle", LT_COPYSTYLE },
107 { "endlabeltype", LT_ENDLABELTYPE },
108 { "fill_bottom", LT_FILL_BOTTOM },
109 { "fill_top", LT_FILL_TOP },
111 { "freespacing", LT_FREE_SPACING },
112 { "intitle", LT_INTITLE },
113 { "itemsep", LT_ITEMSEP },
114 { "keepempty", LT_KEEPEMPTY },
115 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
116 { "labelfont", LT_LABELFONT },
117 { "labelindent", LT_LABELINDENT },
118 { "labelsep", LT_LABELSEP },
119 { "labelstring", LT_LABELSTRING },
120 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
121 { "labeltype", LT_LABELTYPE },
122 { "latexname", LT_LATEXNAME },
123 { "latexparam", LT_LATEXPARAM },
124 { "latextype", LT_LATEXTYPE },
125 { "leftmargin", LT_LEFTMARGIN },
126 { "margin", LT_MARGIN },
127 { "needprotect", LT_NEED_PROTECT },
128 { "newline", LT_NEWLINE },
129 { "nextnoindent", LT_NEXTNOINDENT },
130 { "obsoletedby", LT_OBSOLETEDBY },
131 { "parindent", LT_PARINDENT },
132 { "parsep", LT_PARSEP },
133 { "parskip", LT_PARSKIP },
134 { "preamble", LT_PREAMBLE },
135 { "rightmargin", LT_RIGHTMARGIN },
136 { "spacing", LT_SPACING },
137 { "textfont", LT_TEXTFONT },
138 { "topsep", LT_TOPSEP }
143 /////////////////////
145 // Constructor for layout
146 LyXLayout::LyXLayout ()
148 margintype = MARGIN_STATIC;
149 latextype = LATEX_PARAGRAPH;
153 font = LyXFont(LyXFont::ALL_INHERIT);
154 labelfont = LyXFont(LyXFont::ALL_INHERIT);
155 resfont = LyXFont(LyXFont::ALL_SANE);
156 reslabelfont = LyXFont(LyXFont::ALL_SANE);
157 nextnoindent = false;
162 labelbottomsep = 0.0;
164 align = LYX_ALIGN_BLOCK;
165 alignpossible = LYX_ALIGN_BLOCK;
166 labeltype = LABEL_NO_LABEL;
167 endlabeltype = END_LABEL_NO_LABEL;
168 // Should or should not. That is the question.
169 // spacing.set(Spacing::OneHalf);
172 newline_allowed = true;
173 free_spacing = false;
177 // Reads a layout definition from file
178 bool LyXLayout::Read (LyXLex & lexrc, LyXTextClass const & tclass)
181 // This table is sorted alphabetically [asierra 30March96]
182 keyword_item layoutTags[] = {
183 { "align", LT_ALIGN },
184 { "alignpossible", LT_ALIGNPOSSIBLE },
185 { "bottomsep", LT_BOTTOMSEP },
186 { "copystyle", LT_COPYSTYLE },
188 { "endlabeltype", LT_ENDLABELTYPE },
189 { "fill_bottom", LT_FILL_BOTTOM },
190 { "fill_top", LT_FILL_TOP },
192 { "freespacing", LT_FREE_SPACING },
193 { "intitle", LT_INTITLE },
194 { "itemsep", LT_ITEMSEP },
195 { "keepempty", LT_KEEPEMPTY },
196 { "labelbottomsep", LT_LABEL_BOTTOMSEP },
197 { "labelfont", LT_LABELFONT },
198 { "labelindent", LT_LABELINDENT },
199 { "labelsep", LT_LABELSEP },
200 { "labelstring", LT_LABELSTRING },
201 { "labelstringappendix", LT_LABELSTRING_APPENDIX },
202 { "labeltype", LT_LABELTYPE },
203 { "latexname", LT_LATEXNAME },
204 { "latexparam", LT_LATEXPARAM },
205 { "latextype", LT_LATEXTYPE },
206 { "leftmargin", LT_LEFTMARGIN },
207 { "margin", LT_MARGIN },
208 { "needprotect", LT_NEED_PROTECT },
209 { "newline", LT_NEWLINE },
210 { "nextnoindent", LT_NEXTNOINDENT },
211 { "obsoletedby", LT_OBSOLETEDBY },
212 { "parindent", LT_PARINDENT },
213 { "parsep", LT_PARSEP },
214 { "parskip", LT_PARSKIP },
215 { "preamble", LT_PREAMBLE },
216 { "rightmargin", LT_RIGHTMARGIN },
217 { "spacing", LT_SPACING },
218 { "textfont", LT_TEXTFONT },
219 { "topsep", LT_TOPSEP }
223 bool finished = false;
224 lexrc.pushTable(layoutTags, LT_INTITLE);
225 // parse style section
226 while (!finished && lexrc.IsOK() && !error) {
227 int le = lexrc.lex();
228 // See comment in lyxrc.C.
230 case LyXLex::LEX_FEOF:
233 case LyXLex::LEX_UNDEF: // parse error
234 lexrc.printError("Unknown layout tag `$$Token'");
239 switch(static_cast<LayoutTags>(le)) {
240 case LT_END: // end of structure
244 case LT_COPYSTYLE: // initialize with a known style
246 if (tclass.hasLayout(lexrc.GetString())) {
247 string tmpname = name_;
248 this->operator= (tclass.GetLayout(lexrc.GetString()));
251 lexrc.printError("Cannot copy known "
257 case LT_OBSOLETEDBY: // replace with a known style
259 if (tclass.hasLayout(lexrc.GetString())) {
260 string tmpname = name_;
261 this->operator= (tclass.GetLayout(lexrc.GetString()));
263 if (obsoleted_by().empty())
264 obsoleted_by_ = lexrc.GetString();
266 lexrc.printError("Cannot replace with"
273 case LT_MARGIN: // Margin style definition.
277 case LT_LATEXTYPE: // Latex style definition.
278 readLatexType(lexrc);
282 intitle = lexrc.next() && lexrc.GetInteger();
285 case LT_NEED_PROTECT:
286 needprotect = lexrc.next() && lexrc.GetInteger();
290 keepempty = lexrc.next() && lexrc.GetInteger();
303 labelfont.lyxRead(lexrc);
306 case LT_NEXTNOINDENT: // Indent next paragraph?
307 if (lexrc.next() && lexrc.GetInteger())
310 nextnoindent = false;
315 latexname_ = lexrc.GetString();
320 latexparam_ = lexrc.GetString();
324 preamble_ = lexrc.getLongString("EndPreamble");
328 readLabelType(lexrc);
331 case LT_ENDLABELTYPE:
332 readEndLabelType(lexrc);
335 case LT_LEFTMARGIN: // left margin type
337 leftmargin = lexrc.GetString();
340 case LT_RIGHTMARGIN: // right margin type
342 rightmargin = lexrc.GetString();
345 case LT_LABELINDENT: // label indenting flag
347 labelindent = lexrc.GetString();
350 case LT_PARINDENT: // paragraph indent. flag
352 parindent = lexrc.GetString();
355 case LT_PARSKIP: // paragraph skip size
357 parskip = lexrc.GetFloat();
360 case LT_ITEMSEP: // item separation size
362 itemsep = lexrc.GetFloat();
365 case LT_TOPSEP: // top separation size
367 topsep = lexrc.GetFloat();
370 case LT_BOTTOMSEP: // bottom separation size
372 bottomsep = lexrc.GetFloat();
375 case LT_LABEL_BOTTOMSEP: // label bottom separation size
377 labelbottomsep = lexrc.GetFloat();
380 case LT_LABELSEP: // label separator
382 labelsep = subst(lexrc.GetString(), 'x', ' ');
386 case LT_PARSEP: // par. separation size
388 parsep = lexrc.GetFloat();
391 case LT_FILL_TOP: // fill top flag
393 fill_top = lexrc.GetInteger();
396 case LT_FILL_BOTTOM: // fill bottom flag
398 fill_bottom = lexrc.GetInteger();
401 case LT_NEWLINE: // newlines allowed?
403 newline_allowed = lexrc.GetInteger();
406 case LT_ALIGN: // paragraph align
409 case LT_ALIGNPOSSIBLE: // paragraph allowed align
410 readAlignPossible(lexrc);
413 case LT_LABELSTRING: // label string definition
415 labelstring_ = lexrc.GetString();
418 case LT_LABELSTRING_APPENDIX: // label string appendix definition
420 labelstring_appendix_ = lexrc.GetString();
423 case LT_FREE_SPACING: // Allow for free spacing.
425 free_spacing = lexrc.GetInteger();
428 case LT_SPACING: // setspace.sty
448 static keyword_item alignTags[] = {
449 { "block", AT_BLOCK },
450 { "center", AT_CENTER },
451 { "layout", AT_LAYOUT },
453 { "right", AT_RIGHT }
457 void LyXLayout::readAlign(LyXLex & lexrc)
460 keyword_item alignTags[] = {
461 { "block", AT_BLOCK },
462 { "center", AT_CENTER },
463 { "layout", AT_LAYOUT },
465 { "right", AT_RIGHT }
468 pushpophelper pph(lexrc, alignTags, AT_LAYOUT);
469 int le = lexrc.lex();
471 case LyXLex::LEX_UNDEF:
472 lexrc.printError("Unknown alignment `$$Token'");
476 switch(static_cast<AlignTags>(le)) {
478 align = LYX_ALIGN_BLOCK;
481 align = LYX_ALIGN_LEFT;
484 align = LYX_ALIGN_RIGHT;
487 align = LYX_ALIGN_CENTER;
490 align = LYX_ALIGN_LAYOUT;
496 void LyXLayout::readAlignPossible(LyXLex & lexrc)
499 keyword_item alignTags[] = {
500 { "block", AT_BLOCK },
501 { "center", AT_CENTER },
502 { "layout", AT_LAYOUT },
504 { "right", AT_RIGHT }
507 lexrc.pushTable(alignTags, AT_LAYOUT);
508 alignpossible = LYX_ALIGN_NONE;
509 int lineno = lexrc.GetLineNo();
511 int le = lexrc.lex();
513 case LyXLex::LEX_UNDEF:
514 lexrc.printError("Unknown alignment `$$Token'");
518 switch (static_cast<AlignTags>(le)) {
520 alignpossible |= LYX_ALIGN_BLOCK;
523 alignpossible |= LYX_ALIGN_LEFT;
526 alignpossible |= LYX_ALIGN_RIGHT;
529 alignpossible |= LYX_ALIGN_CENTER;
532 alignpossible |= LYX_ALIGN_LAYOUT;
535 } while (lineno == lexrc.GetLineNo());
544 LA_CENTERED_TOP_ENVIRONMENT,
549 LA_COUNTER_SUBSECTION,
550 LA_COUNTER_SUBSUBSECTION,
551 LA_COUNTER_PARAGRAPH,
552 LA_COUNTER_SUBPARAGRAPH,
562 static keyword_item labelTypeTags[] = {
563 { "bibliography", LA_BIBLIO },
564 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
565 { "counter_chapter", LA_COUNTER_CHAPTER },
566 { "counter_enumi", LA_COUNTER_ENUMI },
567 { "counter_enumii", LA_COUNTER_ENUMII },
568 { "counter_enumiii", LA_COUNTER_ENUMIII },
569 { "counter_enumiv", LA_COUNTER_ENUMIV },
570 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
571 { "counter_section", LA_COUNTER_SECTION },
572 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
573 { "counter_subsection", LA_COUNTER_SUBSECTION },
574 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
575 { "manual", LA_MANUAL },
576 { "no_label", LA_NO_LABEL },
577 { "sensitive", LA_SENSITIVE },
578 { "static", LA_STATIC },
579 { "top_environment", LA_TOP_ENVIRONMENT }
584 void LyXLayout::readLabelType(LyXLex & lexrc)
587 keyword_item labelTypeTags[] = {
588 { "bibliography", LA_BIBLIO },
589 { "centered_top_environment", LA_CENTERED_TOP_ENVIRONMENT },
590 { "counter_chapter", LA_COUNTER_CHAPTER },
591 { "counter_enumi", LA_COUNTER_ENUMI },
592 { "counter_enumii", LA_COUNTER_ENUMII },
593 { "counter_enumiii", LA_COUNTER_ENUMIII },
594 { "counter_enumiv", LA_COUNTER_ENUMIV },
595 { "counter_paragraph", LA_COUNTER_PARAGRAPH },
596 { "counter_section", LA_COUNTER_SECTION },
597 { "counter_subparagraph", LA_COUNTER_SUBPARAGRAPH },
598 { "counter_subsection", LA_COUNTER_SUBSECTION },
599 { "counter_subsubsection", LA_COUNTER_SUBSUBSECTION },
600 { "manual", LA_MANUAL },
601 { "no_label", LA_NO_LABEL },
602 { "sensitive", LA_SENSITIVE },
603 { "static", LA_STATIC },
604 { "top_environment", LA_TOP_ENVIRONMENT }
607 pushpophelper pph(lexrc, labelTypeTags, LA_BIBLIO);
608 int le = lexrc.lex();
610 case LyXLex::LEX_UNDEF:
611 lexrc.printError("Unknown labeltype tag `$$Token'");
615 switch (static_cast<LabelTypeTags>(le)) {
617 labeltype = LABEL_NO_LABEL;
620 labeltype = LABEL_MANUAL;
622 case LA_TOP_ENVIRONMENT:
623 labeltype = LABEL_TOP_ENVIRONMENT;
625 case LA_CENTERED_TOP_ENVIRONMENT:
626 labeltype = LABEL_CENTERED_TOP_ENVIRONMENT;
629 labeltype = LABEL_STATIC;
632 labeltype = LABEL_SENSITIVE;
634 case LA_COUNTER_CHAPTER:
635 labeltype = LABEL_COUNTER_CHAPTER;
637 case LA_COUNTER_SECTION:
638 labeltype = LABEL_COUNTER_SECTION;
640 case LA_COUNTER_SUBSECTION:
641 labeltype = LABEL_COUNTER_SUBSECTION;
643 case LA_COUNTER_SUBSUBSECTION:
644 labeltype = LABEL_COUNTER_SUBSUBSECTION;
646 case LA_COUNTER_PARAGRAPH:
647 labeltype = LABEL_COUNTER_PARAGRAPH;
649 case LA_COUNTER_SUBPARAGRAPH:
650 labeltype = LABEL_COUNTER_SUBPARAGRAPH;
652 case LA_COUNTER_ENUMI:
653 labeltype = LABEL_COUNTER_ENUMI;
655 case LA_COUNTER_ENUMII:
656 labeltype = LABEL_COUNTER_ENUMII;
658 case LA_COUNTER_ENUMIII:
659 labeltype = LABEL_COUNTER_ENUMIII;
661 case LA_COUNTER_ENUMIV:
662 labeltype = LABEL_COUNTER_ENUMIV;
665 labeltype = LABEL_BIBLIO;
670 static keyword_item endlabelTypeTags[] = {
671 { "box", END_LABEL_BOX },
672 { "filled_box", END_LABEL_FILLED_BOX },
673 { "no_label", END_LABEL_NO_LABEL }
676 void LyXLayout::readEndLabelType(LyXLex & lexrc)
678 pushpophelper pph(lexrc, endlabelTypeTags,
679 END_LABEL_ENUM_LAST-END_LABEL_ENUM_FIRST+1);
680 int le = lexrc.lex();
682 case LyXLex::LEX_UNDEF:
683 lexrc.printError("Unknown labeltype tag `$$Token'");
686 case END_LABEL_FILLED_BOX:
687 case END_LABEL_NO_LABEL:
688 endlabeltype = static_cast<LYX_END_LABEL_TYPES>(le);
691 lyxerr << "Unhandled value " << le
692 << " in LyXLayout::readEndLabelType." << endl;
698 static keyword_item marginTags[] = {
699 { "dynamic", MARGIN_DYNAMIC },
700 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
701 { "manual", MARGIN_MANUAL },
702 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
703 { "static", MARGIN_STATIC }
707 void LyXLayout::readMargin(LyXLex & lexrc)
710 keyword_item marginTags[] = {
711 { "dynamic", MARGIN_DYNAMIC },
712 { "first_dynamic", MARGIN_FIRST_DYNAMIC },
713 { "manual", MARGIN_MANUAL },
714 { "right_address_box", MARGIN_RIGHT_ADDRESS_BOX },
715 { "static", MARGIN_STATIC }
718 pushpophelper pph(lexrc, marginTags, MARGIN_RIGHT_ADDRESS_BOX);
720 int le = lexrc.lex();
722 case LyXLex::LEX_UNDEF:
723 lexrc.printError("Unknown margin type tag `$$Token'");
728 case MARGIN_FIRST_DYNAMIC:
729 case MARGIN_RIGHT_ADDRESS_BOX:
730 margintype = static_cast<LYX_MARGIN_TYPE>(le);
733 lyxerr << "Unhandled value " << le
734 << " in LyXLayout::readMargin." << endl;
741 static keyword_item latexTypeTags[] = {
742 { "command", LATEX_COMMAND },
743 { "environment", LATEX_ENVIRONMENT },
744 { "item_environment", LATEX_ITEM_ENVIRONMENT },
745 { "list_environment", LATEX_LIST_ENVIRONMENT },
746 { "paragraph", LATEX_PARAGRAPH }
751 void LyXLayout::readLatexType(LyXLex & lexrc)
754 keyword_item latexTypeTags[] = {
755 { "command", LATEX_COMMAND },
756 { "environment", LATEX_ENVIRONMENT },
757 { "item_environment", LATEX_ITEM_ENVIRONMENT },
758 { "list_environment", LATEX_LIST_ENVIRONMENT },
759 { "paragraph", LATEX_PARAGRAPH }
762 pushpophelper pph(lexrc, latexTypeTags, LATEX_LIST_ENVIRONMENT);
763 int le = lexrc.lex();
765 case LyXLex::LEX_UNDEF:
766 lexrc.printError("Unknown latextype tag `$$Token'");
768 case LATEX_PARAGRAPH:
770 case LATEX_ENVIRONMENT:
771 case LATEX_ITEM_ENVIRONMENT:
772 case LATEX_LIST_ENVIRONMENT:
773 latextype = static_cast<LYX_LATEX_TYPES>(le);
776 lyxerr << "Unhandled value " << le
777 << " in LyXLayout::readLatexType." << endl;
784 ST_SPACING_SINGLE = 1,
792 static keyword_item spacingTags[] = {
793 {"double", ST_SPACING_DOUBLE },
794 {"onehalf", ST_SPACING_ONEHALF },
795 {"other", ST_OTHER },
796 {"single", ST_SPACING_SINGLE }
801 void LyXLayout::readSpacing(LyXLex & lexrc)
804 keyword_item spacingTags[] = {
805 {"double", ST_SPACING_DOUBLE },
806 {"onehalf", ST_SPACING_ONEHALF },
807 {"other", ST_OTHER },
808 {"single", ST_SPACING_SINGLE }
811 pushpophelper pph(lexrc, spacingTags, ST_OTHER);
812 int le = lexrc.lex();
814 case LyXLex::LEX_UNDEF:
815 lexrc.printError("Unknown spacing token `$$Token'");
819 switch(static_cast<SpacingTags>(le)) {
820 case ST_SPACING_SINGLE:
821 spacing.set(Spacing::Single);
823 case ST_SPACING_ONEHALF:
824 spacing.set(Spacing::Onehalf);
826 case ST_SPACING_DOUBLE:
827 spacing.set(Spacing::Double);
831 spacing.set(Spacing::Other, lexrc.GetFloat());
837 /* ******************************************************************* */
839 LyXTextClass::LyXTextClass(string const & fn, string const & cln,
841 : name_(fn), latexname_(cln), description_(desc)
848 pagestyle_ = "default";
849 maxcounter_ = LABEL_COUNTER_CHAPTER;
850 defaultfont_ = LyXFont(LyXFont::ALL_SANE);
851 opt_fontsize_ = "10|11|12";
852 opt_pagestyle_ = "empty|plain|headings|fancy";
858 bool LyXTextClass::do_readStyle(LyXLex & lexrc, LyXLayout & lay)
860 lyxerr[Debug::TCLASS] << "Reading style " << lay.name() << endl;
861 if (!lay.Read(lexrc, *this)) {
863 lay.resfont = lay.font;
864 lay.resfont.realize(defaultfont());
865 lay.reslabelfont = lay.labelfont;
866 lay.reslabelfont.realize(defaultfont());
867 return false; // no errors
869 lyxerr << "Error parsing style `" << lay.name() << "'" << endl;
897 static keyword_item textClassTags[] = {
898 { "classoptions", TC_CLASSOPTIONS },
899 { "columns", TC_COLUMNS },
900 { "defaultfont", TC_DEFAULTFONT },
901 { "input", TC_INPUT },
902 { "leftmargin", TC_LEFTMARGIN },
903 { "maxcounter", TC_MAXCOUNTER },
904 { "nostyle", TC_NOSTYLE },
905 { "outputtype", TC_OUTPUTTYPE },
906 { "pagestyle", TC_PAGESTYLE },
907 { "preamble", TC_PREAMBLE },
908 { "providesamsmath", TC_PROVIDESAMSMATH },
909 { "providesmakeidx", TC_PROVIDESMAKEIDX },
910 { "providesurl", TC_PROVIDESURL },
911 { "rightmargin", TC_RIGHTMARGIN },
912 { "secnumdepth", TC_SECNUMDEPTH },
913 { "sides", TC_SIDES },
914 { "style", TC_STYLE },
915 { "tocdepth", TC_TOCDEPTH }
920 // Reads a textclass structure from file.
921 bool LyXTextClass::Read(string const & filename, bool merge)
924 keyword_item textClassTags[] = {
925 { "classoptions", TC_CLASSOPTIONS },
926 { "columns", TC_COLUMNS },
927 { "defaultfont", TC_DEFAULTFONT },
928 { "input", TC_INPUT },
929 { "leftmargin", TC_LEFTMARGIN },
930 { "maxcounter", TC_MAXCOUNTER },
931 { "nostyle", TC_NOSTYLE },
932 { "outputtype", TC_OUTPUTTYPE },
933 { "pagestyle", TC_PAGESTYLE },
934 { "preamble", TC_PREAMBLE },
935 { "providesamsmath", TC_PROVIDESAMSMATH },
936 { "providesmakeidx", TC_PROVIDESMAKEIDX },
937 { "providesurl", TC_PROVIDESURL },
938 { "rightmargin", TC_RIGHTMARGIN },
939 { "secnumdepth", TC_SECNUMDEPTH },
940 { "sides", TC_SIDES },
941 { "style", TC_STYLE },
942 { "tocdepth", TC_TOCDEPTH }
946 lyxerr[Debug::TCLASS] << "Reading textclass "
947 << MakeDisplayPath(filename)
950 lyxerr[Debug::TCLASS] << "Reading input file "
951 << MakeDisplayPath(filename)
954 LyXLex lexrc(textClassTags, TC_RIGHTMARGIN);
957 lexrc.setFile(filename);
958 if (!lexrc.IsOK()) error = true;
961 while (lexrc.IsOK() && !error) {
962 int le = lexrc.lex();
964 case LyXLex::LEX_FEOF:
967 case LyXLex::LEX_UNDEF:
968 lexrc.printError("Unknown TextClass tag `$$Token'");
973 switch(static_cast<TextClassTags>(le)) {
974 case TC_OUTPUTTYPE: // output type definition
975 readOutputType(lexrc);
978 case TC_INPUT: // Include file
980 string tmp = LibFileSearch("layouts",
984 if (Read(tmp, true)) {
985 lexrc.printError("Error reading input"
994 string name = subst(lexrc.GetString(),
996 if (hasLayout(name)) {
997 LyXLayout & lay = GetLayout(name);
998 error = do_readStyle(lexrc, lay);
1002 if (!(error = do_readStyle(lexrc, lay)))
1003 layoutlist.push_back(lay);
1007 lexrc.printError("No name given for style: `$$Token'.");
1014 string style = subst(lexrc.GetString(),
1016 if (!delete_layout(style))
1017 lexrc.printError("Cannot delete style"
1024 columns_ = lexrc.GetInteger();
1029 switch(lexrc.GetInteger()) {
1030 case 1: sides_ = OneSide; break;
1031 case 2: sides_ = TwoSides; break;
1033 lyxerr << "Impossible number of page"
1034 " sides, setting to one."
1044 pagestyle_ = strip(lexrc.GetString());
1047 case TC_DEFAULTFONT:
1048 defaultfont_.lyxRead(lexrc);
1049 if (!defaultfont_.resolved()) {
1050 lexrc.printError("Warning: defaultfont should "
1051 "be fully instantiated!");
1052 defaultfont_.realize(LyXFont::ALL_SANE);
1057 readMaxCounter(lexrc);
1060 case TC_SECNUMDEPTH:
1062 secnumdepth_ = lexrc.GetInteger();
1067 tocdepth_ = lexrc.GetInteger();
1070 // First step to support options
1071 case TC_CLASSOPTIONS:
1072 readClassOptions(lexrc);
1076 preamble_ = lexrc.getLongString("EndPreamble");
1079 case TC_PROVIDESAMSMATH:
1080 if (lexrc.next() && lexrc.GetInteger())
1081 provides_ |= amsmath;
1084 case TC_PROVIDESMAKEIDX:
1085 if (lexrc.next() && lexrc.GetInteger())
1086 provides_ |= makeidx;
1089 case TC_PROVIDESURL:
1090 if (lexrc.next() && lexrc.GetInteger())
1094 case TC_LEFTMARGIN: // left margin type
1096 leftmargin_ = lexrc.GetString();
1099 case TC_RIGHTMARGIN: // right margin type
1101 rightmargin_ = lexrc.GetString();
1106 if (!merge) { // we are at top level here.
1107 lyxerr[Debug::TCLASS] << "Finished reading textclass "
1108 << MakeDisplayPath(filename)
1111 lyxerr[Debug::TCLASS] << "Finished reading input file "
1112 << MakeDisplayPath(filename)
1120 static keyword_item outputTypeTags[] = {
1121 { "docbook", DOCBOOK },
1123 { "linuxdoc", LINUXDOC },
1124 { "literate", LITERATE }
1128 void LyXTextClass::readOutputType(LyXLex & lexrc)
1131 keyword_item outputTypeTags[] = {
1132 { "docbook", DOCBOOK },
1134 { "linuxdoc", LINUXDOC },
1135 { "literate", LITERATE }
1138 pushpophelper pph(lexrc, outputTypeTags, LITERATE);
1140 int le = lexrc.lex();
1142 case LyXLex::LEX_UNDEF:
1143 lexrc.printError("Unknown output type `$$Token'");
1149 outputType_ = static_cast<OutputType>(le);
1152 lyxerr << "Unhandled value " << le
1153 << " in LyXTextClass::readOutputType." << endl;
1160 enum MaxCounterTags {
1161 MC_COUNTER_CHAPTER = 1,
1163 MC_COUNTER_SUBSECTION,
1164 MC_COUNTER_SUBSUBSECTION,
1165 MC_COUNTER_PARAGRAPH,
1166 MC_COUNTER_SUBPARAGRAPH,
1175 static keyword_item maxCounterTags[] = {
1176 {"counter_chapter", MC_COUNTER_CHAPTER },
1177 {"counter_enumi", MC_COUNTER_ENUMI },
1178 {"counter_enumii", MC_COUNTER_ENUMII },
1179 {"counter_enumiii", MC_COUNTER_ENUMIII },
1180 {"counter_enumiv", MC_COUNTER_ENUMIV },
1181 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1182 {"counter_section", MC_COUNTER_SECTION },
1183 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1184 {"counter_subsection", MC_COUNTER_SUBSECTION },
1185 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1190 void LyXTextClass::readMaxCounter(LyXLex & lexrc)
1193 keyword_item maxCounterTags[] = {
1194 {"counter_chapter", MC_COUNTER_CHAPTER },
1195 {"counter_enumi", MC_COUNTER_ENUMI },
1196 {"counter_enumii", MC_COUNTER_ENUMII },
1197 {"counter_enumiii", MC_COUNTER_ENUMIII },
1198 {"counter_enumiv", MC_COUNTER_ENUMIV },
1199 {"counter_paragraph", MC_COUNTER_PARAGRAPH },
1200 {"counter_section", MC_COUNTER_SECTION },
1201 {"counter_subparagraph", MC_COUNTER_SUBPARAGRAPH },
1202 {"counter_subsection", MC_COUNTER_SUBSECTION },
1203 {"counter_subsubsection", MC_COUNTER_SUBSUBSECTION }
1206 pushpophelper pph(lexrc, maxCounterTags, MC_COUNTER_ENUMIV);
1207 int le = lexrc.lex();
1209 case LyXLex::LEX_UNDEF:
1210 lexrc.printError("Unknown MaxCounter tag `$$Token'");
1214 switch (static_cast<MaxCounterTags>(le)) {
1215 case MC_COUNTER_CHAPTER:
1216 maxcounter_ = LABEL_COUNTER_CHAPTER;
1218 case MC_COUNTER_SECTION:
1219 maxcounter_ = LABEL_COUNTER_SECTION;
1221 case MC_COUNTER_SUBSECTION:
1222 maxcounter_ = LABEL_COUNTER_SUBSECTION;
1224 case MC_COUNTER_SUBSUBSECTION:
1225 maxcounter_ = LABEL_COUNTER_SUBSUBSECTION;
1227 case MC_COUNTER_PARAGRAPH:
1228 maxcounter_ = LABEL_COUNTER_PARAGRAPH;
1230 case MC_COUNTER_SUBPARAGRAPH:
1231 maxcounter_ = LABEL_COUNTER_SUBPARAGRAPH;
1233 case MC_COUNTER_ENUMI:
1234 maxcounter_ = LABEL_COUNTER_ENUMI;
1236 case MC_COUNTER_ENUMII:
1237 maxcounter_ = LABEL_COUNTER_ENUMII;
1239 case MC_COUNTER_ENUMIII:
1240 maxcounter_ = LABEL_COUNTER_ENUMIII;
1242 case MC_COUNTER_ENUMIV:
1243 maxcounter_ = LABEL_COUNTER_ENUMIV;
1249 enum ClassOptionsTags {
1258 static keyword_item classOptionsTags[] = {
1260 {"fontsize", CO_FONTSIZE },
1261 {"other", CO_OTHER },
1262 {"pagestyle", CO_PAGESTYLE }
1267 void LyXTextClass::readClassOptions(LyXLex & lexrc)
1270 keyword_item classOptionsTags[] = {
1272 {"fontsize", CO_FONTSIZE },
1273 {"other", CO_OTHER },
1274 {"pagestyle", CO_PAGESTYLE }
1277 lexrc.pushTable(classOptionsTags, CO_END);
1278 bool getout = false;
1279 while (!getout && lexrc.IsOK()) {
1280 int le = lexrc.lex();
1282 case LyXLex::LEX_UNDEF:
1283 lexrc.printError("Unknown ClassOption tag `$$Token'");
1287 switch (static_cast<ClassOptionsTags>(le)) {
1290 opt_fontsize_ = strip(lexrc.GetString());
1294 opt_pagestyle_ = strip(lexrc.GetString());
1298 options_ = lexrc.GetString();
1309 bool LyXTextClass::hasLayout(string const & name) const
1311 for (LayoutList::const_iterator cit = layoutlist.begin();
1312 cit != layoutlist.end(); ++cit) {
1313 if ((*cit).name() == name)
1320 LyXLayout const & LyXTextClass::GetLayout (string const & name) const
1322 for (LayoutList::const_iterator cit = layoutlist.begin();
1323 cit != layoutlist.end(); ++cit) {
1324 if ((*cit).name() == name)
1327 Assert(false); // we actually require the name to exist.
1328 return layoutlist.front();
1332 LyXLayout & LyXTextClass::GetLayout(string const & name)
1334 for (LayoutList::iterator it = layoutlist.begin();
1335 it != layoutlist.end(); ++it) {
1336 if ((*it).name() == name)
1339 Assert(false); // we actually require the name to exist.
1340 return layoutlist.front();
1344 bool LyXTextClass::delete_layout (string const & name)
1346 for(LayoutList::iterator it = layoutlist.begin();
1347 it != layoutlist.end(); ++it) {
1348 if ((*it).name() == name) {
1349 layoutlist.erase(it);
1357 // Load textclass info if not loaded yet
1358 void LyXTextClass::load()
1363 string real_file = LibFileSearch("layouts", name_, "layout");
1365 if (Read(real_file)) {
1366 lyxerr << "Error reading `"
1367 << MakeDisplayPath(real_file)
1368 << "'\n(Check `" << name_
1369 << "')\nCheck your installation and "
1370 "try Options/Reconfigure..." << endl;
1376 //////////////////////////////////////////
1378 // Gets textclass number from name
1379 pair<bool, LyXTextClassList::size_type>
1380 LyXTextClassList::NumberOfClass(string const & textclass) const
1382 for (ClassList::const_iterator cit = classlist.begin();
1383 cit != classlist.end(); ++cit) {
1384 if ((*cit).name() == textclass)
1385 return make_pair(true, cit - classlist.begin());
1387 return make_pair(false, size_type(0));
1391 // Gets layout structure from style number and textclass number
1393 LyXTextClassList::Style(LyXTextClassList::size_type textclass,
1394 LyXTextClass::size_type layout) const
1396 classlist[textclass].load();
1397 if (layout < classlist[textclass].numLayouts())
1398 return classlist[textclass][layout];
1399 return classlist[textclass][0];
1403 // Gets layout number from name and textclass number
1404 pair<bool, LyXTextClass::size_type>
1405 LyXTextClassList::NumberOfLayout(LyXTextClassList::size_type textclass,
1406 string const & name) const
1408 classlist[textclass].load();
1409 for(unsigned int i = 0; i < classlist[textclass].numLayouts(); ++i) {
1410 if (classlist[textclass][i].name() == name)
1411 return make_pair(true, i);
1413 if (name == "dummy")
1414 return make_pair(true, LYX_DUMMY_LAYOUT);
1415 return make_pair(false, LyXTextClass::LayoutList::size_type(0)); // not found
1419 // Gets a layout (style) name from layout number and textclass number
1421 LyXTextClassList::NameOfLayout(LyXTextClassList::size_type textclass,
1422 LyXTextClass::size_type layout) const
1424 static string dummy("dummy");
1425 classlist[textclass].load();
1426 if (layout < classlist[textclass].numLayouts())
1427 return classlist[textclass][layout].name();
1432 // Gets a textclass name from number
1434 LyXTextClassList::NameOfClass(LyXTextClassList::size_type number) const
1436 static string dummy("dummy");
1437 if (classlist.size() == 0) {
1440 Assert(number < classlist.size());
1441 return classlist[number].name();
1445 // Gets a textclass latexname from number
1447 LyXTextClassList::LatexnameOfClass(LyXTextClassList::size_type number) const
1449 static string dummy("dummy");
1450 classlist[number].load();
1451 if (classlist.size() == 0) {
1454 Assert(number < classlist.size());
1455 return classlist[number].latexname();
1459 // Gets a textclass description from number
1461 LyXTextClassList::DescOfClass(LyXTextClassList::size_type number) const
1463 static string dummy("dummy");
1464 if (classlist.size() == 0) {
1467 Assert(number < classlist.size());
1468 return classlist[number].description();
1472 // Gets a textclass structure from number
1473 LyXTextClass const &
1474 LyXTextClassList::TextClass(LyXTextClassList::size_type textclass) const
1476 classlist[textclass].load();
1477 if (textclass < classlist.size())
1478 return classlist[textclass];
1480 return classlist[0];
1484 void LyXTextClassList::Add(LyXTextClass const & t)
1486 classlist.push_back(t);
1490 // used when sorting the textclass list.
1491 class less_textclass_desc {
1493 int operator()(LyXTextClass const & tc1, LyXTextClass const & tc2) {
1494 return tc1.description() < tc2.description();
1499 // Reads LyX textclass definitions according to textclass config file
1500 bool LyXTextClassList::Read ()
1503 string real_file = LibFileSearch("", "textclass.lst");
1504 lyxerr[Debug::TCLASS] << "Reading textclasses from `"
1505 << real_file << "'" << endl;
1507 if (real_file.empty()) {
1508 lyxerr << "LyXTextClassList::Read: unable to find "
1509 "textclass file `" << MakeDisplayPath(real_file, 1000)
1510 << "'. Exiting." << endl;
1512 WriteAlert(_("LyX wasn't able to find its layout descriptions!"),
1513 _("Check that the file \"textclass.lst\""),
1514 _("is installed correctly. Sorry, has to exit :-("));
1516 // This causes LyX to end... Not a desirable behaviour. Lgb
1517 // What do you propose? That the user gets a file dialog
1518 // and is allowed to hunt for the file? (Asger)
1519 // more that we have a layout for minimal.cls statically
1520 // compiled in... (Lgb)
1523 if (!lex.setFile(real_file)) {
1524 lyxerr << "LyXTextClassList::Read: "
1525 "lyxlex was not able to set file: "
1526 << real_file << endl;
1530 lyxerr << "LyXTextClassList::Read: unable to open "
1531 "textclass file `" << MakeDisplayPath(real_file, 1000)
1532 << "'\nCheck your installation. LyX can't continue."
1536 bool finished = false;
1537 string fname, clname, desc;
1538 // Parse config-file
1539 lyxerr[Debug::TCLASS] << "Starting parsing of textclass.lst" << endl;
1540 while (lex.IsOK() && !finished) {
1541 lyxerr[Debug::TCLASS] << "\tline by line" << endl;
1542 switch (lex.lex()) {
1543 case LyXLex::LEX_FEOF:
1547 fname = lex.GetString();
1548 lyxerr[Debug::TCLASS] << "Fname: " << fname << endl;
1550 clname = lex.GetString();
1551 lyxerr[Debug::TCLASS]
1552 << "Clname: " << clname << endl;
1554 desc = lex.GetString();
1555 lyxerr[Debug::TCLASS]
1556 << "Desc: " << desc << endl;
1557 // This code is run when we have
1558 // fname, clname and desc
1559 LyXTextClass tmpl(fname,
1563 debugging(Debug::TCLASS)) {
1571 lyxerr[Debug::TCLASS] << "End of parsing of textclass.lst" << endl;
1573 if (classlist.size() == 0) {
1574 lyxerr << "LyXTextClassList::Read: no textclasses found!"
1576 WriteAlert(_("LyX wasn't able to find any layout description!"),
1577 _("Check the contents of the file \"textclass.lst\""),
1578 _("Sorry, has to exit :-("));
1581 // Ok everything loaded ok, now sort the list.
1582 sort(classlist.begin(), classlist.end(), less_textclass_desc());
1588 Returns false if this fails
1591 LyXTextClassList::Load (LyXTextClassList::size_type number) const
1594 if (number < classlist.size()) {
1595 classlist[number].load();
1596 if (classlist[number].numLayouts() == 0) {