File indexing completed on 2024-04-21 03:54:20

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