X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftex2lyx%2FPreamble.cpp;h=82135a8621d7db71741c74ebbe49ff93d24b192c;hb=9631c36ff061d2f32561094b59e24198f66be018;hp=781ce2cc7997ec1f81e06c0157ea37d223356f30;hpb=e31981a414c56da0e2d41d43d645ed0b4efcb42f;p=lyx.git diff --git a/src/tex2lyx/Preamble.cpp b/src/tex2lyx/Preamble.cpp index 781ce2cc79..82135a8621 100644 --- a/src/tex2lyx/Preamble.cpp +++ b/src/tex2lyx/Preamble.cpp @@ -16,6 +16,7 @@ #include "Preamble.h" #include "tex2lyx.h" +#include "Encoding.h" #include "LayoutFile.h" #include "Layout.h" #include "Lexer.h" @@ -44,16 +45,11 @@ Preamble preamble; namespace { -//add this to known_languages when updating to lyxformat 266: -// "armenian" (needs special handling since not supported by standard babel) -//add these to known_languages when updating to lyxformat 268: -//"chinese-simplified", "chinese-traditional", "japanese", "korean" -// Both changes require first that support for non-babel languages (CJK, -// armtex) is added. +// CJK languages are handled in text.cpp, polyglossia languages are listed +// further down. /** * known babel language names (including synonyms) * not in standard babel: arabic, arabtex, armenian, belarusian, serbian-latin, thai - * not yet supported by LyX: kurmanji * please keep this in sync with known_coded_languages line by line! */ const char * const known_languages[] = {"acadian", "afrikaans", "albanian", @@ -63,9 +59,9 @@ const char * const known_languages[] = {"acadian", "afrikaans", "albanian", "dutch", "english", "esperanto", "estonian", "farsi", "finnish", "francais", "french", "frenchb", "frenchle", "frenchpro", "galician", "german", "germanb", "greek", "hebrew", "hungarian", "icelandic", "indon", "indonesian", "interlingua", -"irish", "italian", "kazakh", "latin", "latvian", "lithuanian", "lowersorbian", -"lsorbian", "magyar", "malay", "meyalu", "mongolian", "naustrian", "newzealand", -"ngerman", "ngermanb", "norsk", "nynorsk", "polutonikogreek", "polish", +"irish", "italian", "japanese", "kazakh", "kurmanji", "latin", "latvian", "lithuanian", +"lowersorbian", "lsorbian", "magyar", "malay", "meyalu", "mongolian", "naustrian", +"newzealand", "ngerman", "ngermanb", "norsk", "nynorsk", "polutonikogreek", "polish", "portuges", "portuguese", "romanian", "russian", "russianb", "samin", "scottish", "serbian", "serbian-latin", "slovak", "slovene", "spanish", "swedish", "thai", "turkish", "turkmen", "ukraineb", "ukrainian", @@ -83,49 +79,17 @@ const char * const known_coded_languages[] = {"french", "afrikaans", "albanian", "dutch", "english", "esperanto", "estonian", "farsi", "finnish", "french", "french", "french", "french", "french", "galician", "german", "german", "greek", "hebrew", "magyar", "icelandic", "bahasa", "bahasa", "interlingua", -"irish", "italian", "kazakh", "latin", "latvian", "lithuanian", "lowersorbian", -"lowersorbian", "magyar", "bahasam", "bahasam", "mongolian", "naustrian", "newzealand", -"ngerman", "ngerman", "norsk", "nynorsk", "polutonikogreek", "polish", +"irish", "italian", "japanese", "kazakh", "kurmanji", "latin", "latvian", "lithuanian", +"lowersorbian", "lowersorbian", "magyar", "bahasam", "bahasam", "mongolian", "naustrian", +"newzealand", "ngerman", "ngerman", "norsk", "nynorsk", "polutonikogreek", "polish", "portuguese", "portuguese", "romanian", "russian", "russian", "samin", "scottish", "serbian", "serbian-latin", "slovak", "slovene", "spanish", "swedish", "thai", "turkish", "turkmen", "ukrainian", "ukrainian", "uppersorbian", "uppersorbian", "english", "english", "vietnamese", "welsh", 0}; -/** - * known polyglossia language names (including variants) - */ -const char * const polyglossia_languages[] = { -"albanian", "croatian", "hebrew", "norsk", "swedish", "amharic", "czech", "hindi", -"nynorsk", "syriac", "arabic", "danish", "icelandic", "occitan", "tamil", -"armenian", "divehi", "interlingua", "polish", "telugu", "asturian", "dutch", -"irish", "portuges", "thai", "bahasai", "english", "italian", "romanian", "turkish", -"bahasam", "esperanto", "lao", "russian", "turkmen", "basque", "estonian", "latin", -"samin", "ukrainian", "bengali", "farsi", "latvian", "sanskrit", "urdu", "brazil", -"brazilian", "finnish", "lithuanian", "scottish", "usorbian", "breton", "french", -"lsorbian", "serbian", "vietnamese", "bulgarian", "galician", "magyar", "slovak", -"welsh", "catalan", "german", "malayalam", "slovenian", "coptic", "greek", -"marathi", "spanish", -"american", "ancient", "australian", "british", "monotonic", "newzealand", -"polytonic", 0}; - -/** - * the same as polyglossia_languages with .lyx names - * please keep this in sync with polyglossia_languages line by line! - */ -const char * const coded_polyglossia_languages[] = { -"albanian", "croatian", "hebrew", "norsk", "swedish", "amharic", "czech", "hindi", -"nynorsk", "syriac", "arabic_arabi", "danish", "icelandic", "occitan", "tamil", -"armenian", "divehi", "interlingua", "polish", "telugu", "asturian", "dutch", -"irish", "portuges", "thai", "bahasa", "english", "italian", "romanian", "turkish", -"bahasam", "esperanto", "lao", "russian", "turkmen", "basque", "estonian", "latin", -"samin", "ukrainian", "bengali", "farsi", "latvian", "sanskrit", "urdu", "brazilian", -"brazilian", "finnish", "lithuanian", "scottish", "uppersorbian", "breton", "french", -"lowersorbian", "serbian", "vietnamese", "bulgarian", "galician", "magyar", "slovak", -"welsh", "catalan", "ngerman", "malayalam", "slovene", "coptic", "greek", -"marathi", "spanish", -"american", "ancientgreek", "australian", "british", "greek", "newzealand", -"polutonikogreek", 0}; +/// languages with danish quotes (.lyx names) +const char * const known_danish_quotes_languages[] = {"danish", 0}; /// languages with english quotes (.lyx names) const char * const known_english_quotes_languages[] = {"american", "australian", @@ -160,15 +124,21 @@ const char * const known_old_language_packages[] = {"french", "frenchle", char const * const known_fontsizes[] = { "10pt", "11pt", "12pt", 0 }; const char * const known_roman_fonts[] = { "ae", "beraserif", "bookman", -"ccfonts", "chancery", "charter", "cmr", "fourier", "lmodern", "mathpazo", -"mathptmx", "newcent", "utopia", 0}; +"ccfonts", "chancery", "charter", "cmr", "fourier", "garamondx", "libertine", +"libertine-type1", "lmodern", "mathdesign", "mathpazo", "mathptmx", "newcent", +"tgbonum", "tgchorus", "tgpagella", "tgschola", "tgtermes", "utopia", 0}; -const char * const known_sans_fonts[] = { "avant", "berasans", "cmbr", "cmss", -"helvet", "lmss", 0}; +const char * const known_sans_fonts[] = { "avant", "berasans", "biolinum-type1", +"cmbr", "cmss", "helvet", "kurier", "kurierl", "lmss", "tgadventor", "tgheros", 0}; + +const char * const known_kurier_fonts[] = { "kurier", "kurierl", "kurier-condensed", +"kurier-light-condensed", 0}; const char * const known_typewriter_fonts[] = { "beramono", "cmtl", "cmtt", "courier", "lmtt", "luximono", "fourier", "lmodern", "mathpazo", "mathptmx", -"newcent", 0}; +"newcent", "tgcursor", "txtt", 0}; + +const char * const known_math_fonts[] = { "eulervm", "newtxmath", 0}; const char * const known_paper_sizes[] = { "a0paper", "b0paper", "c0paper", "a1paper", "b1paper", "c1paper", "a2paper", "b2paper", "c2paper", "a3paper", @@ -209,8 +179,8 @@ const char * const known_xetex_packages[] = {"arabxetex", "fixlatvian", /// packages that are automatically skipped if loaded by LyX const char * const known_lyx_packages[] = {"amsbsy", "amsmath", "amssymb", -"amstext", "amsthm", "array", "booktabs", "calc", "color", "float", "fontspec", -"graphicx", "hhline", "ifthen", "longtable", "makeidx", "multirow", +"amstext", "amsthm", "array", "babel", "booktabs", "calc", "CJK", "color", "float", +"fontspec", "graphicx", "hhline", "ifthen", "longtable", "makeidx", "multirow", "nomencl", "pdfpages", "rotating", "rotfloat", "splitidx", "setspace", "subscript", "textcomp", "ulem", "url", "varioref", "verbatim", "wrapfig", "xunicode", 0}; @@ -321,6 +291,42 @@ string process_keyval_opt(vector & options, string name) } // anonymous namespace +/** + * known polyglossia language names (including variants) + */ +const char * const Preamble::polyglossia_languages[] = { +"albanian", "croatian", "hebrew", "norsk", "swedish", "amharic", "czech", "hindi", +"nynorsk", "syriac", "arabic", "danish", "icelandic", "occitan", "tamil", +"armenian", "divehi", "interlingua", "polish", "telugu", "asturian", "dutch", +"irish", "portuges", "thai", "bahasai", "english", "italian", "romanian", "turkish", +"bahasam", "esperanto", "lao", "russian", "turkmen", "basque", "estonian", "latin", +"samin", "ukrainian", "bengali", "farsi", "latvian", "sanskrit", "urdu", "brazil", +"brazilian", "finnish", "lithuanian", "scottish", "usorbian", "breton", "french", +"lsorbian", "serbian", "vietnamese", "bulgarian", "galician", "magyar", "slovak", +"welsh", "catalan", "german", "malayalam", "slovenian", "coptic", "greek", +"marathi", "spanish", +"american", "ancient", "australian", "british", "monotonic", "newzealand", +"polytonic", 0}; + +/** + * the same as polyglossia_languages with .lyx names + * please keep this in sync with polyglossia_languages line by line! + */ +const char * const Preamble::coded_polyglossia_languages[] = { +"albanian", "croatian", "hebrew", "norsk", "swedish", "amharic", "czech", "hindi", +"nynorsk", "syriac", "arabic_arabi", "danish", "icelandic", "occitan", "tamil", +"armenian", "divehi", "interlingua", "polish", "telugu", "asturian", "dutch", +"irish", "portuges", "thai", "bahasa", "english", "italian", "romanian", "turkish", +"bahasam", "esperanto", "lao", "russian", "turkmen", "basque", "estonian", "latin", +"samin", "ukrainian", "bengali", "farsi", "latvian", "sanskrit", "urdu", "brazilian", +"brazilian", "finnish", "lithuanian", "scottish", "uppersorbian", "breton", "french", +"lowersorbian", "serbian", "vietnamese", "bulgarian", "galician", "magyar", "slovak", +"welsh", "catalan", "ngerman", "malayalam", "slovene", "coptic", "greek", +"marathi", "spanish", +"american", "ancientgreek", "australian", "british", "greek", "newzealand", +"polutonikogreek", 0}; + + bool Preamble::indentParagraphs() const { return h_paragraph_separation == "indent"; @@ -406,18 +412,18 @@ void Preamble::add_package(string const & name, vector & options) namespace { -// Given is a string like "scaled=0.9", return 0.9 * 100 -string const scale_as_percentage(string const & scale) +// Given is a string like "scaled=0.9" or "Scale=0.9", return 0.9 * 100 +bool scale_as_percentage(string const & scale, string & percentage) { 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 (isStrDbl(value)) { + percentage = convert(100 * convert(value)); + return true; + } } - // If the input string didn't match our expectations. - // return the default value "100" - return "100"; + return false; } @@ -433,13 +439,16 @@ string remove_braces(string const & value) } // anonymous namespace -Preamble::Preamble() : one_language(true), title_layout_found(false) +Preamble::Preamble() : one_language(true), title_layout_found(false), + h_font_cjk_set(false) { //h_backgroundcolor; //h_boxbgcolor; h_biblio_style = "plain"; + h_bibtex_command = "default"; h_cite_engine = "basic"; h_cite_engine_type = "numerical"; + h_color = "#008000"; h_defskip = "medskip"; //h_float_placement; //h_fontcolor; @@ -447,26 +456,33 @@ Preamble::Preamble() : one_language(true), title_layout_found(false) h_font_roman = "default"; h_font_sans = "default"; h_font_typewriter = "default"; + h_font_math = "auto"; h_font_default_family = "default"; h_use_non_tex_fonts = "false"; h_font_sc = "false"; h_font_osf = "false"; h_font_sf_scale = "100"; h_font_tt_scale = "100"; + //h_font_cjk h_graphics = "default"; h_default_output_format = "default"; h_html_be_strict = "false"; h_html_css_as_file = "0"; h_html_math_output = "0"; + h_index = "Index"; + h_index_command = "default"; h_inputencoding = "auto"; h_justification = "true"; h_language = "english"; h_language_package = "none"; //h_listings_params; + h_maintain_unincluded_children = "false"; //h_margins; //h_notefontcolor; //h_options; h_output_changes = "false"; + h_output_sync = "0"; + //h_output_sync_macro h_papercolumns = "1"; h_paperfontsize = "default"; h_paperorientation = "portrait"; @@ -492,6 +508,7 @@ Preamble::Preamble() : one_language(true), title_layout_found(false) //h_pdf_quoted_options; h_quotes_language = "english"; h_secnumdepth = "3"; + h_shortcut = "idx"; h_spacing = "single"; h_suppress_date = "false"; h_textclass = "article"; @@ -501,7 +518,7 @@ Preamble::Preamble() : one_language(true), title_layout_found(false) h_use_indices = "false"; h_use_geometry = "false"; h_use_default_options = "false"; - h_use_hyperref = "0"; + h_use_hyperref = "false"; h_use_refstyle = "0"; h_use_packages["amsmath"] = "1"; h_use_packages["amssymb"] = "0"; @@ -509,6 +526,8 @@ Preamble::Preamble() : one_language(true), title_layout_found(false) h_use_packages["mhchem"] = "0"; h_use_packages["mathdots"] = "0"; h_use_packages["mathtools"] = "0"; + h_use_packages["stackrel"] = "0"; + h_use_packages["stmaryrd"] = "0"; h_use_packages["undertilde"] = "0"; } @@ -517,7 +536,7 @@ void Preamble::handle_hyperref(vector & options) { // FIXME swallow inputencoding changes that might surround the // hyperref setup if it was written by LyX - h_use_hyperref = "1"; + h_use_hyperref = "true"; // swallow "unicode=true", since LyX does always write that vector::iterator it = find(options.begin(), options.end(), "unicode=true"); @@ -632,21 +651,19 @@ void Preamble::handle_package(Parser &p, string const & name, { vector options = split_options(opts); add_package(name, options); - string scale; + char const * const * where = 0; if (is_known(name, known_xetex_packages)) { xetex = true; h_use_non_tex_fonts = "true"; registerAutomaticallyLoadedPackage("fontspec"); if (h_inputencoding == "auto") - p.setEncoding("utf8"); + p.setEncoding("UTF-8"); } // roman fonts - if (is_known(name, known_roman_fonts)) { + if (is_known(name, known_roman_fonts)) h_font_roman = name; - p.skip_spaces(); - } if (name == "fourier") { h_font_roman = "utopia"; @@ -655,6 +672,45 @@ void Preamble::handle_package(Parser &p, string const & name, h_font_sc = "true"; } + if (name == "garamondx") { + h_font_roman = "garamondx"; + if (opts == "osfI") + h_font_osf = "true"; + } + + if (name == "libertine") { + h_font_roman = "libertine"; + // this automatically invokes biolinum + h_font_sans = "biolinum"; + if (opts == "osf") + h_font_osf = "true"; + else if (opts == "lining") + h_font_osf = "false"; + } + + if (name == "libertine-type1") { + h_font_roman = "libertine"; + // NOTE: contrary to libertine.sty, libertine-type1 + // does not automatically invoke biolinum + if (opts == "lining") + h_font_osf = "false"; + else if (opts == "osf") + h_font_osf = "true"; + } + + if (name == "mathdesign") { + if (opts.find("charter") != string::npos) + h_font_roman = "md-charter"; + if (opts.find("garamond") != string::npos) + h_font_roman = "md-garamond"; + if (opts.find("utopia") != string::npos) + h_font_roman = "md-utopia"; + if (opts.find("expert") != string::npos) { + h_font_sc = "true"; + h_font_osf = "true"; + } + } + else if (name == "mathpazo") h_font_roman = "palatino"; @@ -664,21 +720,24 @@ void Preamble::handle_package(Parser &p, string const & name, // 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); + if (options.size() == 1) { + if (scale_as_percentage(opts, h_font_sf_scale)) + options.clear(); } } + if (name == "biolinum-type1") + h_font_sans = "biolinum"; + // typewriter fonts if (is_known(name, known_typewriter_fonts)) { // fourier can be set as roman font _only_ // fourier as typewriter is handled in handling of \ttdefault if (name != "fourier") { h_font_typewriter = name; - if (!opts.empty()) { - scale = opts; - h_font_tt_scale = scale_as_percentage(scale); + if (options.size() == 1) { + if (scale_as_percentage(opts, h_font_tt_scale)) + options.clear(); } } } @@ -687,15 +746,34 @@ void Preamble::handle_package(Parser &p, string const & name, if (name == "eco") h_font_osf = "true"; + // math fonts + if (is_known(name, known_math_fonts)) + h_font_math = name; + + if (name == "newtxmath") { + if (opts.empty()) + h_font_math = "newtxmath"; + else if (opts == "garamondx") + h_font_math = "garamondx-ntxm"; + else if (opts == "libertine") + h_font_math = "libertine-ntxm"; + else if (opts == "minion") + h_font_math = "minion-ntxm"; + } + + if (name == "refstyle") + h_use_refstyle = "1"; + // after the detection and handling of special cases, we can remove the // fonts, otherwise they would appear in the preamble, see bug #7856 if (is_known(name, known_roman_fonts) || is_known(name, known_sans_fonts) - || is_known(name, known_typewriter_fonts)) + || is_known(name, known_typewriter_fonts) || is_known(name, known_math_fonts)) ; else if (name == "amsmath" || name == "amssymb" || name == "esint" || name == "mhchem" || name == "mathdots" || - name == "mathtools" || name == "undertilde") + name == "mathtools" || name == "stackrel" || + name == "stmaryrd" || name == "undertilde") h_use_packages[name] = "2"; else if (name == "babel") { @@ -713,16 +791,34 @@ void Preamble::handle_package(Parser &p, string const & name, // call as document language. If there is no such language option, the // last language in the documentclass options is used. handle_opt(options, known_languages, h_language); - // If babel is called with options, LyX puts them by default into the - // document class options. This works for most languages, except - // for Latvian, Lithuanian, Mongolian, Turkmen and Vietnamese and - // perhaps in future others. - // Therefore keep the babel call as it is as the user might have - // reasons for it. - h_preamble << "\\usepackage[" << opts << "]{babel}\n"; - delete_opt(options, known_languages); - // finally translate the babel name to a LyX name + // translate the babel name to a LyX name h_language = babel2lyx(h_language); + if (h_language == "japanese") { + // For Japanese, the encoding isn't indicated in the source + // file, and there's really not much we can do. We could + // 1) offer a list of possible encodings to choose from, or + // 2) determine the encoding of the file by inspecting it. + // For the time being, we leave the encoding alone so that + // we don't get iconv errors when making a wrong guess, and + // we will output a note at the top of the document + // explaining what to do. + Encoding const * const enc = encodings.fromIconvName( + p.getEncoding(), Encoding::japanese, false); + if (enc) + h_inputencoding = enc->name(); + is_nonCJKJapanese = true; + // in this case babel can be removed from the preamble + registerAutomaticallyLoadedPackage("babel"); + } else { + // If babel is called with options, LyX puts them by default into the + // document class options. This works for most languages, except + // for Latvian, Lithuanian, Mongolian, Turkmen and Vietnamese and + // perhaps in future others. + // Therefore keep the babel call as it is as the user might have + // reasons for it. + h_preamble << "\\usepackage[" << opts << "]{babel}\n"; + } + delete_opt(options, known_languages); } else h_preamble << "\\usepackage{babel}\n"; @@ -735,7 +831,21 @@ void Preamble::handle_package(Parser &p, string const & name, xetex = true; registerAutomaticallyLoadedPackage("xunicode"); if (h_inputencoding == "auto") - p.setEncoding("utf8"); + p.setEncoding("UTF-8"); + } + + else if (name == "CJK") { + // set the encoding to "auto" because it might be set to "default" by the babel handling + // and this would not be correct for CJK + if (h_inputencoding == "default") + h_inputencoding = "auto"; + registerAutomaticallyLoadedPackage("CJK"); + } + + else if (name == "CJKutf8") { + h_inputencoding = "UTF8"; + p.setEncoding("UTF-8"); + registerAutomaticallyLoadedPackage("CJKutf8"); } else if (name == "fontenc") { @@ -758,10 +868,19 @@ void Preamble::handle_package(Parser &p, string const & name, if (opts.find(",") == string::npos && one_language == true) h_inputencoding = opts; if (!options.empty()) - p.setEncoding(options.back()); + p.setEncoding(options.back(), Encoding::inputenc); options.clear(); } + else if (name == "srcltx") { + h_output_sync = "1"; + if (!opts.empty()) { + h_output_sync_macro = "\\usepackage[" + opts + "]{srcltx}"; + options.clear(); + } else + h_output_sync_macro = "\\usepackage{srcltx}"; + } + else if (is_known(name, known_old_language_packages)) { // known language packages from the times before babel // if they are found and not also babel, they will be used as @@ -781,10 +900,16 @@ void Preamble::handle_package(Parser &p, string const & name, else if (is_known(name, known_lyx_packages) && options.empty()) { if (name == "splitidx") h_use_indices = "true"; - if (!in_lyx_preamble) + if (!in_lyx_preamble) { h_preamble << package_beg_sep << name << package_mid_sep << "\\usepackage{" - << name << "}\n" << package_end_sep; + << name << '}'; + if (p.next_token().cat() == catNewline || + (p.next_token().cat() == catSpace && + p.next_next_token().cat() == catNewline)) + h_preamble << '\n'; + h_preamble << package_end_sep; + } } else if (name == "geometry") @@ -793,8 +918,8 @@ void Preamble::handle_package(Parser &p, string const & name, else if (name == "subfig") ; // ignore this FIXME: Use the package separator mechanism instead - else if (is_known(name, known_languages)) - h_language = name; + else if ((where = is_known(name, known_languages))) + h_language = known_coded_languages[where - known_languages]; else if (name == "natbib") { h_biblio_style = "plainnat"; @@ -824,12 +949,16 @@ void Preamble::handle_package(Parser &p, string const & name, else if (!in_lyx_preamble) { if (options.empty()) - h_preamble << "\\usepackage{" << name << "}\n"; + h_preamble << "\\usepackage{" << name << '}'; else { h_preamble << "\\usepackage[" << opts << "]{" - << name << "}\n"; + << name << '}'; options.clear(); } + if (p.next_token().cat() == catNewline || + (p.next_token().cat() == catSpace && + p.next_next_token().cat() == catNewline)) + h_preamble << '\n'; } // We need to do something with the options... @@ -870,7 +999,7 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc) // http://en.wikipedia.org/wiki/Quotation_mark,_non-English_usage // (quotes for kazakh and interlingua are unknown) // danish - if (h_language == "danish") + if (is_known(h_language, known_danish_quotes_languages)) h_quotes_language = "danish"; // french else if (is_known(h_language, known_french_quotes_languages)) @@ -939,27 +1068,36 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc) os << *it << '\n'; os << "\\end_modules\n"; } - os << "\\language " << h_language << "\n" + os << "\\maintain_unincluded_children " << h_maintain_unincluded_children << "\n" + << "\\language " << h_language << "\n" << "\\language_package " << h_language_package << "\n" << "\\inputencoding " << h_inputencoding << "\n" << "\\fontencoding " << h_fontencoding << "\n" << "\\font_roman " << h_font_roman << "\n" << "\\font_sans " << h_font_sans << "\n" << "\\font_typewriter " << h_font_typewriter << "\n" + << "\\font_math " << h_font_math << "\n" << "\\font_default_family " << h_font_default_family << "\n" << "\\use_non_tex_fonts " << h_use_non_tex_fonts << "\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" - << "\\default_output_format " << h_default_output_format << "\n"; + << "\\font_tt_scale " << h_font_tt_scale << '\n'; + if (!h_font_cjk.empty()) + os << "\\font_cjk " << h_font_cjk << '\n'; + os << "\\graphics " << h_graphics << '\n' + << "\\default_output_format " << h_default_output_format << "\n" + << "\\output_sync " << h_output_sync << "\n"; + if (h_output_sync == "1") + os << "\\output_sync_macro \"" << h_output_sync_macro << "\"\n"; + os << "\\bibtex_command " << h_bibtex_command << "\n" + << "\\index_command " << h_index_command << "\n"; if (!h_float_placement.empty()) os << "\\float_placement " << h_float_placement << "\n"; os << "\\paperfontsize " << h_paperfontsize << "\n" << "\\spacing " << h_spacing << "\n" << "\\use_hyperref " << h_use_hyperref << '\n'; - if (h_use_hyperref == "1") { + if (h_use_hyperref == "true") { if (!h_pdf_title.empty()) os << "\\pdf_title \"" << h_pdf_title << "\"\n"; if (!h_pdf_author.empty()) @@ -1004,6 +1142,10 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc) os << "\\backgroundcolor " << h_backgroundcolor << '\n'; if (!h_boxbgcolor.empty()) os << "\\boxbgcolor " << h_boxbgcolor << '\n'; + os << "\\index " << h_index << '\n' + << "\\shortcut " << h_shortcut << '\n' + << "\\color " << h_color << '\n' + << "\\end_index\n"; os << h_margins << "\\secnumdepth " << h_secnumdepth << "\n" << "\\tocdepth " << h_tocdepth << "\n" @@ -1115,12 +1257,13 @@ void Preamble::parse(Parser & p, string const & forceclass, // check if the option contains a variant, if yes, extract it string::size_type pos_var = langopts.find("variant"); string::size_type i = langopts.find(',', pos_var); + string::size_type k = langopts.find('=', pos_var); if (pos_var != string::npos){ string variant; if (i == string::npos) - variant = langopts.substr(pos_var + 8, langopts.length() - pos_var - 9); + variant = langopts.substr(k + 1, langopts.length() - k - 2); else - variant = langopts.substr(pos_var + 8, i - pos_var - 8); + variant = langopts.substr(k + 1, i - k - 1); h_language = variant; } p.verbatim_item(); @@ -1135,9 +1278,6 @@ void Preamble::parse(Parser & p, string const & forceclass, // support this yet, see bug #8214 p.hasOpt() ? p.getOpt() : string(); p.verbatim_item(); - // FIXME: there can be multiple occurences of - // \setotherlanguage, we need to handle them all not only the - // first one } else if (t.cs() == "setmainfont") { @@ -1146,16 +1286,30 @@ void Preamble::parse(Parser & p, string const & forceclass, h_font_roman = p.getArg('{', '}'); } - else if (t.cs() == "setsansfont") { - // we don't care about the option - p.hasOpt() ? p.getOpt() : string(); - h_font_sans = p.getArg('{', '}'); - } - - else if (t.cs() == "setmonofont") { - // we don't care about the option - p.hasOpt() ? p.getOpt() : string(); - h_font_typewriter = p.getArg('{', '}'); + else if (t.cs() == "setsansfont" || t.cs() == "setmonofont") { + // LyX currently only supports the scale option + string scale; + if (p.hasOpt()) { + string fontopts = p.getArg('[', ']'); + // check if the option contains a scaling, if yes, extract it + string::size_type pos = fontopts.find("Scale"); + if (pos != string::npos) { + string::size_type i = fontopts.find(',', pos); + if (i == string::npos) + scale_as_percentage(fontopts.substr(pos + 1), scale); + else + scale_as_percentage(fontopts.substr(pos, i - pos), scale); + } + } + if (t.cs() == "setsansfont") { + if (!scale.empty()) + h_font_sf_scale = scale; + h_font_sans = p.getArg('{', '}'); + } else { + if (!scale.empty()) + h_font_tt_scale = scale; + h_font_typewriter = p.getArg('{', '}'); + } } else if (t.cs() == "date") { @@ -1208,12 +1362,12 @@ void Preamble::parse(Parser & p, string const & forceclass, else if (t.cs() == "makeatletter") { // LyX takes care of this - p.setCatCode('@', catLetter); + p.setCatcode('@', catLetter); } else if (t.cs() == "makeatother") { // LyX takes care of this - p.setCatCode('@', catOther); + p.setCatcode('@', catOther); } else if (t.cs() == "newcommand" || t.cs() == "newcommandx" @@ -1232,26 +1386,48 @@ void Preamble::parse(Parser & p, string const & forceclass, string const opt1 = p.getFullOpt(); string const opt2 = p.getFullOpt(); string const body = p.verbatim_item(); + // store the in_lyx_preamble setting + bool const was_in_lyx_preamble = in_lyx_preamble; // font settings if (name == "\\rmdefault") - if (is_known(body, known_roman_fonts)) + if (is_known(body, known_roman_fonts)) { h_font_roman = body; + p.skip_spaces(); + in_lyx_preamble = true; + } if (name == "\\sfdefault") - if (is_known(body, known_sans_fonts)) + if (is_known(body, known_sans_fonts)) { h_font_sans = body; + p.skip_spaces(); + in_lyx_preamble = true; + } if (name == "\\ttdefault") - if (is_known(body, known_typewriter_fonts)) + if (is_known(body, known_typewriter_fonts)) { h_font_typewriter = body; + p.skip_spaces(); + in_lyx_preamble = true; + } if (name == "\\familydefault") { string family = body; // remove leading "\" h_font_default_family = family.erase(0,1); + p.skip_spaces(); + in_lyx_preamble = true; } + if (name == "\\bfdefault") + // LyX re-adds this if a kurier font is used + if (is_known(h_font_sans, known_kurier_fonts) && body == "b") { + p.skip_spaces(); + in_lyx_preamble = true; + } + // remove the lyxdot definition that is re-added by LyX // if necessary - if (name == "\\lyxdot") + if (name == "\\lyxdot") { + p.skip_spaces(); in_lyx_preamble = true; + } // Add the command to the known commands add_known_command(name, opt1, !opt2.empty(), from_utf8(body)); @@ -1271,6 +1447,24 @@ void Preamble::parse(Parser & p, string const & forceclass, << opts << "{" << body << "}"; */ } + // restore the in_lyx_preamble setting + in_lyx_preamble = was_in_lyx_preamble; + } + + else if (t.cs() == "edef"){ + // we only support this for kurier fonts + string const command = p.next_token().asInput(); + p.get_token(); + if (command == "\\sfdefault") { + p.getArg('{', '}'); + if (h_font_sans == "kurier") + h_font_sans = "kurier-condensed"; + if (h_font_sans == "kurierl") + h_font_sans = "kurier-light-condensed"; + p.skip_spaces(); + } + else + h_preamble << "\\edef" << command << "{" << p.getArg('{', '}') << "}\n"; } else if (t.cs() == "documentclass") { @@ -1325,6 +1519,7 @@ void Preamble::parse(Parser & p, string const & forceclass, // FIXME This does not work for classes that have a // different name in LyX than in LaTeX h_textclass = p.getArg('{', '}'); + p.skip_spaces(); } else if (t.cs() == "usepackage") { @@ -1342,7 +1537,7 @@ void Preamble::parse(Parser & p, string const & forceclass, else if (t.cs() == "inputencoding") { string const encoding = p.getArg('{','}'); h_inputencoding = encoding; - p.setEncoding(encoding); + p.setEncoding(encoding, Encoding::inputenc); } else if (t.cs() == "newenvironment") { @@ -1361,6 +1556,22 @@ void Preamble::parse(Parser & p, string const & forceclass, } + else if (t.cs() == "newtheorem") { + string const name = p.getArg('{', '}'); + string const opt1 = p.getFullOpt(); + string const opt2 = p.getFullOpt(); + string const body = p.verbatim_item(); + string const opt3 = p.getFullOpt(); + + add_known_theorem(name, opt1, !opt2.empty(), + from_utf8("\\newtheorem{" + name + '}' + + opt1 + opt2 + '{' + body + '}' + opt3)); + + if (!in_lyx_preamble) + h_preamble << "\\newtheorem{" << name << '}' + << opt1 << opt2 << '{' << '}' << opt3; + } + else if (t.cs() == "def") { string name = p.get_token().cs(); // In fact, name may be more than the name: @@ -1432,6 +1643,19 @@ void Preamble::parse(Parser & p, string const & forceclass, else if (t.cs() == "setstretch") h_spacing = "other " + p.verbatim_item(); + else if (t.cs() == "synctex") { + // the scheme is \synctex=value + // where value can only be "1" or "-1" + h_output_sync = "1"; + // there can be any character behind the value (e.g. a linebreak or a '\' + // therefore we extract it char by char + p.get_token(); + string value = p.get_token().asInput(); + if (value == "-") + value += p.get_token().asInput(); + h_output_sync_macro = "\\synctex=" + value; + } + else if (t.cs() == "begin") { string const name = p.getArg('{', '}'); if (name == "document") @@ -1552,8 +1776,6 @@ void Preamble::parse(Parser & p, string const & forceclass, // Force textclass if the user wanted it if (!forceclass.empty()) h_textclass = forceclass; - if (noweb_mode && !prefixIs(h_textclass, "literate-")) - h_textclass.insert(0, "literate-"); tc.setName(h_textclass); if (!tc.load()) { cerr << "Error: Could not read layout file for textclass \"" << h_textclass << "\"." << endl; @@ -1564,6 +1786,18 @@ void Preamble::parse(Parser & p, string const & forceclass, ss << tc.sides(); h_papersides = ss.str(); } + + // If the CJK package is used we cannot set the document language from + // the babel options. Instead, we guess which language is used most + // and set this one. + default_language = h_language; + if (is_full_document && + (auto_packages.find("CJK") != auto_packages.end() || + auto_packages.find("CJKutf8") != auto_packages.end())) { + p.pushPosition(); + h_language = guessLanguage(p, default_language); + p.popPosition(); + } } @@ -1576,7 +1810,7 @@ string babel2lyx(string const & language) } -string polyglossia2lyx(string const & language) +string Preamble::polyglossia2lyx(string const & language) { char const * const * where = is_known(language, polyglossia_languages); if (where)