* Introduce polyglossia support (bug 6576).

Please test this.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@36433 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Spitzmüller 2010-11-22 12:10:16 +00:00
parent 3ffbab3bca
commit 7cbeed2e40
13 changed files with 288 additions and 85 deletions

View File

@ -284,6 +284,7 @@
\TestPackage{nicefrac}
\TestPackage{nomencl}
\TestPackage{pdfcolmk}
\TestPackage{polyglossia}
\TestPackage{pdfpages}
\TestPackage{prettyref}
\TestPackage{preview}

View File

@ -1,5 +1,5 @@
#LyX 2.0.0svn created this file. For more info see http://www.lyx.org/
\lyxformat 401
\lyxformat 408
\begin_document
\begin_header
\textclass article
@ -37,6 +37,7 @@
\use_indices false
\paperorientation portrait
\suppress_date false
\use_refstyle 0
\index Index
\shortcut idx
\color #008000
@ -4276,6 +4277,48 @@ mongolian-babel
Mongolian.
\end_layout
\begin_layout Subsection
polyglossia
\end_layout
\begin_layout Description
Found:
\begin_inset Info
type "package"
arg "polyglossia"
\end_inset
\end_layout
\begin_layout Description
CTAN:
\family typewriter
macros/xetex/latex/polyglossia/
\end_layout
\begin_layout Description
Notes: The package
\family sans
polyglossia
\family default
provides a language interface specifically for XeTeX.
It aims to supersede the
\family sans
babel
\family default
package by using XeTeX's mutlilingual and multiscript facilities.
If installed,
\family sans
polyglossia
\family default
will by used for language handling instead of
\family sans
babel
\family default
when XeTeX is used as output format.
\end_layout
\begin_layout Subsection
turkmen
\end_layout

View File

@ -1386,6 +1386,7 @@ void Buffer::writeLaTeXSource(odocstream & os,
MacroSet parentMacros;
listParentMacros(parentMacros, features);
runparams.use_polyglossia = features.usePolyglossia();
// Write the preamble
runparams.use_babel = params().writeLaTeX(os, features,
d->texrow,

View File

@ -1305,15 +1305,16 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
ostringstream language_options;
bool const use_babel = features.useBabel() && !tclass.provides("babel");
if (use_babel) {
bool const use_polyglossia = features.usePolyglossia();
bool const global = lyxrc.language_global_options;
if (use_babel || (use_polyglossia && global)) {
language_options << features.getLanguages();
if (!language->babel().empty()) {
if (!language_options.str().empty())
language_options << ',';
language_options << language->babel();
}
if (lyxrc.language_global_options
&& !features.needBabelLangOptions())
if (global && !features.needBabelLangOptions())
clsoptions << language_options.str() << ',';
}
@ -1724,7 +1725,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
&& (features.isRequired("jurabib")
|| features.isRequired("hyperref")
|| features.isRequired("vietnamese")
|| features.isRequired("japanese") ) ) {
|| features.isRequired("japanese"))) {
// FIXME UNICODE
lyxpreamble += from_utf8(features.getBabelPresettings());
lyxpreamble += from_utf8(babelCall(language_options.str(),
@ -1877,6 +1878,7 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
lyxpreamble += from_utf8(features.getBabelPostsettings());
}
// FIXME Polyglossia?
docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
if (!i18npreamble.empty())
lyxpreamble += i18npreamble + '\n';
@ -1896,6 +1898,29 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
os << "\\usepackage{xltxtra}\n";
texrow.newline();
}
// Polyglossia must be loaded after xltxtra
if (use_polyglossia) {
// call the package
os << "\\usepackage{polyglossia}\n";
texrow.newline();
// set the main language
os << "\\setdefaultlanguage";
if (!language->polyglossiaOpts().empty())
os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
os << "{" + from_ascii(language->polyglossia()) + "}\n";
texrow.newline();
// now setup the other languages
std::map<std::string, std::string> const polylangs =
features.getPolyglossiaLanguages();
for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
mit != polylangs.end() ; ++mit) {
os << "\\setotherlanguage";
if (!mit->second.empty())
os << "[" << from_ascii(mit->second) << "]";
os << "{" << from_ascii(mit->first) << "}\n";
texrow.newline();
}
}
return use_babel;
}

