X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftex2lyx%2Fpreamble.cpp;h=4dd8d7f28addd729cf2f2bc08a0adbab126f4edd;hb=c9a726bd43ed568a6fb3e9e4ce1d759f16790d3a;hp=db16af20815700728b67eef83187232154e6b7dc;hpb=04591a6e34a0ac52632f3a309df9ff375a91b713;p=lyx.git diff --git a/src/tex2lyx/preamble.cpp b/src/tex2lyx/preamble.cpp index db16af2081..4dd8d7f28a 100644 --- a/src/tex2lyx/preamble.cpp +++ b/src/tex2lyx/preamble.cpp @@ -3,7 +3,8 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author André Pönitz + * \author André Pönitz + * \author Uwe Stöhr * * Full author contact details are available in file CREDITS. */ @@ -14,12 +15,18 @@ #include "tex2lyx.h" -#include "layout.h" -#include "LyXTextClass.h" -#include "LyXLex.h" +#include "LayoutFile.h" +#include "Layout.h" +#include "Lexer.h" +#include "TextClass.h" + +#include "support/convert.h" +#include "support/FileName.h" #include "support/filetools.h" #include "support/lstrings.h" +#include + #include #include #include @@ -27,58 +34,94 @@ #include #include +using namespace std; +using namespace lyx::support; +using boost::regex; +using boost::smatch; namespace lyx { -using std::istringstream; -using std::ostream; -using std::ostringstream; -using std::string; -using std::vector; -using std::cerr; -using std::endl; +// special columntypes +extern map special_columns; -using support::FileName; -using support::libFileSearch; +map > used_packages; -// special columntypes -extern std::map special_columns; +// needed to handle encodings with babel +bool one_language = true; -std::map > used_packages; +// to avoid that the babel options overwrite the documentclass options +bool documentclass_language; namespace { -const char * const known_languages[] = { "austrian", "babel", "bahasa", -"basque", "breton", "british", "bulgarian", "catalan", "croatian", "czech", -"danish", "dutch", "english", "esperanto", "estonian", "finnish", -"francais", "french", "frenchb", "frenchle", "frenchpro", -"galician", "german", "germanb", "greek", "hebcal", "hebfont", -"hebrew", "hebrew_newcode", "hebrew_oldcode", "hebrew_p", "hyphen", -"icelandic", "irish", "italian", "latin", "lgrcmr", "lgrcmro", "lgrcmss", -"lgrcmtt", "lgrenc", "lgrlcmss", "lgrlcmtt", "lheclas", "lhecmr", -"lhecmss", "lhecmtt", "lhecrml", "lheenc", "lhefr", "lheredis", "lheshold", -"lheshscr", "lheshstk", "lsorbian", "magyar", "naustrian", "ngermanb", -"ngerman", "norsk", "polish", "portuges", "rlbabel", "romanian", -"russianb", "samin", "scottish", "serbian", "slovak", "slovene", "spanish", -"swedish", "turkish", "ukraineb", "usorbian", "welsh", 0}; +const char * const known_languages[] = { "afrikaans", "american", "arabic", +"austrian", "bahasa", "basque", "belarusian", "brazil", "breton", "british", +"bulgarian", "canadian", "canadien", "catalan", "croatian", "czech", "danish", +"dutch", "english", "esperanto", "estonian", "finnish", "francais", "french", +"frenchb", "frenchle", "frenchpro", "galician", "german", "germanb", "greek", +"hebrew", "icelandic", "irish", "italian", "lsorbian", "magyar", "naustrian", +"ngerman", "ngermanb", "norsk", "nynorsk", "polish", "portuges", "romanian", +"russian", "russianb", "scottish", "serbian", "slovak", "slovene", "spanish", +"swedish", "thai", "turkish", "ukraineb", "ukrainian", "usorbian", "welsh", 0}; + +//note this when updating to lyxformat 305: +//bahasai, indonesian, and indon = equal to bahasa +//malay, and meyalu = equal to bahasam const char * const known_french_languages[] = {"french", "frenchb", "francais", - "frenchle", "frenchpro", 0}; + "frenchle", "frenchpro", 0}; +const char * const known_german_languages[] = {"german", "germanb", 0}; +const char * const known_ngerman_languages[] = {"ngerman", "ngermanb", 0}; +const char * const known_russian_languages[] = {"russian", "russianb", 0}; +const char * const known_ukrainian_languages[] = {"ukrainian", "ukraineb", 0}; + char const * const known_fontsizes[] = { "10pt", "11pt", "12pt", 0 }; -// some ugly stuff +const char * const known_roman_fonts[] = { "ae", "bookman", "charter", +"cmr", "fourier", "lmodern", "mathpazo", "mathptmx", "newcent", 0}; + +const char * const known_sans_fonts[] = { "avant", "berasans", "cmbr", "cmss", +"helvet", "lmss", 0}; + +const char * const known_typewriter_fonts[] = { "beramono", "cmtl", "cmtt", +"courier", "lmtt", "luximono", "fourier", "lmodern", "mathpazo", "mathptmx", +"newcent", 0}; + +const char * const known_paper_sizes[] = { "a3paper", "b3paper", "a4paper", +"b4paper", "a5paper", "b5paper", "executivepaper", "legalpaper", +"letterpaper", 0}; + +const char * const known_class_paper_sizes[] = { "a4paper", "a5paper", +"executivepaper", "legalpaper", "letterpaper", 0}; + +const char * const known_paper_margins[] = { "lmargin", "tmargin", "rmargin", +"bmargin", "headheight", "headsep", "footskip", "columnsep", 0}; + +const char * const known_coded_paper_margins[] = { "leftmargin", "topmargin", +"rightmargin", "bottommargin", "headheight", "headsep", "footskip", +"columnsep", 0}; + +// default settings ostringstream h_preamble; string h_textclass = "article"; string h_options = string(); string h_language = "english"; -string h_inputencoding = "latin1"; -string h_fontscheme = "default"; +string h_inputencoding = "auto"; +string h_font_roman = "default"; +string h_font_sans = "default"; +string h_font_typewriter = "default"; +string h_font_default_family = "default"; +string h_font_sc = "false"; +string h_font_osf = "false"; +string h_font_sf_scale = "100"; +string h_font_tt_scale = "100"; string h_graphics = "default"; string h_paperfontsize = "default"; string h_spacing = "single"; string h_papersize = "default"; string h_use_geometry = "false"; -string h_use_amsmath = "0"; +string h_use_amsmath = "1"; +string h_use_esint = "1"; string h_cite_engine = "basic"; string h_use_bibtopic = "false"; string h_paperorientation = "portrait"; @@ -92,6 +135,7 @@ string h_papersides = string(); string h_paperpagestyle = "default"; string h_tracking_changes = "false"; string h_output_changes = "false"; +string h_margins = ""; void handle_opt(vector & opts, char const * const * what, string & target) @@ -99,18 +143,40 @@ void handle_opt(vector & opts, char const * const * what, string & targe if (opts.empty()) return; - for ( ; *what; ++what) { - vector::iterator it = find(opts.begin(), opts.end(), *what); + // the last language option is the document language (for babel and LyX) + // the last size option is the document font size + vector::iterator it; + vector::iterator position = opts.begin(); + for (; *what; ++what) { + it = find(opts.begin(), opts.end(), *what); if (it != opts.end()) { - //cerr << "### found option '" << *what << "'\n"; - target = *what; - opts.erase(it); - return; + documentclass_language = true; + if (it >= position) { + target = *what; + position = it; + } } } } +void delete_opt(vector & opts, char const * const * what) +{ + if (opts.empty()) + return; + + // remove found options from the list + // do this after handle_opt to avoid potential memory leaks and to be able + // to find in every case the last language option + vector::iterator it; + for (; *what; ++what) { + it = find(opts.begin(), opts.end(), *what); + if (it != opts.end()) + opts.erase(it); + } +} + + /*! * Split a package options string (keyval format) into a vector. * Example input: @@ -127,7 +193,7 @@ vector split_options(string const & input) while (p.good()) { Token const & t = p.get_token(); if (t.asInput() == ",") { - options.push_back(option); + options.push_back(trim(option)); option.erase(); } else if (t.asInput() == "=") { option += '='; @@ -139,7 +205,7 @@ vector split_options(string const & input) } if (!option.empty()) - options.push_back(option); + options.push_back(trim(option)); return options; } @@ -168,43 +234,189 @@ void add_package(string const & name, vector & options) } -void handle_package(string const & name, string const & opts) +// Given is a string like "scaled=0.9", return 0.9 * 100 +string const scale_as_percentage(string const & scale) +{ + string::size_type pos = scale.find('='); + if (pos != string::npos) { + string value = scale.substr(pos + 1); + if (isStrDbl(value)) + return convert(100 * convert(value)); + } + // If the input string didn't match our expectations. + // return the default value "100" + return "100"; +} + + +void handle_package(Parser &p, string const & name, string const & opts, + bool in_lyx_preamble) { vector options = split_options(opts); add_package(name, options); + string scale; + + // roman fonts + if (is_known(name, known_roman_fonts)) { + h_font_roman = name; + p.skip_spaces(); + } + + if (name == "fourier") { + h_font_roman = "utopia"; + // when font uses real small capitals + if (opts == "expert") + h_font_sc = "true"; + p.skip_spaces(); + } + + if (name == "mathpazo") { + h_font_roman = "palatino"; + p.skip_spaces(); + } + + if (name == "mathptmx") { + h_font_roman = "times"; + p.skip_spaces(); + } + + // sansserif fonts + if (is_known(name, known_sans_fonts)) { + h_font_sans = name; + if (!opts.empty()) { + scale = opts; + h_font_sf_scale = scale_as_percentage(scale); + } + p.skip_spaces(); + } - //cerr << "handle_package: '" << name << "'\n"; - if (name == "ae") - h_fontscheme = "ae"; - else if (name == "aecompl") - h_fontscheme = "ae"; - else if (name == "amsmath") - h_use_amsmath = "1"; - else if (name == "amssymb") - h_use_amsmath = "1"; - else if (name == "babel") - ; // ignore this + // typewriter fonts + if (is_known(name, known_typewriter_fonts)) { + h_font_typewriter = name; + if (!opts.empty()) { + scale = opts; + h_font_tt_scale = scale_as_percentage(scale); + } + p.skip_spaces(); + } + + // font uses old-style figure + if (name == "eco") { + h_font_osf = "true"; + p.skip_spaces(); + } + + else if (name == "amsmath" || name == "amssymb") { + h_use_amsmath = "2"; + p.skip_spaces(); + } + + else if (name == "esint") { + h_use_esint = "2"; + p.skip_spaces(); + } + + else if (name == "babel" && !opts.empty()) { + // check if more than one option was used - used later for inputenc + // in case inputenc is parsed before babel, set the encoding to auto + if (options.begin() != options.end() - 1) { + one_language = false; + h_inputencoding = "auto"; + } + // only set the document language when there was not already one set + // via the documentclass options + // babel takes the the last language given in the documentclass options + // as document language. If there is no such language option, the last + // option of its \usepackage call is used. + if (documentclass_language == false) { + handle_opt(options, known_languages, h_language); + delete_opt(options, known_languages); + if (is_known(h_language, known_french_languages)) + h_language = "french"; + else if (is_known(h_language, known_german_languages)) + h_language = "german"; + else if (is_known(h_language, known_ngerman_languages)) + h_language = "ngerman"; + else if (is_known(h_language, known_russian_languages)) + h_language = "russian"; + else if (is_known(h_language, known_ukrainian_languages)) + h_language = "ukrainian"; + h_quotes_language = h_language; + } + p.skip_spaces(); + } else if (name == "fontenc") - ; // ignore this + p.skip_spaces(); // ignore this + else if (name == "inputenc") { - h_inputencoding = opts; + // only set when there is not more than one inputenc + // option therefore check for the "," character also + // only set when there is not more then one babel + // language option + if (opts.find(",") == string::npos && one_language == true) { + if (opts == "ascii") + //change ascii to auto to be in the unicode range, see + //http://bugzilla.lyx.org/show_bug.cgi?id=4719 + h_inputencoding = "auto"; + else if (!opts.empty()) + h_inputencoding = opts; + } + if (!options.empty()) + p.setEncoding(options.back()); options.clear(); - } else if (name == "makeidx") - ; // ignore this + p.skip_spaces(); + } + + else if (name == "makeidx") + p.skip_spaces(); // ignore this + + else if (name == "prettyref") + p.skip_spaces(); // ignore this + + else if (name == "varioref") + p.skip_spaces(); // ignore this + else if (name == "verbatim") - ; // ignore this + p.skip_spaces(); // ignore this + + else if (name == "url") + p.skip_spaces(); // ignore this + + else if (name == "color") { + // with the following command this package is only loaded when needed for + // undefined colors, since we only support the predefined colors + h_preamble << "\\@ifundefined{definecolor}\n {\\usepackage{color}}{}\n"; + p.skip_spaces(); + } + else if (name == "graphicx") - ; // ignore this + p.skip_spaces(); // ignore this + + else if (name == "setspace") + p.skip_spaces(); // ignore this + + else if (name == "geometry") + p.skip_spaces(); // Ignore this, the geometry settings are made by the \geometry + // command. This command is handled below. + else if (is_known(name, known_languages)) { - if (is_known(name, known_french_languages)) { + if (is_known(name, known_french_languages)) h_language = "french"; - h_quotes_language = "french"; - } else { + else if (is_known(name, known_german_languages)) + h_language = "german"; + else if (is_known(name, known_ngerman_languages)) + h_language = "ngerman"; + else if (is_known(name, known_russian_languages)) + h_language = "russian"; + else if (is_known(name, known_ukrainian_languages)) + h_language = "ukrainian"; + else h_language = name; - h_quotes_language = name; - } + h_quotes_language = h_language; + p.skip_spaces(); + } - } else if (name == "natbib") { + else if (name == "natbib") { h_cite_engine = "natbib_authoryear"; vector::iterator it = find(options.begin(), options.end(), "authoryear"); @@ -217,13 +429,22 @@ void handle_package(string const & name, string const & opts) options.erase(it); } } - } else if (name == "jurabib") { + p.skip_spaces(); + } + + else if (name == "jurabib") { h_cite_engine = "jurabib"; - } else if (options.empty()) - h_preamble << "\\usepackage{" << name << "}\n"; - else { - h_preamble << "\\usepackage[" << opts << "]{" << name << "}\n"; - options.clear(); + p.skip_spaces(); + } + + else if (!in_lyx_preamble) { + if (options.empty()) + h_preamble << "\\usepackage{" << name << "}"; + else { + h_preamble << "\\usepackage[" << opts << "]{" + << name << "}"; + options.clear(); + } } // We need to do something with the options... @@ -234,28 +455,38 @@ void handle_package(string const & name, string const & opts) -void end_preamble(ostream & os, LyXTextClass const & /*textclass*/) +void end_preamble(ostream & os, TextClass const & /*textclass*/) { - os << "#LyX file created by tex2lyx 0.1.2\n" - << "\\lyxformat 245\n" + os << "#LyX file created by tex2lyx " << PACKAGE_VERSION << "\n" + << "\\lyxformat 256\n" << "\\begin_document\n" << "\\begin_header\n" - << "\\textclass " << h_textclass << "\n" - << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n"; + << "\\textclass " << h_textclass << "\n"; + if (!h_preamble.str().empty()) + os << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n"; if (!h_options.empty()) - os << "\\options " << h_options << "\n"; + os << "\\options " << h_options << "\n"; os << "\\language " << h_language << "\n" << "\\inputencoding " << h_inputencoding << "\n" - << "\\fontscheme " << h_fontscheme << "\n" + << "\\font_roman " << h_font_roman << "\n" + << "\\font_sans " << h_font_sans << "\n" + << "\\font_typewriter " << h_font_typewriter << "\n" + << "\\font_default_family " << h_font_default_family << "\n" + << "\\font_sc " << h_font_sc << "\n" + << "\\font_osf " << h_font_osf << "\n" + << "\\font_sf_scale " << h_font_sf_scale << "\n" + << "\\font_tt_scale " << h_font_tt_scale << "\n" << "\\graphics " << h_graphics << "\n" << "\\paperfontsize " << h_paperfontsize << "\n" << "\\spacing " << h_spacing << "\n" << "\\papersize " << h_papersize << "\n" << "\\use_geometry " << h_use_geometry << "\n" << "\\use_amsmath " << h_use_amsmath << "\n" + << "\\use_esint " << h_use_esint << "\n" << "\\cite_engine " << h_cite_engine << "\n" << "\\use_bibtopic " << h_use_bibtopic << "\n" << "\\paperorientation " << h_paperorientation << "\n" + << h_margins << "\\secnumdepth " << h_secnumdepth << "\n" << "\\tocdepth " << h_tocdepth << "\n" << "\\paragraph_separation " << h_paragraph_separation << "\n" @@ -274,11 +505,14 @@ void end_preamble(ostream & os, LyXTextClass const & /*textclass*/) } // anonymous namespace -LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & forceclass) +void parse_preamble(Parser & p, ostream & os, + string const & forceclass, TeX2LyXDocClass & tc) { // initialize fixed types special_columns['D'] = 3; bool is_full_document = false; + bool is_lyx_file = false; + bool in_lyx_preamble = false; // determine whether this is a full document or a fragment for inclusion while (p.good()) { @@ -301,35 +535,66 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force // // cat codes // - if (t.cat() == catLetter || - t.cat() == catSuper || - t.cat() == catSub || - t.cat() == catOther || - t.cat() == catMath || - t.cat() == catActive || - t.cat() == catBegin || - t.cat() == catEnd || - t.cat() == catAlign || - t.cat() == catParameter) - h_preamble << t.character(); - - else if (t.cat() == catSpace || t.cat() == catNewline) + if (!in_lyx_preamble && + (t.cat() == catLetter || + t.cat() == catSuper || + t.cat() == catSub || + t.cat() == catOther || + t.cat() == catMath || + t.cat() == catActive || + t.cat() == catBegin || + t.cat() == catEnd || + t.cat() == catAlign || + t.cat() == catParameter)) + h_preamble << t.character(); + + else if (!in_lyx_preamble && + (t.cat() == catSpace || t.cat() == catNewline)) h_preamble << t.asInput(); - else if (t.cat() == catComment) - h_preamble << t.asInput(); + else if (t.cat() == catComment) { + // regex to parse comments + static regex const islyxfile("%% LyX .* created this file"); + static regex const usercommands("User specified LaTeX commands"); + + string const comment = t.asInput(); + + // magically switch encoding default if it looks like XeLaTeX + static string const magicXeLaTeX = + "% This document must be compiled with XeLaTeX "; + if (comment.size() > magicXeLaTeX.size() + && comment.substr(0, magicXeLaTeX.size()) == magicXeLaTeX + && h_inputencoding == "auto") { + cerr << "XeLaTeX comment found, switching to UTF8\n"; + h_inputencoding = "utf8"; + } + + smatch sub; + if (regex_search(comment, sub, islyxfile)) { + is_lyx_file = true; + in_lyx_preamble = true; + } else if (is_lyx_file + && regex_search(comment, sub, usercommands)) + in_lyx_preamble = false; + else if (!in_lyx_preamble) + h_preamble << t.asInput(); + } else if (t.cs() == "pagestyle") h_paperpagestyle = p.verbatim_item(); else if (t.cs() == "makeatletter") { + if (!is_lyx_file || !in_lyx_preamble + || p.getCatCode('@') != catLetter) + h_preamble << "\\makeatletter"; p.setCatCode('@', catLetter); - h_preamble << "\\makeatletter"; } else if (t.cs() == "makeatother") { + if (!is_lyx_file || !in_lyx_preamble + || p.getCatCode('@') != catOther) + h_preamble << "\\makeatother"; p.setCatCode('@', catOther); - h_preamble << "\\makeatother"; } else if (t.cs() == "newcommand" || t.cs() == "renewcommand" @@ -343,16 +608,26 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force string const opt1 = p.getOpt(); string const opt2 = p.getFullOpt(); string const body = p.verbatim_item(); + // font settings + if (name == "\\rmdefault") + if (is_known(body, known_roman_fonts)) + h_font_roman = body; + + if (name == "\\sfdefault") + if (is_known(body, known_sans_fonts)) + h_font_sans = body; + + if (name == "\\ttdefault") + if (is_known(body, known_typewriter_fonts)) + h_font_typewriter = body; + + if (name == "\\familydefault") { + string family = body; + // remove leading "\" + h_font_default_family = family.erase(0,1); + } // only non-lyxspecific stuff - if ( name != "\\noun" - && name != "\\tabularnewline" - && name != "\\LyX" - && name != "\\lyxline" - && name != "\\lyxaddress" - && name != "\\lyxrightaddress" - && name != "\\lyxdot" - && name != "\\boldsymbol" - && name != "\\lyxarrow") { + if (!in_lyx_preamble) { ostringstream ss; ss << '\\' << t.cs(); if (star) @@ -372,17 +647,62 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force } else if (t.cs() == "documentclass") { - vector opts; - split(p.getArg('[', ']'), opts, ','); - handle_opt(opts, known_languages, h_language); - if (is_known(h_language, known_french_languages)) - h_language = "french"; + vector::iterator it; + vector opts = split_options(p.getArg('[', ']')); handle_opt(opts, known_fontsizes, h_paperfontsize); + delete_opt(opts, known_fontsizes); // delete "pt" at the end string::size_type i = h_paperfontsize.find("pt"); if (i != string::npos) h_paperfontsize.erase(i); + // to avoid that the babel options overwrite the documentclass options + documentclass_language = false; + handle_opt(opts, known_languages, h_language); + delete_opt(opts, known_languages); + if (is_known(h_language, known_french_languages)) + h_language = "french"; + else if (is_known(h_language, known_german_languages)) + h_language = "german"; + else if (is_known(h_language, known_ngerman_languages)) + h_language = "ngerman"; + else if (is_known(h_language, known_russian_languages)) + h_language = "russian"; + else if (is_known(h_language, known_ukrainian_languages)) + h_language = "ukrainian"; h_quotes_language = h_language; + // paper orientation + if ((it = find(opts.begin(), opts.end(), "landscape")) != opts.end()) { + h_paperorientation = "landscape"; + opts.erase(it); + } + // paper sides + if ((it = find(opts.begin(), opts.end(), "oneside")) + != opts.end()) { + h_papersides = "1"; + opts.erase(it); + } + if ((it = find(opts.begin(), opts.end(), "twoside")) + != opts.end()) { + h_papersides = "2"; + opts.erase(it); + } + // paper columns + if ((it = find(opts.begin(), opts.end(), "onecolumn")) + != opts.end()) { + h_papercolumns = "1"; + opts.erase(it); + } + if ((it = find(opts.begin(), opts.end(), "twocolumn")) + != opts.end()) { + h_papercolumns = "2"; + opts.erase(it); + } + // paper sizes + // some size options are know to any document classes, other sizes + // are handled by the \geometry command of the geometry package + handle_opt(opts, known_class_paper_sizes, h_papersize); + delete_opt(opts, known_class_paper_sizes); + // the remaining options h_options = join(opts, ","); h_textclass = p.getArg('{', '}'); } @@ -390,16 +710,19 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force else if (t.cs() == "usepackage") { string const options = p.getArg('[', ']'); string const name = p.getArg('{', '}'); - if (options.empty() && name.find(',')) { - vector vecnames; - split(name, vecnames, ','); - vector::const_iterator it = vecnames.begin(); - vector::const_iterator end = vecnames.end(); - for (; it != end; ++it) - handle_package(trim(*it), string()); - } else { - handle_package(name, options); - } + vector vecnames; + split(name, vecnames, ','); + vector::const_iterator it = vecnames.begin(); + vector::const_iterator end = vecnames.end(); + for (; it != end; ++it) + handle_package(p, trim(*it), options, + in_lyx_preamble); + } + + else if (t.cs() == "inputencoding") { + string const encoding = p.getArg('{','}'); + h_inputencoding = encoding; + p.setEncoding(encoding); } else if (t.cs() == "newenvironment") { @@ -410,9 +733,7 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force ss << p.getOpt(); ss << '{' << p.verbatim_item() << '}'; ss << '{' << p.verbatim_item() << '}'; - if (name != "lyxcode" && name != "lyxlist" && - name != "lyxrightadress" && - name != "lyxaddress" && name != "lyxgreyedout") + if (!in_lyx_preamble) h_preamble << ss.str(); } @@ -420,8 +741,9 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force string name = p.get_token().cs(); while (p.next_token().cat() != catBegin) name += p.get_token().asString(); - h_preamble << "\\def\\" << name << '{' - << p.verbatim_item() << "}"; + if (!in_lyx_preamble) + h_preamble << "\\def\\" << name << '{' + << p.verbatim_item() << "}"; } else if (t.cs() == "newcolumntype") { @@ -431,7 +753,6 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force string opts = p.getOpt(); if (!opts.empty()) { istringstream is(string(opts, 1)); - //cerr << "opt: " << is.str() << "\n"; is >> nargs; } special_columns[name[0]] = nargs; @@ -455,15 +776,32 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force else if (t.cs() == "setlength") { string const name = p.verbatim_item(); string const content = p.verbatim_item(); - // Is this correct? - if (name == "parskip") - h_paragraph_separation = "skip"; - else if (name == "parindent") - h_paragraph_separation = "skip"; - else + // the paragraphs are only not indented when \parindent is set to zero + if (name == "\\parindent" && content != "") { + if (content[0] == '0') + h_paragraph_separation = "skip"; + } else if (name == "\\parskip") { + if (content == "\\smallskipamount") + h_defskip = "smallskip"; + else if (content == "\\medskipamount") + h_defskip = "medskip"; + else if (content == "\\bigskipamount") + h_defskip = "bigskip"; + else + h_defskip = content; + } else h_preamble << "\\setlength{" << name << "}{" << content << "}"; } + else if (t.cs() == "onehalfspacing") + h_spacing = "onehalf"; + + else if (t.cs() == "doublespacing") + h_spacing = "double"; + + else if (t.cs() == "setstretch") + h_spacing = "other " + p.verbatim_item(); + else if (t.cs() == "begin") { string const name = p.getArg('{', '}'); if (name == "document") @@ -471,6 +809,35 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force h_preamble << "\\begin{" << name << "}"; } + else if (t.cs() == "geometry") { + h_use_geometry = "true"; + vector opts = split_options(p.getArg('{', '}')); + vector::iterator it; + // paper orientation + if ((it = find(opts.begin(), opts.end(), "landscape")) != opts.end()) { + h_paperorientation = "landscape"; + opts.erase(it); + } + // paper size + handle_opt(opts, known_paper_sizes, h_papersize); + delete_opt(opts, known_paper_sizes); + // page margins + char const * const * margin = known_paper_margins; + int k = -1; + for (; *margin; ++margin) { + k += 1; + // search for the "=" in e.g. "lmargin=2cm" to get the value + for(size_t i = 0; i != opts.size(); i++) { + if (opts.at(i).find(*margin) != string::npos) { + string::size_type pos = opts.at(i).find("="); + string value = opts.at(i).substr(pos + 1); + string name = known_coded_paper_margins[k]; + h_margins += "\\" + name + " " + value + "\n"; + } + } + } + } + else if (t.cs() == "jurabibsetup") { vector jurabibsetup = split_options(p.getArg('{', '}')); @@ -482,7 +849,7 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force } } - else if (!t.cs().empty()) + else if (!t.cs().empty() && !in_lyx_preamble) h_preamble << '\\' << t.cs(); } p.skip_spaces(); @@ -490,22 +857,20 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force // Force textclass if the user wanted it if (!forceclass.empty()) h_textclass = forceclass; - if (noweb_mode && !lyx::support::prefixIs(h_textclass, "literate-")) + if (noweb_mode && !prefixIs(h_textclass, "literate-")) h_textclass.insert(0, "literate-"); FileName layoutfilename = libFileSearch("layouts", h_textclass, "layout"); if (layoutfilename.empty()) { cerr << "Error: Could not find layout file for textclass \"" << h_textclass << "\"." << endl; exit(1); } - LyXTextClass textclass; - textclass.read(layoutfilename); + tc.read(layoutfilename); if (h_papersides.empty()) { ostringstream ss; - ss << textclass.sides(); + ss << tc.sides(); h_papersides = ss.str(); } - end_preamble(os, textclass); - return textclass; + end_preamble(os, tc); } // }])