Skip to content

Commit a6add20

Browse files
committed
Encapsulate all elements of a cultural name with Unicode Isolation characters.
This ensures left to right order of label elements.
1 parent 6d64202 commit a6add20

File tree

1 file changed

+50
-20
lines changed

1 file changed

+50
-20
lines changed

src/core/StelSkyCultureMgr.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -974,12 +974,41 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
974974
const QString &commonNameI18n,
975975
const QString &abbrevI18n) const
976976
{
977+
// Each element may be in an RTL language (e.g. Arab). However, we want a canonical order of left to right elements.
978+
// This requires building Unicode isolation cells.
979+
// Unicode constants from Unicode Standard Annex #9, section 2.
980+
//static const QString LRE{"\u202a"}; // Left-to-right embedding: Treat following text as embedded left-to-right
981+
//static const QString RLE{"\u202b"}; // Right-to-left embedding: Treat following text as embedded right-to-left
982+
//static const QString LRO{"\u202d"}; // Left-to-right override: Force following characters to be treated as strong left-to-right chars.
983+
//static const QString RLO{"\u202e"}; // Right-to-left override: Force following characters to be treated as strong right-to-left chars.
984+
//static const QString PDF{"\u202c"}; // Pop directional formatting: terminate scope of last LRE/RLE/LRO/RLO
985+
static const QString LRI{"\u2066"}; // left-to-right isolate: Treat following text as isolated and left-to-right
986+
static const QString RLI{"\u2067"}; // right-to-left isolate: Treat following text as isolated and right-to-left
987+
static const QString FSI{"\u2068"}; // First strong isolate: Treat following text as isolated and in the direction of its first strong directional character.
988+
// ASSUMPTION: Can be used as autodetect feature? Mark all parts inside embeddings?
989+
static const QString PDI{"\u2069"}; // Pop directional isolate: terminate scope of last LRI/RLI/FSI
990+
//static const QString LRM{"\u200e"}; // left-to-right mark: zero-width char
991+
//static const QString RLM{"\u200f"}; // right-to-left mark: right to left zero-width non-Arabic char
992+
//static const QString ALM{"\u061c"}; // right-to-left mark: right to left zero-width Arabic char
993+
994+
StelObject::CulturalName lName;
995+
// copy over filled elements from cName, but enclose each with Unicode isolation markers.
996+
if (!cName.native .isEmpty()) lName.native = FSI+cName.native+PDI;
997+
if (!cName.pronounce .isEmpty()) lName.pronounce = FSI+cName.pronounce+PDI;
998+
if (!cName.pronounceI18n .isEmpty()) lName.pronounceI18n = FSI+cName.pronounceI18n+PDI;
999+
if (!cName.transliteration.isEmpty()) lName.transliteration = FSI+cName.transliteration+PDI;
1000+
if (!cName.translated .isEmpty()) lName.translated = FSI+cName.translated+PDI;
1001+
if (!cName.translatedI18n .isEmpty()) lName.translatedI18n = FSI+cName.translatedI18n+PDI;
1002+
if (!cName.IPA .isEmpty()) lName.IPA = FSI+cName.IPA+PDI;
1003+
if (!cName.byname .isEmpty()) lName.byname = FSI+cName.byname+PDI;
1004+
if (!cName.bynameI18n .isEmpty()) lName.bynameI18n = FSI+cName.bynameI18n+PDI;
1005+
9771006
// At least while many fields have not been filled, we should create a few fallbacks
9781007
// If native contains non-Latin glyphs, pronounce or transliteration is mandatory.
979-
QString pronounceStr=(cName.pronounceI18n.isEmpty() ? cName.pronounce : cName.pronounceI18n);
980-
QString nativeOrPronounce = (cName.native.isEmpty() ? cName.pronounceI18n : cName.native);
981-
QString pronounceOrNative = (cName.pronounceI18n.isEmpty() ? cName.native : cName.pronounceI18n);
982-
QString translitOrPronounce = (cName.transliteration.isEmpty() ? pronounceStr : cName.transliteration);
1008+
QString pronounceStr=(lName.pronounceI18n.isEmpty() ? lName.pronounce : lName.pronounceI18n);
1009+
QString nativeOrPronounce = (lName.native.isEmpty() ? lName.pronounceI18n : lName.native);
1010+
QString pronounceOrNative = (lName.pronounceI18n.isEmpty() ? lName.native : lName.pronounceI18n);
1011+
QString translitOrPronounce = (lName.transliteration.isEmpty() ? pronounceStr : lName.transliteration);
9831012

9841013
// If you call this with an actual argument abbrevI18n, you really only want a short label.
9851014
if (flagUseAbbreviatedNames && !abbrevI18n.isNull())
@@ -990,20 +1019,20 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
9901019
switch (style)
9911020
{
9921021
case StelObject::CulturalDisplayStyle::Native: // native if available. fallback to pronounce and english entries
993-
return cName.native.isEmpty() ? (cName.pronounceI18n.isEmpty() ? cName.translatedI18n : cName.pronounceI18n) : cName.native;
1022+
return lName.native.isEmpty() ? (lName.pronounceI18n.isEmpty() ? lName.translatedI18n : lName.pronounceI18n) : lName.native;
9941023
case StelObject::CulturalDisplayStyle::Pronounce: // pronounce if available. fallback to native
9951024
return pronounceOrNative;
9961025
case StelObject::CulturalDisplayStyle::Translit:
9971026
return translitOrPronounce;
9981027
case StelObject::CulturalDisplayStyle::Translated:
999-
return (cName.translatedI18n.isEmpty() ? (pronounceStr.isEmpty() ? cName.native : pronounceStr) : cName.translatedI18n);
1028+
return (lName.translatedI18n.isEmpty() ? (pronounceStr.isEmpty() ? lName.native : pronounceStr) : lName.translatedI18n);
10001029
case StelObject::CulturalDisplayStyle::IPA: // really only IPA?
1001-
return cName.IPA;
1030+
return lName.IPA;
10021031
case StelObject::CulturalDisplayStyle::NONE: // fully non-cultural!
10031032
case StelObject::CulturalDisplayStyle::Modern:
10041033
return commonNameI18n;
10051034
case StelObject::CulturalDisplayStyle::Byname:
1006-
return (cName.bynameI18n.isEmpty() ? (pronounceStr.isEmpty() ? cName.native : pronounceStr) : cName.bynameI18n);
1035+
return (lName.bynameI18n.isEmpty() ? (pronounceStr.isEmpty() ? lName.native : pronounceStr) : lName.bynameI18n);
10071036
default:
10081037
break;
10091038
}
@@ -1026,7 +1055,7 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10261055
if (styleInt & int(StelObject::CulturalDisplayStyle::Pronounce))
10271056
braced.append(pronounceStr);
10281057
if (styleInt & int(StelObject::CulturalDisplayStyle::Translit))
1029-
braced.append(cName.transliteration);
1058+
braced.append(lName.transliteration);
10301059
}
10311060
else // not including native
10321061
{
@@ -1035,7 +1064,7 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10351064
{
10361065
label=pronounceOrNative;
10371066
if (styleInt & int(StelObject::CulturalDisplayStyle::Translit))
1038-
braced.append(cName.transliteration);
1067+
braced.append(lName.transliteration);
10391068
}
10401069

10411070
else if (styleInt & int(StelObject::CulturalDisplayStyle::Translit))
@@ -1048,33 +1077,34 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10481077
braced.removeOne(QString(""));
10491078
braced.removeOne(QString());
10501079
braced.removeOne(label); // avoid repeating the main thing if it was used as fallback!
1080+
10511081
if (!braced.isEmpty()) label.append(QString(" %1%3%2").arg(QChar(0x2997), QChar(0x2998), braced.join(", ")));
10521082

10531083
// Add IPA (where possible)
1054-
if ((styleInt & int(StelObject::CulturalDisplayStyle::IPA)) && (!cName.IPA.isEmpty()) && (label != cName.IPA))
1055-
label.append(QString(" [%1]").arg(cName.IPA));
1084+
if ((styleInt & int(StelObject::CulturalDisplayStyle::IPA)) && (!lName.IPA.isEmpty()) && (label != lName.IPA))
1085+
label.append(QString(" [%1]").arg(lName.IPA));
10561086

10571087
// Add translation and optional byname in brackets
10581088

10591089
QStringList bracketed;
1060-
if ((styleInt & int(StelObject::CulturalDisplayStyle::Translated)) && (!cName.translatedI18n.isEmpty()))
1090+
if ((styleInt & int(StelObject::CulturalDisplayStyle::Translated)) && (!lName.translatedI18n.isEmpty()))
10611091
{
10621092
if (label.isEmpty())
1063-
label=cName.translatedI18n;
1064-
else if (!label.startsWith(cName.translatedI18n, Qt::CaseInsensitive)) // seems useless to add translation into same string
1093+
label=lName.translatedI18n;
1094+
else if (!label.startsWith(lName.translatedI18n, Qt::CaseInsensitive)) // seems useless to add translation into same string
10651095

1066-
//label.append(QString(" (%1)").arg(cName.translatedI18n));
1067-
bracketed.append(cName.translatedI18n);
1096+
//label.append(QString(" (%1)").arg(lName.translatedI18n));
1097+
bracketed.append(lName.translatedI18n);
10681098
}
10691099

1070-
if ( (styleInt & int(StelObject::CulturalDisplayStyle::Byname)) && (!cName.bynameI18n.isEmpty()))
1071-
bracketed.append(cName.bynameI18n);
1100+
if ( (styleInt & int(StelObject::CulturalDisplayStyle::Byname)) && (!lName.bynameI18n.isEmpty()))
1101+
bracketed.append(lName.bynameI18n);
10721102
if (!bracketed.isEmpty())
10731103
label.append(QString(" (%1)").arg(bracketed.join(", ")));
10741104

10751105

10761106
// Add an explanatory modern name in decorative angle brackets
1077-
if ((styleInt & int(StelObject::CulturalDisplayStyle::Modern)) && (!commonNameI18n.isEmpty()) && (!label.startsWith(commonNameI18n)) && (commonNameI18n!=cName.translatedI18n))
1107+
if ((styleInt & int(StelObject::CulturalDisplayStyle::Modern)) && (!commonNameI18n.isEmpty()) && (!label.startsWith(commonNameI18n)) && (commonNameI18n!=lName.translatedI18n))
10781108
label.append(QString(" %1%3%2").arg(QChar(0x29FC), QChar(0x29FD), commonNameI18n));
10791109
if ((styleInt & int(StelObject::CulturalDisplayStyle::Modern)) && label.isEmpty()) // if something went wrong?
10801110
label=commonNameI18n;

0 commit comments

Comments
 (0)