View File

@ -272,7 +272,18 @@ int Font::latexWriteStartChanges(odocstream & os, BufferParams const & bparams,
bool env = false;
int count = 0;
if (language()->babel() != base.language()->babel() &&
// polyglossia or babel?
if (runparams.use_polyglossia) {
if (!language()->polyglossia().empty()) {
string tmp = "\\text" + language()->polyglossia();
if (!language()->polyglossiaOpts().empty())
tmp += "[" + language()->polyglossiaOpts() + "]";
tmp += "{";
os << from_ascii(tmp);
count += tmp.length();
}
} else if (language()->babel() != base.language()->babel() &&
language() != prev.language()) {
if (language()->lang() == "farsi") {
os << "\\textFR{";

View File

@ -285,10 +285,23 @@ LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
bool LaTeXFeatures::useBabel() const
{
return (lyxrc.language_package_selection != LyXRC::LP_NONE) &&
((bufferParams().language->lang() != lyxrc.default_language &&
!bufferParams().language->babel().empty()) ||
this->hasLanguages());
return (lyxrc.language_package_selection != LyXRC::LP_NONE)
&& !usePolyglossia()
&& ((bufferParams().language->lang() != lyxrc.default_language
&& !bufferParams().language->babel().empty())
|| this->hasLanguages());
}
bool LaTeXFeatures::usePolyglossia() const
{
return (lyxrc.language_package_selection == LyXRC::LP_AUTO)
&& isRequired("xetex")
&& isAvailable("polyglossia")
&& ((bufferParams().language->lang() != lyxrc.default_language
&& !bufferParams().language->polyglossia().empty())
|| this->hasLanguages())
&& this->hasPolyglossiaLanguages();
}
@ -474,6 +487,19 @@ bool LaTeXFeatures::hasLanguages() const
}
bool LaTeXFeatures::hasPolyglossiaLanguages() const
{
LanguageList::const_iterator const begin = UsedLanguages_.begin();
for (LanguageList::const_iterator cit = begin;
cit != UsedLanguages_.end();
++cit) {
if ((*cit)->polyglossia().empty())
return false;
}
return true;
}
string LaTeXFeatures::getLanguages() const
{
ostringstream languages;
@ -490,6 +516,20 @@ string LaTeXFeatures::getLanguages() const
}
std::map<std::string, std::string> LaTeXFeatures::getPolyglossiaLanguages() const
{
std::map<std::string, std::string> languages;
LanguageList::const_iterator const begin = UsedLanguages_.begin();
for (LanguageList::const_iterator cit = begin;
cit != UsedLanguages_.end();
++cit) {
languages[(*cit)->polyglossia()] = (*cit)->polyglossiaOpts();
}
return languages;
}
set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
{
// This does only find encodings of languages supported by babel, but
@ -825,7 +865,7 @@ docstring const LaTeXFeatures::getMacros() const
if (mustProvide("lyxarrow"))
macros << lyxarrow_def << '\n';
if (mustProvide("textgreek")) {
if (!usePolyglossia() && mustProvide("textgreek")) {
// Avoid a LaTeX error if times fonts are used and the grtimes
// package is installed but actual fonts are not (bug 6469).
if (params_.fontsRoman == "times")
@ -839,7 +879,7 @@ docstring const LaTeXFeatures::getMacros() const
macros << textgreek_def << '\n';
}
if (mustProvide("textcyr"))
if (!usePolyglossia() && mustProvide("textcyr"))
macros << textcyr_def << '\n';
if (mustProvide("lyxmathsym"))

View File

@ -101,9 +101,13 @@ public:
void useLanguage(Language const *);
///
bool hasLanguages() const;
/// check if all used languages are supported by polyglossia
bool hasPolyglossiaLanguages() const;
///
std::string getLanguages() const;
///
std::map<std::string, std::string> getPolyglossiaLanguages() const;
///
std::set<std::string> getEncodingSet(std::string const & doc_encoding) const;
///
void useLayout(docstring const & lyt);
@ -117,6 +121,8 @@ public:
BufferParams const & bufferParams() const;
/// the return value is dependent upon both LyXRC and LaTeXFeatures.
bool useBabel() const;
///
bool usePolyglossia() const;
/// are we in a float?
bool inFloat() const { return in_float_; }
/// are we in a float?

View File

@ -21,7 +21,7 @@ namespace lyx {
OutputParams::OutputParams(Encoding const * enc)
: flavor(LATEX), math_flavor(NotApplicable), nice(false), moving_arg(false),
inulemcmd(false), local_font(0), master_language(0), encoding(enc),
free_spacing(false), use_babel(false),
free_spacing(false), use_babel(false), use_polyglossia(false),
use_indices(false), use_japanese(false), linelen(0), depth(0),
exportdata(new ExportData),
inComment(false), inTableCell(NO), inFloat(NONFLOAT),

View File

@ -136,6 +136,10 @@ public:
*/
bool use_babel;
/** Do we use polyglossia (instead of babel)?
*/
bool use_polyglossia;
/** Are we generating multiple indices?
*/
bool use_indices;

View File

@ -2369,12 +2369,16 @@ void Paragraph::latex(BufferParams const & bparams,
open_font = false;
}
string const running_lang = runparams.use_polyglossia ?
running_font.language()->polyglossia() : running_font.language()->babel();
// close babel's font environment before opening CJK.
if (!running_font.language()->babel().empty() &&
string const lang_end_command = runparams.use_polyglossia ?
"\\end{$$lang}" : lyxrc.language_command_end;
if (!running_lang.empty() &&
font.language()->encoding()->package() == Encoding::CJK) {
string end_tag = subst(lyxrc.language_command_end,
string end_tag = subst(lang_end_command,
"$$lang",
running_font.language()->babel());
running_lang);
os << from_ascii(end_tag);
column += end_tag.length();
}

View File

@ -267,18 +267,20 @@ int InsetQuotes::latex(odocstream & os, OutputParams const & runparams) const
string qstr;
if (language_ == FrenchQuotes && times_ == DoubleQuotes
&& prefixIs(runparams.local_font->language()->code(), "fr")) {
&& prefixIs(runparams.local_font->language()->code(), "fr")
&& !runparams.use_polyglossia) {
if (side_ == LeftQuote)
qstr = "\\og "; //the spaces are important here
else
qstr = " \\fg{}"; //and here
} else if (lyxrc.fontenc == "T1") {
} else if (lyxrc.fontenc == "T1" && !runparams.use_polyglossia) {
qstr = latex_quote_t1[times_][quoteind];
#ifdef DO_USE_DEFAULT_LANGUAGE
} else if (doclang == "default") {
#else
} else if (!runparams.use_babel) {
#endif
// these are also used by polyglossia
qstr = latex_quote_ot1[times_][quoteind];
} else {
qstr = latex_quote_babel[times_][quoteind];

View File

@ -97,6 +97,16 @@ TeXDeeper(Buffer const & buf,
}
string const getPolyglossiaEnvName(Language const * lang)
{
string result = lang->polyglossia();
if (result == "arabic")
// exceptional spelling; see polyglossia docs.
result = "Arabic";
return result;
}
ParagraphList::const_iterator
TeXEnvironment(Buffer const & buf,
Text const & text,
@ -131,29 +141,47 @@ TeXEnvironment(Buffer const & buf,
? (use_prev_env_language ? prev_env_language_
: priorpit->getParLanguage(bparams))
: doc_language;
if (par_language->babel() != prev_par_language->babel()) {
string par_lang = par_language->babel();
string prev_par_lang = prev_par_language->babel();
string doc_lang = doc_language->babel();
string lang_begin_command = lyxrc.language_command_begin;
string lang_end_command = lyxrc.language_command_end;
if (!lyxrc.language_command_end.empty() &&
prev_par_language->babel() != doc_language->babel() &&
!prev_par_language->babel().empty()) {
if (runparams.use_polyglossia) {
par_lang = getPolyglossiaEnvName(par_language);
prev_par_lang = getPolyglossiaEnvName(prev_par_language);
doc_lang = getPolyglossiaEnvName(doc_language);
lang_begin_command = "\\begin{$$lang}";
lang_end_command = "\\end{$$lang}";
}
if (par_lang != prev_par_lang) {
if (!lang_end_command.empty() &&
prev_par_lang != doc_lang &&
!prev_par_lang.empty()) {
os << from_ascii(subst(
lyxrc.language_command_end,
lang_end_command,
"$$lang",
prev_par_language->babel()))
prev_par_lang))
// the '%' is necessary to prevent unwanted whitespace
<< "%\n";
texrow.newline();
}
if ((lyxrc.language_command_end.empty() ||
par_language->babel() != doc_language->babel()) &&
!par_language->babel().empty()) {
par_lang != doc_lang) &&
!par_lang.empty()) {
os << from_ascii(subst(
lyxrc.language_command_begin,
lang_begin_command,
"$$lang",
par_language->babel()))
par_lang));
if (runparams.use_polyglossia
&& !par_language->polyglossiaOpts().empty())
os << "["
<< from_ascii(par_language->polyglossiaOpts())
<< "]";
// the '%' is necessary to prevent unwanted whitespace
<< "%\n";
os << "%\n";
texrow.newline();
}
}
@ -441,7 +469,22 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
: priorpit->getParLanguage(bparams))
: outer_language;
if (par_language->babel() != prev_language->babel()
string par_lang = par_language->babel();
string prev_lang = prev_language->babel();
string doc_lang = doc_language->babel();
string outer_lang = outer_language->babel();
string lang_begin_command = lyxrc.language_command_begin;
string lang_end_command = lyxrc.language_command_end;
if (runparams.use_polyglossia) {
par_lang = getPolyglossiaEnvName(par_language);
prev_lang = getPolyglossiaEnvName(prev_language);
doc_lang = getPolyglossiaEnvName(doc_language);
outer_lang = getPolyglossiaEnvName(outer_language);
lang_begin_command = "\\begin{$$lang}";
lang_end_command = "\\end{$$lang}";
}
if (par_lang != prev_lang
// check if we already put language command in TeXEnvironment()
&& !(style.isEnvironment()
&& (pit == paragraphs.begin() ||
@ -449,13 +492,13 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
priorpit->getDepth() <= pit->getDepth())
|| priorpit->getDepth() < pit->getDepth())))
{
if (!lyxrc.language_command_end.empty() &&
prev_language->babel() != outer_language->babel() &&
!prev_language->babel().empty())
if (!lang_end_command.empty() &&
prev_lang != outer_lang &&
!prev_lang.empty())
{
os << from_ascii(subst(lyxrc.language_command_end,
os << from_ascii(subst(lang_end_command,
"$$lang",
prev_language->babel()))
prev_lang))
// the '%' is necessary to prevent unwanted whitespace
<< "%\n";
texrow.newline();
@ -466,15 +509,16 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
// the previous one, if the current language is different than the
// outer_language (which is currently in effect once the previous one
// is closed).
if ((lyxrc.language_command_end.empty() ||
par_language->babel() != outer_language->babel()) &&
!par_language->babel().empty()) {
if ((lang_end_command.empty() ||
par_lang != outer_lang) &&
!par_lang.empty()) {
// If we're inside an inset, and that inset is within an \L or \R
// (or equivalents), then within the inset, too, any opposite
// language paragraph should appear within an \L or \R (in addition
// to, outside of, the normal language switch commands).
// This behavior is not correct for ArabTeX, though.
if ( // not for ArabTeX
if (!runparams.use_polyglossia &&
// not for ArabTeX
(par_language->lang() != "arabic_arabtex" &&
outer_language->lang() != "arabic_arabtex") &&
// are we in an inset?
@ -509,11 +553,16 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
// With CJK, the CJK tag has to be closed first (see below)
if (runparams.encoding->package() != Encoding::CJK) {
os << from_ascii(subst(
lyxrc.language_command_begin,
lang_begin_command,
"$$lang",
par_language->babel()))
par_lang));
if (runparams.use_polyglossia
&& !par_language->polyglossiaOpts().empty())
os << "["
<< from_ascii(par_language->polyglossiaOpts())
<< "]";
// the '%' is necessary to prevent unwanted whitespace
<< "%\n";
os << "%\n";
texrow.newline();
}
}
@ -566,9 +615,9 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
// With CJK, the CJK tag had to be closed first (see above)
if (runparams.encoding->package() == Encoding::CJK) {
os << from_ascii(subst(
lyxrc.language_command_begin,
lang_begin_command,
"$$lang",
par_language->babel()))
par_lang))
// the '%' is necessary to prevent unwanted whitespace
<< "%\n";
texrow.newline();
@ -709,6 +758,7 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
// needed if we're within an \L or \R that we may have opened above (not
// necessarily in this paragraph) and are about to close.
bool closing_rtl_ltr_environment =
!runparams.use_polyglossia &&
// not for ArabTeX
(par_language->lang() != "arabic_arabtex" &&
outer_language->lang() != "arabic_arabtex") &&
@ -734,7 +784,7 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
}
// when the paragraph uses CJK, the language has to be closed earlier
if (font.language()->encoding()->package() != Encoding::CJK) {
if (lyxrc.language_command_end.empty()) {
if (lang_end_command.empty()) {
// If this is a child, we should restore the
// master language after the last paragraph.
Language const * const current_language =
@ -742,18 +792,21 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
&& runparams.master_language)
? runparams.master_language
: outer_language;
if (!current_language->babel().empty()) {
string const current_lang = runparams.use_polyglossia ?
getPolyglossiaEnvName(current_language)
: current_language->babel();
if (!current_lang.empty()) {
os << from_ascii(subst(
lyxrc.language_command_begin,
lang_begin_command,
"$$lang",
current_language->babel()));
current_lang));
pending_newline = true;
}
} else if (!par_language->babel().empty()) {
} else if (!par_lang.empty()) {
os << from_ascii(subst(
lyxrc.language_command_end,
lang_end_command,
"$$lang",
par_language->babel()));
par_lang));
pending_newline = true;
}
}
@ -895,13 +948,24 @@ void latexParagraphs(Buffer const & buf,
}
// if "auto begin" is switched off, explicitly switch the
// language on at start
string const mainlang = runparams.use_polyglossia ?
getPolyglossiaEnvName(bparams.language)
: bparams.language->babel();
string const lang_begin_command = runparams.use_polyglossia ?
"\\begin{$$lang}" : lyxrc.language_command_begin;
if (maintext && !lyxrc.language_auto_begin &&
!bparams.language->babel().empty()) {
!mainlang.empty()) {
// FIXME UNICODE
os << from_utf8(subst(lyxrc.language_command_begin,
os << from_utf8(subst(lang_begin_command,
"$$lang",
bparams.language->babel()))
<< '\n';
mainlang));
if (runparams.use_polyglossia
&& !bparams.language->polyglossiaOpts().empty())
os << "["
<< from_ascii(bparams.language->polyglossiaOpts())
<< "]";
os << '\n';
texrow.newline();
}
@ -969,11 +1033,13 @@ void latexParagraphs(Buffer const & buf,
// if "auto end" is switched off, explicitly close the language at the end
// but only if the last par is in a babel language
if (maintext && !lyxrc.language_auto_end && !bparams.language->babel().empty() &&
string const lang_end_command = runparams.use_polyglossia ?
"\\end{$$lang}" : lyxrc.language_command_end;
if (maintext && !lyxrc.language_auto_end && !mainlang.empty() &&
lastpar->getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
os << from_utf8(subst(lyxrc.language_command_end,
os << from_utf8(subst(lang_end_command,
"$$lang",
bparams.language->babel()))
mainlang))
<< '\n';
texrow.newline();
}