X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftex2lyx%2Fpreamble.cpp;h=4dd8d7f28addd729cf2f2bc08a0adbab126f4edd;hb=c9a726bd43ed568a6fb3e9e4ce1d759f16790d3a;hp=77f72cdb315eaac7172cebebd3aef71b63094e3d;hpb=116740d7e35b3f9e54e87afdc7aa00ad62364947;p=lyx.git diff --git a/src/tex2lyx/preamble.cpp b/src/tex2lyx/preamble.cpp index 77f72cdb31..4dd8d7f28a 100644 --- a/src/tex2lyx/preamble.cpp +++ b/src/tex2lyx/preamble.cpp @@ -3,8 +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 Uwe Stöhr + * \author André Pönitz + * \author Uwe Stöhr * * Full author contact details are available in file CREDITS. */ @@ -15,12 +15,18 @@ #include "tex2lyx.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 @@ -28,48 +34,48 @@ #include #include +using namespace std; +using namespace lyx::support; +using boost::regex; +using boost::smatch; namespace lyx { -using std::find; -using std::istringstream; -using std::ostream; -using std::ostringstream; -using std::string; -using std::vector; -using std::cerr; -using std::endl; -using std::find; +// 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[] = { "afrikaans", "albanian", "american", -"arabic_arabtex", "arabic_arabi", "armenian", "austrian", "bahasa", "basque", -"brazilian", "breton", "british", "bulgarian", "canadian", "canadien", -"catalan", "chinese-simplified", "chinese-traditional", "croatian", "czech", -"danish", "dutch", "english", "esperanto", "estonian", "farsi", "finnish", -"francais", "french", "galician", "german", "greek", "hebrew", "icelandic", -"irish", "italian", "japanese", "japanese-plain", "kazakh", "korean", "latin", -"latvian", "lithuanian", "lowersorbian", "magyar", "naustrian", "ngerman", -"norsk", "nynorsk ", "polish", "portuges", "romanian", "russian", "samin", -"scottish", "serbian", "slovak", "slovene", "spanish", "swedish", "thai", -"turkish", "ukrainian", "uppersorbian", "vietnamese", "welsh", 0}; - -const char * const known_fontsizes[] = { "10pt", "11pt", "12pt", 0 }; - -const char * const known_encodings[] = { "auto", "latin1", "latin2", "latin3", -"latin4", "latin5", "latin9", "latin10", "iso88595", "8859-6", "iso-8859-7", -"8859-8", "l7xen", "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", -"cp862", "cp865", "cp866", "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", -"cp1257", "koi8-r", "koi8-u", "pt154", "pt254", "utf8", 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}; +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 }; const char * const known_roman_fonts[] = { "ae", "bookman", "charter", "cmr", "fourier", "lmodern", "mathpazo", "mathptmx", "newcent", 0}; @@ -81,41 +87,55 @@ const char * const known_typewriter_fonts[] = { "beramono", "cmtl", "cmtt", "courier", "lmtt", "luximono", "fourier", "lmodern", "mathpazo", "mathptmx", "newcent", 0}; -// some ugly stuff +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 = "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 = "1"; -string h_use_esint = "1"; -string h_cite_engine = "basic"; -string h_use_bibtopic = "false"; -string h_paperorientation = "portrait"; -string h_secnumdepth = "3"; -string h_tocdepth = "3"; -string h_paragraph_separation = "indent"; -string h_defskip = "medskip"; -string h_quotes_language = "english"; -string h_papercolumns = "1"; -string h_papersides = string(); -string h_paperpagestyle = "default"; -string h_tracking_changes = "false"; -string h_output_changes = "false"; -string h_use_hyperref = "false"; +string h_textclass = "article"; +string h_options = string(); +string h_language = "english"; +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 = "1"; +string h_use_esint = "1"; +string h_cite_engine = "basic"; +string h_use_bibtopic = "false"; +string h_paperorientation = "portrait"; +string h_secnumdepth = "3"; +string h_tocdepth = "3"; +string h_paragraph_separation = "indent"; +string h_defskip = "medskip"; +string h_quotes_language = "english"; +string h_papercolumns = "1"; +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) @@ -123,18 +143,39 @@ void handle_opt(vector & opts, char const * const * what, string & targe if (opts.empty()) return; + // 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) { - vector::iterator it = find(opts.begin(), opts.end(), *what); - // the last language option is the document language + it = find(opts.begin(), opts.end(), *what); if (it != opts.end()) { - //cerr << "### found option '" << *what << "'\n"; - target = *what; - opts.erase(it); + 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. @@ -152,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 += '='; @@ -164,7 +205,7 @@ vector split_options(string const & input) } if (!option.empty()) - options.push_back(option); + options.push_back(trim(option)); return options; } @@ -193,67 +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); - size_t pos; string scale; - // cerr << "handle_package: '" << name << "'\n"; - // roman fonts - if (is_known(name, known_roman_fonts)) + if (is_known(name, known_roman_fonts)) { h_font_roman = name; - if (name == "fourier") + p.skip_spaces(); + } + + if (name == "fourier") { h_font_roman = "utopia"; - if (name == "mathpazo") + // when font uses real small capitals + if (opts == "expert") + h_font_sc = "true"; + p.skip_spaces(); + } + + if (name == "mathpazo") { h_font_roman = "palatino"; - if (name == "mathptmx") + 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; - pos = scale.find(".", 0); - h_font_sf_scale = scale.erase(0, pos + 1); + h_font_sf_scale = scale_as_percentage(scale); } + p.skip_spaces(); } + // typewriter fonts if (is_known(name, known_typewriter_fonts)) { h_font_typewriter = name; if (!opts.empty()) { scale = opts; - pos = scale.find(".", 0); - h_font_tt_scale = scale.erase(0, pos + 1); + 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 == "amssymb") + else if (name == "amsmath" || name == "amssymb") { h_use_amsmath = "2"; - else if (name == "esint") + p.skip_spaces(); + } + + else if (name == "esint") { h_use_esint = "2"; - else if (name == "babel") - ; // ignore this + 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") { - // only set when there are not more than one inputenc option - // therefore check for the "," character - if ((pos = opts.find(",", 0)) == string::npos) - 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)) { - h_language = name; - h_quotes_language = name; - } else if (name == "natbib") { + if (is_known(name, known_french_languages)) + h_language = "french"; + 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 = h_language; + p.skip_spaces(); + } + + else if (name == "natbib") { h_cite_engine = "natbib_authoryear"; vector::iterator it = find(options.begin(), options.end(), "authoryear"); @@ -266,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... @@ -282,10 +454,11 @@ void handle_package(string const & name, string const & opts) } + void end_preamble(ostream & os, TextClass const & /*textclass*/) { - os << "#LyX file created by tex2lyx 0.1.5\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"; @@ -306,7 +479,6 @@ void end_preamble(ostream & os, TextClass const & /*textclass*/) << "\\graphics " << h_graphics << "\n" << "\\paperfontsize " << h_paperfontsize << "\n" << "\\spacing " << h_spacing << "\n" - << "\\use_hyperref " << h_use_hyperref << "\n" << "\\papersize " << h_papersize << "\n" << "\\use_geometry " << h_use_geometry << "\n" << "\\use_amsmath " << h_use_amsmath << "\n" @@ -314,6 +486,7 @@ void end_preamble(ostream & os, TextClass const & /*textclass*/) << "\\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" @@ -332,12 +505,14 @@ void end_preamble(ostream & os, TextClass const & /*textclass*/) } // anonymous namespace - -TextClass 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()) { @@ -360,32 +535,67 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla // // 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) - ;//h_preamble << t.asInput(); - - else if (t.cat() == catComment) - ;//h_preamble << t.asInput(); + 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) { + // 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") + else if (t.cs() == "makeatletter") { + if (!is_lyx_file || !in_lyx_preamble + || p.getCatCode('@') != catLetter) + h_preamble << "\\makeatletter"; p.setCatCode('@', catLetter); + } - else if (t.cs() == "makeatother") + else if (t.cs() == "makeatother") { + if (!is_lyx_file || !in_lyx_preamble + || p.getCatCode('@') != catOther) + h_preamble << "\\makeatother"; p.setCatCode('@', catOther); + } else if (t.cs() == "newcommand" || t.cs() == "renewcommand" || t.cs() == "providecommand") { @@ -417,19 +627,7 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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" - && name != "\\rmdefault" - && name != "\\sfdefault" - && name != "\\ttdefault" - && name != "\\familydefault") { + if (!in_lyx_preamble) { ostringstream ss; ss << '\\' << t.cs(); if (star) @@ -446,19 +644,65 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla << opts << "{" << body << "}"; */ } - } else if (t.cs() == "documentclass") { - vector opts; - split(p.getArg('[', ']'), opts, ','); + vector::iterator it; + vector opts = split_options(p.getArg('[', ']')); handle_opt(opts, known_fontsizes, h_paperfontsize); - handle_opt(opts, known_languages, h_language); + 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('{', '}'); } @@ -466,16 +710,19 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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") { @@ -486,9 +733,7 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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(); } @@ -496,8 +741,9 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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") { @@ -507,7 +753,6 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla string opts = p.getOpt(); if (!opts.empty()) { istringstream is(string(opts, 1)); - //cerr << "opt: " << is.str() << "\n"; is >> nargs; } special_columns[name[0]] = nargs; @@ -531,15 +776,32 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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") @@ -547,6 +809,35 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla 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('{', '}')); @@ -558,7 +849,7 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla } } - else if (!t.cs().empty()) + else if (!t.cs().empty() && !in_lyx_preamble) h_preamble << '\\' << t.cs(); } p.skip_spaces(); @@ -566,25 +857,22 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla // 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); } - TextClass 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); } - // }])