X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeXFeatures.cpp;h=bcf9ddc82d7c1cf4cf5391bb70260bce7548d1db;hb=e11c7cb71da01989da9370c10e30af0c6a21a1f4;hp=4f3b87886cbe6f24d9d1b81f21748feab49b597a;hpb=8415041b1f4d7a2e436e3f407bccd9a7e6bcdd87;p=lyx.git diff --git a/src/LaTeXFeatures.cpp b/src/LaTeXFeatures.cpp index 4f3b87886c..bcf9ddc82d 100644 --- a/src/LaTeXFeatures.cpp +++ b/src/LaTeXFeatures.cpp @@ -27,8 +27,8 @@ #include "LaTeXFonts.h" #include "LaTeXPackages.h" #include "Layout.h" -#include "Lexer.h" #include "LyXRC.h" +#include "OutputParams.h" #include "TextClass.h" #include "TexRow.h" #include "texstream.h" @@ -37,13 +37,12 @@ #include "support/debug.h" #include "support/docstream.h" -#include "support/FileName.h" +#include "support/docstring.h" #include "support/filetools.h" -#include "support/gettext.h" #include "support/lstrings.h" -#include "support/regex.h" #include +#include using namespace std; @@ -74,6 +73,11 @@ static docstring const lyxarrow_def = from_ascii( "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n" "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}"); +static docstring const aastex_case_def = from_ascii( + "\\providecommand\\case[2]{\\mbox{$\\frac{#1}{#2}$}}%"); +// Copied from https://github.com/AASJournals/AASTeX60/blob/master/cls/aastex63.cls#L1645 +// Adapted to providecommand for compatibility reasons. + // ZERO WIDTH SPACE (ZWSP) is actually not a space character // but marks a line break opportunity. Several commands provide a // line break opportunity. They differ in side-effects: @@ -189,44 +193,11 @@ static docstring const tabularnewline_def = from_ascii( "%% Because html converters don't know tabularnewline\n" "\\providecommand{\\tabularnewline}{\\\\}\n"); -static docstring const lyxgreyedout_def = from_ascii( - "%% The greyedout annotation environment\n" - "\\newenvironment{lyxgreyedout}\n" - " {\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n" - " {\\ignorespacesafterend\\egroup}\n"); - -static docstring const lyxgreyedout_rtl_def = from_ascii( - "%% The greyedout annotation environment (with RTL support)\n" - "\\NewEnviron{lyxgreyedout}{%\n" - "\\if@rl%\n" - "\\everypar{\\textcolor{note_fontcolor}\\beginL\\ignorespaces}%\n" - "\\BODY\\everypar{\\ignorespacesafterend\\endL}\n" - "\\else%\n" - "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n" - "\\BODY\\ignorespacesafterend\\egroup\n" - "\\fi}\n"); - -static docstring const lyxgreyedout_luartl_def = from_ascii( - "%% The greyedout annotation environment (with RTL support)\n" - "\\NewEnviron{lyxgreyedout}{%\n" - "\\if@RTL%\n" - "\\everypar{\\color{note_fontcolor}\\pardir TRT \\textdir TRT\\ignorespaces}%\n" - "\\BODY\\everypar{\\ignorespacesafterend}\n" - "\\else%\n" - "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n" - "\\BODY\\ignorespacesafterend\\egroup\n" - "\\fi}\n"); - -static docstring const lyxgreyedout_luartl_babel_def = from_ascii( - "%% The greyedout annotation environment (with RTL support)\n" - "\\NewEnviron{lyxgreyedout}{%\n" - "\\if@rl%\n" - "\\everypar{\\color{note_fontcolor}\\pardir TRT \\textdir TRT\\ignorespaces}%\n" - "\\BODY\\everypar{\\ignorespacesafterend}\n" - "\\else%\n" - "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n" - "\\BODY\\ignorespacesafterend\\egroup\n" - "\\fi}\n"); +static docstring const cellvarwidth_def = from_ascii( + "%% Variable width box for table cells\n" + "\\newenvironment{cellvarwidth}[1][t]\n" + " {\\begin{varwidth}[#1]{\\linewidth}}\n" + " {\\@finalstrut\\@arstrutbox\\end{varwidth}}\n"); // We want to omit the file extension for includegraphics, but this does not // work when the filename contains other dots. @@ -499,6 +470,7 @@ static docstring const textschwa_def = from_ascii( // split-level fractions static docstring const xfrac_def = from_ascii( "\\usepackage{xfrac}\n"); + static docstring const smallLetterFrac_def = from_ascii( "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{default}{text}\n" " {phantom=c, scale-factor=1.0, slash-left-kern=-.05em}\n" @@ -574,6 +546,52 @@ static docstring const lyxmintcaption_def = from_ascii( "}\n"); +docstring const lyxgreyedoutDef(bool const rtl, bool const ct, bool const lua, bool const babel) +{ + odocstringstream ods; + + if (rtl) { + ods << "%% The greyedout annotation environment (with RTL support)\n" + << "\\NewEnviron{lyxgreyedout}{%\n"; + if (lua && !babel) + // luabidi uses this switch + ods << " \\if@RTL%\n"; + else + ods << " \\if@rl%\n"; + ods << " \\everypar{%\n"; + if (lua) + ods << " \\pardir TRT \\textdir TRT\\normalfont\\normalsize\\textcolor{note_fontcolor}\\ignorespaces%\n"; + else + ods << " \\normalfont\\normalsize\\textcolor{note_fontcolor}\\beginL\\ignorespaces%\n"; + ods << " }%\n"; + if (ct) + ods << " \\colorlet{lyxadded}{lyxadded!30}\\colorlet{lyxdeleted}{lyxdeleted!30}%\n"; + if (lua) + ods << " \\BODY\\everypar{\\ignorespacesafterend}%\n"; + else + ods << " \\BODY\\everypar{\\ignorespacesafterend\\endL}%\n"; + ods << " \\else%\n"; + if (ct) + ods << " \\colorlet{lyxadded}{lyxadded!30}\\colorlet{lyxdeleted}{lyxdeleted!30}%\n"; + ods << " \\normalfont\\normalsize\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n" + << " \\BODY\\ignorespacesafterend\\egroup%\n" + << " \\fi%\n" + << "}\n"; + } else { + ods << "%% The greyedout annotation environment\n" + << "\\newenvironment{lyxgreyedout}\n" + << "{"; + if (ct) + ods << "\\colorlet{lyxadded}{lyxadded!30}\\colorlet{lyxdeleted}{lyxdeleted!30}%\n "; + ods << "\\normalfont\\normalsize\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n" + << "{\\ignorespacesafterend\\egroup}\n"; + } + + return ods.str(); +} + + + ///////////////////////////////////////////////////////////////////// // // LyXHTML strings @@ -765,8 +783,8 @@ bool LaTeXFeatures::isProvided(string const & name) const if (params_.useNonTeXFonts) return params_.documentClass().provides(name); - bool const ot1 = (params_.main_font_encoding() == "default" - || params_.main_font_encoding() == "OT1"); + bool const ot1 = (runparams().main_fontenc == "default" + || runparams().main_fontenc == "OT1"); bool const complete = (params_.fontsSans() == "default" && params_.fontsTypewriter() == "default"); bool const nomath = (params_.fontsMath() == "default"); @@ -819,7 +837,7 @@ void addSnippet(std::list & list, TexString ts, bool allow_dupes) return ts.str == ts2.str; }) ) - list.push_back(move(ts)); + list.push_back(std::move(ts)); } @@ -834,15 +852,15 @@ TexString getSnippets(std::list const & list) } // namespace -void LaTeXFeatures::addPreambleSnippet(TexString ts, bool allow_dupes) +void LaTeXFeatures::addPreambleSnippet(TexString snippet, bool allow_dupes) { - addSnippet(preamble_snippets_, move(ts), allow_dupes); + addSnippet(preamble_snippets_, std::move(snippet), allow_dupes); } -void LaTeXFeatures::addPreambleSnippet(docstring const & str, bool allow_dupes) +void LaTeXFeatures::addPreambleSnippet(docstring const & snippet, bool allow_dupes) { - addSnippet(preamble_snippets_, TexString(str), allow_dupes); + addSnippet(preamble_snippets_, TexString(snippet), allow_dupes); } @@ -924,11 +942,9 @@ bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const if (params_.language->polyglossia().empty()) return false; // now the secondary languages - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { - if ((*cit)->polyglossia().empty()) + for (auto const & lang : UsedLanguages_) + { + if (lang->polyglossia().empty()) return false; } return true; @@ -941,11 +957,9 @@ bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const if (params_.language->isPolyglossiaExclusive()) return true; // now the secondary languages - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { - if ((*cit)->isPolyglossiaExclusive()) + for (auto const & lang : UsedLanguages_) + { + if (lang->isPolyglossiaExclusive()) return true; } return false; @@ -959,12 +973,10 @@ vector LaTeXFeatures::getPolyglossiaExclusiveLanguages() const if (params_.language->isPolyglossiaExclusive()) result.push_back(params_.language->display()); // now the secondary languages - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { - if ((*cit)->isPolyglossiaExclusive()) - result.push_back((*cit)->display()); + for (auto const & lang : UsedLanguages_) + { + if (lang->isPolyglossiaExclusive()) + result.push_back(lang->display()); } return result; } @@ -977,12 +989,10 @@ vector LaTeXFeatures::getBabelExclusiveLanguages() const if (params_.language->isBabelExclusive()) result.push_back(params_.language->display()); // now the secondary languages - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { - if ((*cit)->isBabelExclusive()) - result.push_back((*cit)->display()); + for (auto const & lang : UsedLanguages_) + { + if (lang->isBabelExclusive()) + result.push_back(lang->display()); } return result; } @@ -990,22 +1000,19 @@ vector LaTeXFeatures::getBabelExclusiveLanguages() const string LaTeXFeatures::getBabelLanguages() const { - ostringstream langs; - - bool first = true; - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { - if ((*cit)->babel().empty()) - continue; - if (!first) - langs << ','; - else - first = false; - langs << (*cit)->babel(); + vector blangs; + for (auto const & lang : UsedLanguages_) { + if (!lang->babel().empty()) + blangs.push_back(lang->babel()); } - return langs.str(); + + // Sort alphabetically to assure consistent order + // (the order itself does not matter apart from + // some exceptions, e.g. hebrew must come after + // arabic and farsi) + sort(blangs.begin(), blangs.end()); + + return getStringFromVector(blangs); } @@ -1013,13 +1020,9 @@ set LaTeXFeatures::getPolyglossiaLanguages() const { set langs; - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); - ++cit) { + for (auto const & lang : UsedLanguages_) // We do not need the variants here - langs.insert((*cit)->polyglossia()); - } + langs.insert(lang->polyglossia()); return langs; } @@ -1030,10 +1033,8 @@ string LaTeXFeatures::getActiveChars() const // first the main language res += params_.language->activeChars(); // now the secondary languages - LanguageList::const_iterator const begin = UsedLanguages_.begin(); - for (LanguageList::const_iterator cit = begin; - cit != UsedLanguages_.end(); ++cit) - res += ((*cit)->activeChars()); + for (auto const & lang : UsedLanguages_) + res += (lang->activeChars()); return res; } @@ -1065,7 +1066,8 @@ void LaTeXFeatures::getFontEncodings(vector & encs, bool const onlylangs encs.insert(encs.begin(), "T2A"); } - for (auto const & lang : UsedLanguages_) { + for (auto const & lang : UsedLanguages_) + { vector extraencs = getVectorFromString(lang->fontenc(buffer().masterParams())); for (auto const & extra : extraencs) { @@ -1179,10 +1181,6 @@ char const * bibliofeatures[] = { "named" }; -int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *); - -int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *); - } // namespace @@ -1250,14 +1248,10 @@ string const LaTeXFeatures::getPackageOptions() const { ostringstream packageopts; // Output all the package option stuff we have been asked to do. - map::const_iterator it = - params_.documentClass().packageOptions().begin(); - map::const_iterator en = - params_.documentClass().packageOptions().end(); - for (; it != en; ++it) - if (mustProvide(it->first)) - packageopts << "\\PassOptionsToPackage{" << it->second << "}" - << "{" << it->first << "}\n"; + for (auto const & p : params_.documentClass().packageOptions()) + if (mustProvide(p.first)) + packageopts << "\\PassOptionsToPackage{" << p.second << "}" + << "{" << p.first << "}\n"; return packageopts.str(); } @@ -1274,9 +1268,9 @@ string const LaTeXFeatures::getPackages() const // These are all the 'simple' includes. i.e // packages which we just \usepackage{package} - for (int i = 0; i < nb_simplefeatures; ++i) { - if (mustProvide(simplefeatures[i])) - packages << "\\usepackage{" << simplefeatures[i] << "}\n"; + for (char const * feature : simplefeatures) { + if (mustProvide(feature)) + packages << "\\usepackage{" << feature << "}\n"; } // The rest of these packages are somewhat more complicated @@ -1284,8 +1278,8 @@ string const LaTeXFeatures::getPackages() const if (mustProvide("changebar")) { packages << "\\usepackage"; - if (runparams_.flavor == OutputParams::LATEX - || runparams_.flavor == OutputParams::DVILUATEX) + if (runparams_.flavor == Flavor::LaTeX + || runparams_.flavor == Flavor::DviLuaTeX) packages << "[dvips]"; packages << "{changebar}\n"; } @@ -1299,8 +1293,8 @@ string const LaTeXFeatures::getPackages() const // [pdf]lscape is used to rotate longtables if (mustProvide("lscape")) { - if (runparams_.flavor == OutputParams::LATEX - || runparams_.flavor == OutputParams::DVILUATEX) + if (runparams_.flavor == Flavor::LaTeX + || runparams_.flavor == Flavor::DviLuaTeX) packages << "\\usepackage{lscape}\n"; else packages << "\\usepackage{pdflscape}\n"; @@ -1321,8 +1315,8 @@ string const LaTeXFeatures::getPackages() const // if fontspec or newtxmath is used, AMS packages have to be loaded // before fontspec (in BufferParams) string const amsPackages = loadAMSPackages(); - bool const ot1 = (params_.main_font_encoding() == "default" - || params_.main_font_encoding() == "OT1"); + bool const ot1 = (runparams().main_fontenc == "default" + || runparams().main_fontenc == "OT1"); bool const use_newtxmath = theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage( ot1, false, false) == "newtxmath"; @@ -1436,10 +1430,9 @@ string const LaTeXFeatures::getPackages() const packages << "\\usepackage{esint}\n"; // Known bibliography packages (simple \usepackage{package}) - for (int i = 0; i < nb_bibliofeatures; ++i) { - if (mustProvide(bibliofeatures[i])) - packages << "\\usepackage{" - << bibliofeatures[i] << "}\n"; + for (char const * feature : bibliofeatures) { + if (mustProvide(feature)) + packages << "\\usepackage{" << feature << "}\n"; } // Compatibility between achicago and natbib @@ -1518,7 +1511,8 @@ string const LaTeXFeatures::getPackages() const } // fixltx2e provides subscript - if (mustProvide("subscript") && !isRequired("fixltx2e")) + if (mustProvide("subscript") && !isRequired("fixltx2e") + && !isAvailable("LaTeX-2005/12/01")) packages << "\\usepackage{subscript}\n"; // footmisc must be loaded after setspace @@ -1548,10 +1542,10 @@ TexString LaTeXFeatures::getMacros() const macros << "\\XeTeXdashbreakstate 0" << '\n'; if (mustProvide("papersize")) { - if (runparams_.flavor == OutputParams::LATEX - || runparams_.flavor == OutputParams::DVILUATEX) + if (runparams_.flavor == Flavor::LaTeX + || runparams_.flavor == Flavor::DviLuaTeX) macros << papersizedvi_def << '\n'; - else if (runparams_.flavor == OutputParams::LUATEX) + else if (runparams_.flavor == Flavor::LuaTeX) macros << papersizepdflua_def << '\n'; else macros << papersizepdf_def << '\n'; @@ -1584,19 +1578,22 @@ TexString LaTeXFeatures::getMacros() const if (mustProvide("lyxarrow")) macros << lyxarrow_def << '\n'; + if (mustProvide("aastex_case")) + macros << aastex_case_def << '\n'; + if (mustProvide("lyxzerowidthspace")) macros << lyxZWSP_def << '\n'; if (!usePolyglossia() && mustProvide("textgreek")) { - // ensure LGR font encoding is defined also if fontenc is not loaded by LyX - if (params_.main_font_encoding() == "default") + // ensure LGR font encoding is defined also if fontenc is not loaded by LyX + if (runparams().main_fontenc == "default") macros << textgreek_LGR_def; macros << textgreek_def << '\n'; } if (!usePolyglossia() && mustProvide("textcyrillic")) { // ensure T2A font encoding is set up also if fontenc is not loaded by LyX - if (params_.main_font_encoding() == "default") + if (runparams().main_fontenc == "default") macros << textcyr_T2A_def; macros << textcyr_def << '\n'; } @@ -1677,13 +1674,13 @@ TexString LaTeXFeatures::getMacros() const if (mustProvide("textquotedbl")) macros << textquotedbl_def << '\n'; if (mustProvide("textquotesinglep")) { - if (runparams_.flavor == OutputParams::XETEX) + if (runparams_.flavor == Flavor::XeTeX) macros << textquotesinglep_xetex_def << '\n'; else macros << textquotesinglep_luatex_def << '\n'; } if (mustProvide("textquotedblp")) { - if (runparams_.flavor == OutputParams::XETEX) + if (runparams_.flavor == Flavor::XeTeX) macros << textquotedblp_xetex_def << '\n'; else macros << textquotedblp_luatex_def << '\n'; @@ -1705,22 +1702,17 @@ TexString LaTeXFeatures::getMacros() const if (mustProvide("NeedTabularnewline")) macros << tabularnewline_def; + if (mustProvide("cellvarwidth")) + macros << cellvarwidth_def; + // greyed-out environment (note inset) // the color is specified in the routine // getColorOptions() to avoid LaTeX-package clashes - if (mustProvide("lyxgreyedout")) { - // We need different version for RTL (#8647) - if (hasRTLLanguage()) { - if (runparams_.flavor == OutputParams::LUATEX) - if (useBabel()) - macros << lyxgreyedout_luartl_babel_def; - else - macros << lyxgreyedout_luartl_def; - else - macros << lyxgreyedout_rtl_def; - } else - macros << lyxgreyedout_def; - } + if (mustProvide("lyxgreyedout")) + // We need different version for RTL (#8647), with change tracking (#12025) + // and for some specific engine/language package combinations + macros << lyxgreyedoutDef(hasRTLLanguage(), mustProvide("ct-xcolor-ulem"), + (runparams_.flavor == Flavor::LuaTeX), useBabel()); if (mustProvide("lyxdot")) macros << lyxdot_def << '\n'; @@ -1735,11 +1727,11 @@ TexString LaTeXFeatures::getMacros() const if (mustProvide("ct-xcolor-ulem")) { streamsize const prec = macros.os().precision(2); - RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext)); + RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext_output)); macros << "\\providecolor{lyxadded}{rgb}{" << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n"; - RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext)); + RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext_output)); macros << "\\providecolor{lyxdeleted}{rgb}{" << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n"; @@ -1764,11 +1756,11 @@ TexString LaTeXFeatures::getMacros() const if (!mustProvide("ct-xcolor-ulem")) { streamsize const prec = macros.os().precision(2); - RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext)); + RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext_output)); macros << "\\providecolor{lyxadded}{rgb}{" << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n"; - RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext)); + RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext_output)); macros << "\\providecolor{lyxdeleted}{rgb}{" << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n"; @@ -1807,7 +1799,7 @@ docstring const LaTeXFeatures::getBabelPresettings() const { odocstringstream tmp; - for (Language const * lang : UsedLanguages_) + for (auto const & lang : UsedLanguages_) if (!lang->babel_presettings().empty()) tmp << lang->babel_presettings() << '\n'; if (!params_.language->babel_presettings().empty()) @@ -1824,7 +1816,7 @@ docstring const LaTeXFeatures::getBabelPostsettings() const { odocstringstream tmp; - for (Language const * lang : UsedLanguages_) + for (auto const & lang : UsedLanguages_) if (!lang->babel_postsettings().empty()) tmp << lang->babel_postsettings() << '\n'; if (!params_.language->babel_postsettings().empty()) @@ -1960,8 +1952,8 @@ docstring const getFloatI18nPreamble(docstring const & type, { // Check whether name can be encoded in the buffer encoding bool encodable = true; - for (size_t i = 0; i < name.size(); ++i) { - if (!enc.encodable(name[i])) { + for (char_type c : name) { + if (!enc.encodable(c)) { encodable = false; break; } @@ -2237,10 +2229,8 @@ void LaTeXFeatures::getFloatDefinitions(otexstream & os) const // \newfloat{algorithm}{htbp}{loa} // \providecommand{\algorithmname}{Algorithm} // \floatname{algorithm}{\protect\algorithmname} - UsedFloats::const_iterator cit = usedFloats_.begin(); - UsedFloats::const_iterator end = usedFloats_.end(); - for (; cit != end; ++cit) { - Floating const & fl = floats.getType(cit->first); + for (auto const & cit : usedFloats_) { + Floating const & fl = floats.getType(cit.first); // For builtin floats we do nothing. if (fl.isPredefined()) @@ -2289,7 +2279,7 @@ void LaTeXFeatures::getFloatDefinitions(otexstream & os) const // used several times, when the same style is still in // effect. (Lgb) } - if (cit->second) + if (cit.second) // The subfig package is loaded later os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n"; } @@ -2334,13 +2324,10 @@ void LaTeXFeatures::expandMultiples() { for (Features::iterator it = features_.begin(); it != features_.end();) { if (contains(*it, ',')) { - vector const multiples = getVectorFromString(*it, ","); - vector::const_iterator const end = multiples.end(); - vector::const_iterator itm = multiples.begin(); // Do nothing if any multiple is already required - for (; itm != end; ++itm) { - if (!isRequired(*itm)) - require(*itm); + for (string const & pkg : getVectorFromString(*it, ",")) { + if (!isRequired(pkg)) + require(pkg); } features_.erase(it); it = features_.begin();