diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index d8442211b76..fe35334ba78 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1901,10 +1901,11 @@ GK_ATOM(x_symbol, "x-symbol") // referenced in all.js GK_ATOM(x_user_def, "x-user-def") -// additional languages that use Turkish-style case transformation +// additional languages that have special case transformations GK_ATOM(az, "az") GK_ATOM(ba, "ba") GK_ATOM(crh, "crh") +GK_ATOM(nl, "nl") // Names for editor transactions GK_ATOM(TypingTxnName, "Typing") diff --git a/layout/generic/nsTextRunTransformations.cpp b/layout/generic/nsTextRunTransformations.cpp index 5f5f261edf3..f5497944010 100644 --- a/layout/generic/nsTextRunTransformations.cpp +++ b/layout/generic/nsTextRunTransformations.cpp @@ -362,8 +362,19 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, nsAutoTArray canBreakBeforeArray; PRUint32 extraCharsCount = 0; + // Some languages have special casing conventions that differ from the + // default Unicode mappings. + // The enum values here are named for well-known exemplar languages that + // exhibit the behavior in question; multiple lang tags may map to the + // same setting here, if the behavior is shared by other languages. + enum { + eNone, // default non-lang-specific behavior + eTurkish, // preserve dotted/dotless-i distinction in uppercase + eDutch // treat "ij" digraph as a unit for capitalization + } languageSpecificCasing = eNone; + const nsIAtom* lang = nsnull; - bool turkishCasing = false; + bool capitalizeDutchIJ = false; PRUint32 i; for (i = 0; i < length; ++i) { PRUint32 ch = str[i]; @@ -383,16 +394,20 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, if (lang != styleContext->GetStyleFont()->mLanguage) { lang = styleContext->GetStyleFont()->mLanguage; - turkishCasing = lang == nsGkAtoms::tr || - lang == nsGkAtoms::az || - lang == nsGkAtoms::ba || - lang == nsGkAtoms::crh || - lang == nsGkAtoms::tt; + if (lang == nsGkAtoms::tr || lang == nsGkAtoms::az || + lang == nsGkAtoms::ba || lang == nsGkAtoms::crh || + lang == nsGkAtoms::tt) { + languageSpecificCasing = eTurkish; + } else if (lang == nsGkAtoms::nl) { + languageSpecificCasing = eDutch; + } else { + languageSpecificCasing = eNone; + } } switch (style) { case NS_STYLE_TEXT_TRANSFORM_LOWERCASE: - if (turkishCasing && ch == 'I') { + if (languageSpecificCasing == eTurkish && ch == 'I') { ch = LATIN_SMALL_LETTER_DOTLESS_I; } else { ch = ToLowerCase(ch); @@ -403,20 +418,29 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, convertedString.Append('S'); extraChar = true; ch = 'S'; - } else if (turkishCasing && ch == 'i') { + } else if (languageSpecificCasing == eTurkish && ch == 'i') { ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE; } else { ch = ToUpperCase(ch); } break; case NS_STYLE_TEXT_TRANSFORM_CAPITALIZE: + if (capitalizeDutchIJ && ch == 'j') { + ch = 'J'; + capitalizeDutchIJ = false; + break; + } + capitalizeDutchIJ = false; if (i < aTextRun->mCapitalize.Length() && aTextRun->mCapitalize[i]) { if (ch == SZLIG) { convertedString.Append('S'); extraChar = true; ch = 'S'; - } else if (turkishCasing && ch == 'i') { + } else if (languageSpecificCasing == eTurkish && ch == 'i') { ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE; + } else if (languageSpecificCasing == eDutch && ch == 'i') { + ch = 'I'; + capitalizeDutchIJ = true; } else { ch = ToTitleCase(ch); }