Eine aufbereitete Darstellung der Quelle
Stufen
Anforderungen
|
Konzepte
|
Entwurf
|
Entwicklung
|
Qualitätssicherung
|
Lebenszyklus
|
Steuerung
Ziele
Untersuchung
mit Columbo
Integrität von
Datenbanken
Interaktion und
Portierbarkeit
Ergonomie der
Schnittstellen
Angebot
Produkte
Projekt
Beratung
Mittel
Analytik
Modellierung
Sprachen
Algebra
Logik
Hardware
Denken
Kreativität
Zusammenhänge
Gesellschaft
Wirtschaft
Branche
Firma
Benutzer
products
/
Sources
/
formale Sprachen
/
C
/
Gnome
/
testsuite
/
svg
/
renderer
/ (
Gnome Linux Desktop
Version 4.23.2
©
) Datei vom 30.5.2026 mit Größe 121 B
Bilddatei
mnemonic.cxx
products/Sources/formale Sprachen/C/LibreOffice/vcl/source/window/mnemonic.cxx
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace ::com::sun::star; MnemonicGenerator::MnemonicGenerator(sal_Unicode cMnemonic) : m_cMnemonic(cMnemonic) { memset( maMnemonics, 1, sizeof( maMnemonics ) ); } MnemonicGenerator& MnemonicGenerator::operator=(MnemonicGenerator const &) = default; //MSVC2022 workaround MnemonicGenerator::MnemonicGenerator(MnemonicGenerator const&) = default; //MSVC2022 workaround sal_uInt16 MnemonicGenerator::ImplGetMnemonicIndex( sal_Unicode c ) { static sal_uInt16 const aImplMnemonicRangeTab[MNEMONIC_RANGES*2] = { MNEMONIC_RANGE_1_START, MNEMONIC_RANGE_1_END, MNEMONIC_RANGE_2_START, MNEMONIC_RANGE_2_END, MNEMONIC_RANGE_3_START, MNEMONIC_RANGE_3_END, MNEMONIC_RANGE_4_START, MNEMONIC_RANGE_4_END }; sal_uInt16 nMnemonicIndex = 0; for ( sal_uInt16 i = 0; i < MNEMONIC_RANGES; i++ ) { if ( (c >= aImplMnemonicRangeTab[i*2]) && (c <= aImplMnemonicRangeTab[i*2+1]) ) return nMnemonicIndex+c-aImplMnemonicRangeTab[i*2]; nMnemonicIndex += aImplMnemonicRangeTab[i*2+1]-aImplMnemonicRangeTab[i*2]; } return MNEMONIC_INDEX_NOTFOUND; } sal_Unicode MnemonicGenerator::ImplFindMnemonic( const OUString& rKey ) { sal_Int32 nIndex = 0; while ( (nIndex = rKey.indexOf( m_cMnemonic, nIndex )) != -1 ) { if (nIndex == rKey.getLength() - 1) { SAL_WARN("vcl", "key \"" << rKey << "\" ends in lone mnemonic prefix"); break; } sal_Unicode cMnemonic = rKey[ nIndex+1 ]; if ( cMnemonic != m_cMnemonic ) return cMnemonic; nIndex += 2; } return 0; } void MnemonicGenerator::RegisterMnemonic( const OUString& rKey ) { uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass(); // Don't crash even when we don't have access to i18n service if ( !xCharClass.is() ) return; OUString aKey = xCharClass->toLower(rKey, 0, rKey.getLength(), css::lang::Locale()); // If we find a Mnemonic, set the flag. In other case count the // characters, because we need this to set most as possible // Mnemonics sal_Unicode cMnemonic = ImplFindMnemonic( aKey ); if ( cMnemonic ) { sal_uInt16 nMnemonicIndex = ImplGetMnemonicIndex( cMnemonic ); if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) maMnemonics[nMnemonicIndex] = 0; } else { sal_Int32 nIndex = 0; sal_Int32 nLen = aKey.getLength(); while ( nIndex < nLen ) { sal_Unicode c = aKey[ nIndex ]; sal_uInt16 nMnemonicIndex = ImplGetMnemonicIndex( c ); if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) { if ( maMnemonics[nMnemonicIndex] && (maMnemonics[nMnemonicIndex] < 0xFF) ) maMnemonics[nMnemonicIndex]++; } nIndex++; } } } OUString MnemonicGenerator::CreateMnemonic( const OUString& _rKey ) { if ( _rKey.isEmpty() || ImplFindMnemonic( _rKey ) ) return _rKey; uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass(); // Don't crash even when we don't have access to i18n service if ( !xCharClass.is() ) return _rKey; OUString aKey = xCharClass->toLower(_rKey, 0, _rKey.getLength(), css::lang::Locale()); bool bChanged = false; sal_Int32 nLen = aKey.getLength(); bool bCJK = MsLangId::isCJK(Application::GetSettings().GetUILanguageTag().getLanguageType()); // #107889# in CJK versions ALL strings (even those that contain latin characters) // will get mnemonics in the form: xyz (M) // thus steps 1) and 2) are skipped for CJK locales // #110720#, avoid CJK-style mnemonics for latin-only strings that do not contain useful mnemonic chars if( bCJK ) { bool bLatinOnly = true; bool bMnemonicIndexFound = false; sal_Unicode c; sal_Int32 nIndex; for( nIndex=0; nIndex < nLen; nIndex++ ) { c = aKey[ nIndex ]; if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms { bLatinOnly = false; break; } if( ImplGetMnemonicIndex( c ) != MNEMONIC_INDEX_NOTFOUND ) bMnemonicIndexFound = true; } if( bLatinOnly && !bMnemonicIndexFound ) return _rKey; } OUString rKey(_rKey); int nCJK = 0; sal_uInt16 nMnemonicIndex; sal_Unicode c; sal_Int32 nIndex = 0; if( !bCJK ) { // 1) first try the first character of a word do { c = aKey[ nIndex ]; if ( nCJK != 2 ) { if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms nCJK = 1; else if ( ((c >= 0x0030) && (c <= 0x0039)) || // digits ((c >= 0x0041) && (c <= 0x005A)) || // latin capitals ((c >= 0x0061) && (c <= 0x007A)) || // latin small ((c >= 0x0370) && (c <= 0x037F)) || // greek numeral signs ((c >= 0x0400) && (c <= 0x04FF)) ) // cyrillic nCJK = 2; } nMnemonicIndex = ImplGetMnemonicIndex( c ); if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) { if ( maMnemonics[nMnemonicIndex] ) { maMnemonics[nMnemonicIndex] = 0; rKey = rKey.replaceAt( nIndex, 0, rtl::OUStringChar(m_cMnemonic) ); bChanged = true; break; } } // Search for next word nIndex++; while ( nIndex < nLen ) { c = aKey[ nIndex ]; if ( c == ' ' ) break; nIndex++; } nIndex++; } while ( nIndex < nLen ); // 2) search for a unique/uncommon character if ( !bChanged ) { sal_uInt16 nBestCount = 0xFFFF; sal_uInt16 nBestMnemonicIndex = 0; sal_Int32 nBestIndex = 0; nIndex = 0; do { c = aKey[ nIndex ]; nMnemonicIndex = ImplGetMnemonicIndex( c ); if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) { if ( maMnemonics[nMnemonicIndex] ) { if ( maMnemonics[nMnemonicIndex] < nBestCount ) { nBestCount = maMnemonics[nMnemonicIndex]; nBestIndex = nIndex; nBestMnemonicIndex = nMnemonicIndex; if ( nBestCount == 2 ) break; } } } nIndex++; } while ( nIndex < nLen ); if ( nBestCount != 0xFFFF ) { maMnemonics[nBestMnemonicIndex] = 0; rKey = rKey.replaceAt( nBestIndex, 0, rtl::OUStringChar(m_cMnemonic) ); bChanged = true; } } } else nCJK = 1; // 3) Add English Mnemonic for CJK Text if ( !bChanged && (nCJK == 1) && !rKey.isEmpty() ) { // Append Ascii Mnemonic for ( c = MNEMONIC_RANGE_2_START; c <= MNEMONIC_RANGE_2_END; c++ ) { nMnemonicIndex = ImplGetMnemonicIndex(c); if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) { if ( maMnemonics[nMnemonicIndex] ) { maMnemonics[nMnemonicIndex] = 0; OUString aStr = OUString::Concat("(") + OUStringChar(m_cMnemonic) + OUStringChar(sal_Unicode(rtl::toAsciiUpperCase(c))) + ")"; nIndex = rKey.getLength(); if( nIndex >= 2 ) { if ( ( rKey[nIndex-2] == '>' && rKey[nIndex-1] == '>' ) || ( rKey[nIndex-2] == 0xFF1E && rKey[nIndex-1] == 0xFF1E ) ) nIndex -= 2; } if( nIndex >= 3 ) { if ( ( rKey[nIndex-3] == '.' && rKey[nIndex-2] == '.' && rKey[nIndex-1] == '.' ) || ( rKey[nIndex-3] == 0xFF0E && rKey[nIndex-2] == 0xFF0E && rKey[nIndex-1] == 0xFF0E ) ) nIndex -= 3; } if( nIndex >= 1) { sal_Unicode cLastChar = rKey[ nIndex-1 ]; if ( (cLastChar == ':') || (cLastChar == 0xFF1A) || (cLastChar == '.') || (cLastChar == 0xFF0E) || (cLastChar == '?') || (cLastChar == 0xFF1F) || (cLastChar == ' ') ) nIndex--; } rKey = rKey.replaceAt( nIndex, 0, aStr ); break; } } } } return rKey; } uno::Reference< i18n::XCharacterClassification > const & MnemonicGenerator::GetCharClass() { if ( !mxCharClass.is() ) mxCharClass = vcl::unohelper::CreateCharacterClassification(); return mxCharClass; } OUString MnemonicGenerator::EraseAllMnemonicChars( const OUString& rStr ) { OUString aStr = rStr; sal_Int32 nLen = aStr.getLength(); sal_Int32 i = 0; while ( i < nLen ) { if ( aStr[ i ] == '~' ) { // check for CJK-style mnemonic if( i > 0 && (i+2) < nLen ) { sal_Unicode c = sal_Unicode(rtl::toAsciiLowerCase(aStr[i+1])); if( aStr[ i-1 ] == '(' && aStr[ i+2 ] == ')' && c >= MNEMONIC_RANGE_2_START && c <= MNEMONIC_RANGE_2_END ) { aStr = aStr.replaceAt( i-1, 4, u"" ); nLen -= 4; i--; continue; } } // remove standard mnemonics aStr = aStr.replaceAt( i, 1, u"" ); nLen--; } else i++; } return aStr; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Quellcodebibliothek
Eigene Quellcodes
Fremde Quellcodes
Suchen
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126438
#Domains=1897691
Impressum
|
Ethik und Gesetz
|
Haftungsausschluß
|
Kontakt
|
Seitenstruktur
|
©
2026 JDD
|