diff --git a/src/tex2lyx/preamble.cpp b/src/tex2lyx/preamble.cpp index cc2dacad73..06a97e0b00 100644 --- a/src/tex2lyx/preamble.cpp +++ b/src/tex2lyx/preamble.cpp @@ -50,6 +50,12 @@ extern std::map special_columns; std::map > used_packages; +// needed to handle encodings with babel +bool one_language = true; + +// to avoid that the babel options overwrite the documentclass options +bool documentclass_language; + namespace { const char * const known_languages[] = { "afrikaans", "american", "austrian", @@ -67,7 +73,12 @@ const char * const known_languages[] = { "afrikaans", "american", "austrian", "thai", "turkish", "ukraineb", "ukrainian", "usorbian", "welsh", 0}; 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 }; const char * const known_roman_fonts[] = { "ae", "bookman", "charter", @@ -120,19 +131,40 @@ 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) { it = find(opts.begin(), opts.end(), *what); if (it != opts.end()) { - target = *what; - // remove found options from the list - 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: @@ -246,14 +278,41 @@ void handle_package(string const & name, string const & opts) else if (name == "amsmath" || name == "amssymb") h_use_amsmath = "1"; - else if (name == "babel") - ; // ignore this + 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; + } + } else if (name == "fontenc") ; // ignore this else if (name == "inputenc") { // only set when there is not more than one inputenc option // therefore check for the "," character - if (opts.find(",") == string::npos) + // also only set when there is not more then one babel language option + if (opts.find(",") == string::npos && one_language == true) h_inputencoding = opts; options.clear(); } else if (name == "makeidx") @@ -263,13 +322,19 @@ void handle_package(string const & name, string const & opts) else if (name == "graphicx") ; // ignore this 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; } else if (name == "natbib") { h_cite_engine = "natbib_authoryear"; @@ -470,14 +535,26 @@ TextClass const parse_preamble(Parser & p, ostream & os, string const & forcecla else if (t.cs() == "documentclass") { vector opts = split_options(p.getArg('[', ']')); - handle_opt(opts, known_languages, h_language); - if (is_known(h_language, known_french_languages)) - h_language = "french"; 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; h_options = join(opts, ","); h_textclass = p.getArg('{', '}');