File indexing completed on 2024-04-28 15:31:55

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2008 Chusslove Illich <caslav.ilic@gmx.net>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include <common_helpers_p.h>
0009 
0010 // If pos points to alphanumeric X in "...(X)...", which is preceded or
0011 // followed only by non-alphanumerics, then "(X)" gets removed.
0012 static QString removeReducedCJKAccMark(const QString &label, int pos)
0013 {
0014     if (pos > 0 && pos + 1 < label.length() //
0015         && label[pos - 1] == QLatin1Char('(') //
0016         && label[pos + 1] == QLatin1Char(')') //
0017         && label[pos].isLetterOrNumber()) {
0018         // Check if at start or end, ignoring non-alphanumerics.
0019         int len = label.length();
0020         int p1 = pos - 2;
0021         while (p1 >= 0 && !label[p1].isLetterOrNumber()) {
0022             --p1;
0023         }
0024         ++p1;
0025         int p2 = pos + 2;
0026         while (p2 < len && !label[p2].isLetterOrNumber()) {
0027             ++p2;
0028         }
0029         --p2;
0030 
0031         const QStringView sview{label};
0032         if (p1 == 0) {
0033             return sview.left(pos - 1) + sview.mid(p2 + 1);
0034         } else if (p2 + 1 == len) {
0035             return sview.left(p1) + sview.mid(pos + 2);
0036         }
0037     }
0038     return label;
0039 }
0040 
0041 QString removeAcceleratorMarker(const QString &label_)
0042 {
0043     QString label = label_;
0044 
0045     int p = 0;
0046     bool accmarkRemoved = false;
0047     while (true) {
0048         p = label.indexOf(QLatin1Char('&'), p);
0049         if (p < 0 || p + 1 == label.length()) {
0050             break;
0051         }
0052 
0053         if (label.at(p + 1).isLetterOrNumber()) {
0054             // Valid accelerator.
0055             label.remove(p, 1);
0056 
0057             // May have been an accelerator in CJK-style "(&X)"
0058             // at the start or end of text.
0059             label = removeReducedCJKAccMark(label, p);
0060 
0061             accmarkRemoved = true;
0062         } else if (label.at(p + 1) == QLatin1Char('&')) {
0063             // Escaped accelerator marker.
0064             label.remove(p, 1);
0065         }
0066 
0067         ++p;
0068     }
0069 
0070     // If no marker was removed, and there are CJK characters in the label,
0071     // also try to remove reduced CJK marker -- something may have removed
0072     // ampersand beforehand.
0073     if (!accmarkRemoved) {
0074         bool hasCJK = false;
0075         for (const QChar c : std::as_const(label)) {
0076             if (c.unicode() >= 0x2e00) { // rough, but should be sufficient
0077                 hasCJK = true;
0078                 break;
0079             }
0080         }
0081         if (hasCJK) {
0082             p = 0;
0083             while (true) {
0084                 p = label.indexOf(QLatin1Char('('), p);
0085                 if (p < 0) {
0086                     break;
0087                 }
0088                 label = removeReducedCJKAccMark(label, p + 1);
0089                 ++p;
0090             }
0091         }
0092     }
0093 
0094     return label;
0095 }
0096 
0097 QString dateFormatWith4DigitYear(const QLocale &locale, QLocale::FormatType format)
0098 {
0099     // Clearly a workaround for QLocale using "yy" way too often for years
0100     // and so you get no way to distinguish between 1913 and 2013 anymore...
0101     // bummer.
0102     QString res = locale.dateFormat(format);
0103     res.replace(QLatin1String("yy"), QLatin1String("yyyy"));
0104     res.replace(QLatin1String("yyyyyyyy"), QLatin1String("yyyy"));
0105     return res;
0106 }