1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_vcl.hxx"
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski #include <string.h>
28*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
29*b1cdbd2cSJim Jagielski #include <vcl/settings.hxx>
30*b1cdbd2cSJim Jagielski #include <vcl/mnemonic.hxx>
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski #include <vcl/unohelp.hxx>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/XCharacterClassification.hpp>
34*b1cdbd2cSJim Jagielski
35*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
36*b1cdbd2cSJim Jagielski
37*b1cdbd2cSJim Jagielski
38*b1cdbd2cSJim Jagielski // =======================================================================
39*b1cdbd2cSJim Jagielski
MnemonicGenerator()40*b1cdbd2cSJim Jagielski MnemonicGenerator::MnemonicGenerator()
41*b1cdbd2cSJim Jagielski {
42*b1cdbd2cSJim Jagielski memset( maMnemonics, 1, sizeof( maMnemonics ) );
43*b1cdbd2cSJim Jagielski }
44*b1cdbd2cSJim Jagielski
45*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
46*b1cdbd2cSJim Jagielski
ImplGetMnemonicIndex(sal_Unicode c)47*b1cdbd2cSJim Jagielski sal_uInt16 MnemonicGenerator::ImplGetMnemonicIndex( sal_Unicode c )
48*b1cdbd2cSJim Jagielski {
49*b1cdbd2cSJim Jagielski static sal_uInt16 const aImplMnemonicRangeTab[MNEMONIC_RANGES*2] =
50*b1cdbd2cSJim Jagielski {
51*b1cdbd2cSJim Jagielski MNEMONIC_RANGE_1_START, MNEMONIC_RANGE_1_END,
52*b1cdbd2cSJim Jagielski MNEMONIC_RANGE_2_START, MNEMONIC_RANGE_2_END,
53*b1cdbd2cSJim Jagielski MNEMONIC_RANGE_3_START, MNEMONIC_RANGE_3_END,
54*b1cdbd2cSJim Jagielski MNEMONIC_RANGE_4_START, MNEMONIC_RANGE_4_END
55*b1cdbd2cSJim Jagielski };
56*b1cdbd2cSJim Jagielski
57*b1cdbd2cSJim Jagielski sal_uInt16 nMnemonicIndex = 0;
58*b1cdbd2cSJim Jagielski for ( sal_uInt16 i = 0; i < MNEMONIC_RANGES; i++ )
59*b1cdbd2cSJim Jagielski {
60*b1cdbd2cSJim Jagielski if ( (c >= aImplMnemonicRangeTab[i*2]) &&
61*b1cdbd2cSJim Jagielski (c <= aImplMnemonicRangeTab[i*2+1]) )
62*b1cdbd2cSJim Jagielski return nMnemonicIndex+c-aImplMnemonicRangeTab[i*2];
63*b1cdbd2cSJim Jagielski
64*b1cdbd2cSJim Jagielski nMnemonicIndex += aImplMnemonicRangeTab[i*2+1]-aImplMnemonicRangeTab[i*2];
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski
67*b1cdbd2cSJim Jagielski return MNEMONIC_INDEX_NOTFOUND;
68*b1cdbd2cSJim Jagielski }
69*b1cdbd2cSJim Jagielski
70*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
71*b1cdbd2cSJim Jagielski
ImplFindMnemonic(const XubString & rKey)72*b1cdbd2cSJim Jagielski sal_Unicode MnemonicGenerator::ImplFindMnemonic( const XubString& rKey )
73*b1cdbd2cSJim Jagielski {
74*b1cdbd2cSJim Jagielski xub_StrLen nIndex = 0;
75*b1cdbd2cSJim Jagielski while ( (nIndex = rKey.Search( MNEMONIC_CHAR, nIndex )) != STRING_NOTFOUND )
76*b1cdbd2cSJim Jagielski {
77*b1cdbd2cSJim Jagielski sal_Unicode cMnemonic = rKey.GetChar( nIndex+1 );
78*b1cdbd2cSJim Jagielski if ( cMnemonic != MNEMONIC_CHAR )
79*b1cdbd2cSJim Jagielski return cMnemonic;
80*b1cdbd2cSJim Jagielski nIndex += 2;
81*b1cdbd2cSJim Jagielski }
82*b1cdbd2cSJim Jagielski
83*b1cdbd2cSJim Jagielski return 0;
84*b1cdbd2cSJim Jagielski }
85*b1cdbd2cSJim Jagielski
86*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
87*b1cdbd2cSJim Jagielski
RegisterMnemonic(const XubString & rKey)88*b1cdbd2cSJim Jagielski void MnemonicGenerator::RegisterMnemonic( const XubString& rKey )
89*b1cdbd2cSJim Jagielski {
90*b1cdbd2cSJim Jagielski const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale();
91*b1cdbd2cSJim Jagielski uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass();
92*b1cdbd2cSJim Jagielski
93*b1cdbd2cSJim Jagielski // Don't crash even when we don't have access to i18n service
94*b1cdbd2cSJim Jagielski if ( !xCharClass.is() )
95*b1cdbd2cSJim Jagielski return;
96*b1cdbd2cSJim Jagielski
97*b1cdbd2cSJim Jagielski XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
98*b1cdbd2cSJim Jagielski
99*b1cdbd2cSJim Jagielski // If we find a Mnemonic, set the flag. In other case count the
100*b1cdbd2cSJim Jagielski // characters, because we need this to set most as possible
101*b1cdbd2cSJim Jagielski // Mnemonics
102*b1cdbd2cSJim Jagielski sal_Unicode cMnemonic = ImplFindMnemonic( aKey );
103*b1cdbd2cSJim Jagielski if ( cMnemonic )
104*b1cdbd2cSJim Jagielski {
105*b1cdbd2cSJim Jagielski sal_uInt16 nMnemonicIndex = ImplGetMnemonicIndex( cMnemonic );
106*b1cdbd2cSJim Jagielski if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
107*b1cdbd2cSJim Jagielski maMnemonics[nMnemonicIndex] = 0;
108*b1cdbd2cSJim Jagielski }
109*b1cdbd2cSJim Jagielski else
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski xub_StrLen nIndex = 0;
112*b1cdbd2cSJim Jagielski xub_StrLen nLen = aKey.Len();
113*b1cdbd2cSJim Jagielski while ( nIndex < nLen )
114*b1cdbd2cSJim Jagielski {
115*b1cdbd2cSJim Jagielski sal_Unicode c = aKey.GetChar( nIndex );
116*b1cdbd2cSJim Jagielski
117*b1cdbd2cSJim Jagielski sal_uInt16 nMnemonicIndex = ImplGetMnemonicIndex( c );
118*b1cdbd2cSJim Jagielski if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
119*b1cdbd2cSJim Jagielski {
120*b1cdbd2cSJim Jagielski if ( maMnemonics[nMnemonicIndex] && (maMnemonics[nMnemonicIndex] < 0xFF) )
121*b1cdbd2cSJim Jagielski maMnemonics[nMnemonicIndex]++;
122*b1cdbd2cSJim Jagielski }
123*b1cdbd2cSJim Jagielski
124*b1cdbd2cSJim Jagielski nIndex++;
125*b1cdbd2cSJim Jagielski }
126*b1cdbd2cSJim Jagielski }
127*b1cdbd2cSJim Jagielski }
128*b1cdbd2cSJim Jagielski
129*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
130*b1cdbd2cSJim Jagielski
CreateMnemonic(XubString & rKey)131*b1cdbd2cSJim Jagielski sal_Bool MnemonicGenerator::CreateMnemonic( XubString& rKey )
132*b1cdbd2cSJim Jagielski {
133*b1cdbd2cSJim Jagielski if ( !rKey.Len() || ImplFindMnemonic( rKey ) )
134*b1cdbd2cSJim Jagielski return sal_False;
135*b1cdbd2cSJim Jagielski
136*b1cdbd2cSJim Jagielski const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale();
137*b1cdbd2cSJim Jagielski uno::Reference < i18n::XCharacterClassification > xCharClass = GetCharClass();
138*b1cdbd2cSJim Jagielski
139*b1cdbd2cSJim Jagielski // Don't crash even when we don't have access to i18n service
140*b1cdbd2cSJim Jagielski if ( !xCharClass.is() )
141*b1cdbd2cSJim Jagielski return sal_False;
142*b1cdbd2cSJim Jagielski
143*b1cdbd2cSJim Jagielski XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
144*b1cdbd2cSJim Jagielski
145*b1cdbd2cSJim Jagielski sal_Bool bChanged = sal_False;
146*b1cdbd2cSJim Jagielski xub_StrLen nLen = aKey.Len();
147*b1cdbd2cSJim Jagielski
148*b1cdbd2cSJim Jagielski sal_Bool bCJK = sal_False;
149*b1cdbd2cSJim Jagielski switch( Application::GetSettings().GetUILanguage() )
150*b1cdbd2cSJim Jagielski {
151*b1cdbd2cSJim Jagielski case LANGUAGE_JAPANESE:
152*b1cdbd2cSJim Jagielski case LANGUAGE_CHINESE_TRADITIONAL:
153*b1cdbd2cSJim Jagielski case LANGUAGE_CHINESE_SIMPLIFIED:
154*b1cdbd2cSJim Jagielski case LANGUAGE_CHINESE_HONGKONG:
155*b1cdbd2cSJim Jagielski case LANGUAGE_CHINESE_SINGAPORE:
156*b1cdbd2cSJim Jagielski case LANGUAGE_CHINESE_MACAU:
157*b1cdbd2cSJim Jagielski case LANGUAGE_KOREAN:
158*b1cdbd2cSJim Jagielski case LANGUAGE_KOREAN_JOHAB:
159*b1cdbd2cSJim Jagielski bCJK = sal_True;
160*b1cdbd2cSJim Jagielski break;
161*b1cdbd2cSJim Jagielski default:
162*b1cdbd2cSJim Jagielski break;
163*b1cdbd2cSJim Jagielski }
164*b1cdbd2cSJim Jagielski // #107889# in CJK versions ALL strings (even those that contain latin characters)
165*b1cdbd2cSJim Jagielski // will get mnemonics in the form: xyz (M)
166*b1cdbd2cSJim Jagielski // thus steps 1) and 2) are skipped for CJK locales
167*b1cdbd2cSJim Jagielski
168*b1cdbd2cSJim Jagielski // #110720#, avoid CJK-style mnemonics for latin-only strings that do not contain useful mnemonic chars
169*b1cdbd2cSJim Jagielski if( bCJK )
170*b1cdbd2cSJim Jagielski {
171*b1cdbd2cSJim Jagielski sal_Bool bLatinOnly = sal_True;
172*b1cdbd2cSJim Jagielski sal_Bool bMnemonicIndexFound = sal_False;
173*b1cdbd2cSJim Jagielski sal_Unicode c;
174*b1cdbd2cSJim Jagielski xub_StrLen nIndex;
175*b1cdbd2cSJim Jagielski
176*b1cdbd2cSJim Jagielski for( nIndex=0; nIndex < nLen; nIndex++ )
177*b1cdbd2cSJim Jagielski {
178*b1cdbd2cSJim Jagielski c = aKey.GetChar( nIndex );
179*b1cdbd2cSJim Jagielski if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk
180*b1cdbd2cSJim Jagielski ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms
181*b1cdbd2cSJim Jagielski {
182*b1cdbd2cSJim Jagielski bLatinOnly = sal_False;
183*b1cdbd2cSJim Jagielski break;
184*b1cdbd2cSJim Jagielski }
185*b1cdbd2cSJim Jagielski if( ImplGetMnemonicIndex( c ) != MNEMONIC_INDEX_NOTFOUND )
186*b1cdbd2cSJim Jagielski bMnemonicIndexFound = sal_True;
187*b1cdbd2cSJim Jagielski }
188*b1cdbd2cSJim Jagielski if( bLatinOnly && !bMnemonicIndexFound )
189*b1cdbd2cSJim Jagielski return sal_False;
190*b1cdbd2cSJim Jagielski }
191*b1cdbd2cSJim Jagielski
192*b1cdbd2cSJim Jagielski
193*b1cdbd2cSJim Jagielski int nCJK = 0;
194*b1cdbd2cSJim Jagielski sal_uInt16 nMnemonicIndex;
195*b1cdbd2cSJim Jagielski sal_Unicode c;
196*b1cdbd2cSJim Jagielski xub_StrLen nIndex = 0;
197*b1cdbd2cSJim Jagielski if( !bCJK )
198*b1cdbd2cSJim Jagielski {
199*b1cdbd2cSJim Jagielski // 1) first try the first character of a word
200*b1cdbd2cSJim Jagielski do
201*b1cdbd2cSJim Jagielski {
202*b1cdbd2cSJim Jagielski c = aKey.GetChar( nIndex );
203*b1cdbd2cSJim Jagielski
204*b1cdbd2cSJim Jagielski if ( nCJK != 2 )
205*b1cdbd2cSJim Jagielski {
206*b1cdbd2cSJim Jagielski if ( ((c >= 0x3000) && (c <= 0xD7FF)) || // cjk
207*b1cdbd2cSJim Jagielski ((c >= 0xFF61) && (c <= 0xFFDC)) ) // halfwidth forms
208*b1cdbd2cSJim Jagielski nCJK = 1;
209*b1cdbd2cSJim Jagielski else if ( ((c >= 0x0030) && (c <= 0x0039)) || // digits
210*b1cdbd2cSJim Jagielski ((c >= 0x0041) && (c <= 0x005A)) || // latin capitals
211*b1cdbd2cSJim Jagielski ((c >= 0x0061) && (c <= 0x007A)) || // latin small
212*b1cdbd2cSJim Jagielski ((c >= 0x0370) && (c <= 0x037F)) || // greek numeral signs
213*b1cdbd2cSJim Jagielski ((c >= 0x0400) && (c <= 0x04FF)) ) // cyrillic
214*b1cdbd2cSJim Jagielski nCJK = 2;
215*b1cdbd2cSJim Jagielski }
216*b1cdbd2cSJim Jagielski
217*b1cdbd2cSJim Jagielski nMnemonicIndex = ImplGetMnemonicIndex( c );
218*b1cdbd2cSJim Jagielski if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
219*b1cdbd2cSJim Jagielski {
220*b1cdbd2cSJim Jagielski if ( maMnemonics[nMnemonicIndex] )
221*b1cdbd2cSJim Jagielski {
222*b1cdbd2cSJim Jagielski maMnemonics[nMnemonicIndex] = 0;
223*b1cdbd2cSJim Jagielski rKey.Insert( MNEMONIC_CHAR, nIndex );
224*b1cdbd2cSJim Jagielski bChanged = sal_True;
225*b1cdbd2cSJim Jagielski break;
226*b1cdbd2cSJim Jagielski }
227*b1cdbd2cSJim Jagielski }
228*b1cdbd2cSJim Jagielski
229*b1cdbd2cSJim Jagielski // Search for next word
230*b1cdbd2cSJim Jagielski do
231*b1cdbd2cSJim Jagielski {
232*b1cdbd2cSJim Jagielski nIndex++;
233*b1cdbd2cSJim Jagielski c = aKey.GetChar( nIndex );
234*b1cdbd2cSJim Jagielski if ( c == ' ' )
235*b1cdbd2cSJim Jagielski break;
236*b1cdbd2cSJim Jagielski }
237*b1cdbd2cSJim Jagielski while ( nIndex < nLen );
238*b1cdbd2cSJim Jagielski nIndex++;
239*b1cdbd2cSJim Jagielski }
240*b1cdbd2cSJim Jagielski while ( nIndex < nLen );
241*b1cdbd2cSJim Jagielski
242*b1cdbd2cSJim Jagielski // 2) search for a unique/uncommon character
243*b1cdbd2cSJim Jagielski if ( !bChanged )
244*b1cdbd2cSJim Jagielski {
245*b1cdbd2cSJim Jagielski sal_uInt16 nBestCount = 0xFFFF;
246*b1cdbd2cSJim Jagielski sal_uInt16 nBestMnemonicIndex = 0;
247*b1cdbd2cSJim Jagielski xub_StrLen nBestIndex = 0;
248*b1cdbd2cSJim Jagielski nIndex = 0;
249*b1cdbd2cSJim Jagielski do
250*b1cdbd2cSJim Jagielski {
251*b1cdbd2cSJim Jagielski c = aKey.GetChar( nIndex );
252*b1cdbd2cSJim Jagielski nMnemonicIndex = ImplGetMnemonicIndex( c );
253*b1cdbd2cSJim Jagielski if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
254*b1cdbd2cSJim Jagielski {
255*b1cdbd2cSJim Jagielski if ( maMnemonics[nMnemonicIndex] )
256*b1cdbd2cSJim Jagielski {
257*b1cdbd2cSJim Jagielski if ( maMnemonics[nMnemonicIndex] < nBestCount )
258*b1cdbd2cSJim Jagielski {
259*b1cdbd2cSJim Jagielski nBestCount = maMnemonics[nMnemonicIndex];
260*b1cdbd2cSJim Jagielski nBestIndex = nIndex;
261*b1cdbd2cSJim Jagielski nBestMnemonicIndex = nMnemonicIndex;
262*b1cdbd2cSJim Jagielski if ( nBestCount == 2 )
263*b1cdbd2cSJim Jagielski break;
264*b1cdbd2cSJim Jagielski }
265*b1cdbd2cSJim Jagielski }
266*b1cdbd2cSJim Jagielski }
267*b1cdbd2cSJim Jagielski
268*b1cdbd2cSJim Jagielski nIndex++;
269*b1cdbd2cSJim Jagielski }
270*b1cdbd2cSJim Jagielski while ( nIndex < nLen );
271*b1cdbd2cSJim Jagielski
272*b1cdbd2cSJim Jagielski if ( nBestCount != 0xFFFF )
273*b1cdbd2cSJim Jagielski {
274*b1cdbd2cSJim Jagielski maMnemonics[nBestMnemonicIndex] = 0;
275*b1cdbd2cSJim Jagielski rKey.Insert( MNEMONIC_CHAR, nBestIndex );
276*b1cdbd2cSJim Jagielski bChanged = sal_True;
277*b1cdbd2cSJim Jagielski }
278*b1cdbd2cSJim Jagielski }
279*b1cdbd2cSJim Jagielski }
280*b1cdbd2cSJim Jagielski else
281*b1cdbd2cSJim Jagielski nCJK = 1;
282*b1cdbd2cSJim Jagielski
283*b1cdbd2cSJim Jagielski // 3) Add English Mnemonic for CJK Text
284*b1cdbd2cSJim Jagielski if ( !bChanged && (nCJK == 1) && rKey.Len() )
285*b1cdbd2cSJim Jagielski {
286*b1cdbd2cSJim Jagielski // Append Ascii Mnemonic
287*b1cdbd2cSJim Jagielski for ( c = MNEMONIC_RANGE_2_START; c <= MNEMONIC_RANGE_2_END; c++ )
288*b1cdbd2cSJim Jagielski {
289*b1cdbd2cSJim Jagielski nMnemonicIndex = ImplGetMnemonicIndex( c );
290*b1cdbd2cSJim Jagielski if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
291*b1cdbd2cSJim Jagielski {
292*b1cdbd2cSJim Jagielski if ( maMnemonics[nMnemonicIndex] )
293*b1cdbd2cSJim Jagielski {
294*b1cdbd2cSJim Jagielski maMnemonics[nMnemonicIndex] = 0;
295*b1cdbd2cSJim Jagielski UniString aStr( '(' );
296*b1cdbd2cSJim Jagielski aStr += MNEMONIC_CHAR;
297*b1cdbd2cSJim Jagielski aStr += c;
298*b1cdbd2cSJim Jagielski aStr += ')';
299*b1cdbd2cSJim Jagielski nIndex = rKey.Len();
300*b1cdbd2cSJim Jagielski if( nIndex >= 2 )
301*b1cdbd2cSJim Jagielski {
302*b1cdbd2cSJim Jagielski static sal_Unicode cGreaterGreater[] = { 0xFF1E, 0xFF1E };
303*b1cdbd2cSJim Jagielski if ( rKey.EqualsAscii( ">>", nIndex-2, 2 ) ||
304*b1cdbd2cSJim Jagielski rKey.Equals( cGreaterGreater, nIndex-2, 2 ) )
305*b1cdbd2cSJim Jagielski nIndex -= 2;
306*b1cdbd2cSJim Jagielski }
307*b1cdbd2cSJim Jagielski if( nIndex >= 3 )
308*b1cdbd2cSJim Jagielski {
309*b1cdbd2cSJim Jagielski static sal_Unicode cDotDotDot[] = { 0xFF0E, 0xFF0E, 0xFF0E };
310*b1cdbd2cSJim Jagielski if ( rKey.EqualsAscii( "...", nIndex-3, 3 ) ||
311*b1cdbd2cSJim Jagielski rKey.Equals( cDotDotDot, nIndex-3, 3 ) )
312*b1cdbd2cSJim Jagielski nIndex -= 3;
313*b1cdbd2cSJim Jagielski }
314*b1cdbd2cSJim Jagielski if( nIndex >= 1)
315*b1cdbd2cSJim Jagielski {
316*b1cdbd2cSJim Jagielski sal_Unicode cLastChar = rKey.GetChar( nIndex-1 );
317*b1cdbd2cSJim Jagielski if ( (cLastChar == ':') || (cLastChar == 0xFF1A) ||
318*b1cdbd2cSJim Jagielski (cLastChar == '.') || (cLastChar == 0xFF0E) ||
319*b1cdbd2cSJim Jagielski (cLastChar == '?') || (cLastChar == 0xFF1F) ||
320*b1cdbd2cSJim Jagielski (cLastChar == ' ') )
321*b1cdbd2cSJim Jagielski nIndex--;
322*b1cdbd2cSJim Jagielski }
323*b1cdbd2cSJim Jagielski rKey.Insert( aStr, nIndex );
324*b1cdbd2cSJim Jagielski bChanged = sal_True;
325*b1cdbd2cSJim Jagielski break;
326*b1cdbd2cSJim Jagielski }
327*b1cdbd2cSJim Jagielski }
328*b1cdbd2cSJim Jagielski }
329*b1cdbd2cSJim Jagielski }
330*b1cdbd2cSJim Jagielski
331*b1cdbd2cSJim Jagielski // #i87415# Duplicates mnemonics are bad for consistent keyboard accessibility
332*b1cdbd2cSJim Jagielski // It's probably better to not have mnemonics for some widgets, than to have ambiguous ones.
333*b1cdbd2cSJim Jagielski // if( ! bChanged )
334*b1cdbd2cSJim Jagielski // {
335*b1cdbd2cSJim Jagielski // /*
336*b1cdbd2cSJim Jagielski // * #97809# if all else fails use the first character of a word
337*b1cdbd2cSJim Jagielski // * anyway and live with duplicate mnemonics
338*b1cdbd2cSJim Jagielski // */
339*b1cdbd2cSJim Jagielski // nIndex = 0;
340*b1cdbd2cSJim Jagielski // do
341*b1cdbd2cSJim Jagielski // {
342*b1cdbd2cSJim Jagielski // c = aKey.GetChar( nIndex );
343*b1cdbd2cSJim Jagielski //
344*b1cdbd2cSJim Jagielski // nMnemonicIndex = ImplGetMnemonicIndex( c );
345*b1cdbd2cSJim Jagielski // if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
346*b1cdbd2cSJim Jagielski // {
347*b1cdbd2cSJim Jagielski // maMnemonics[nMnemonicIndex] = 0;
348*b1cdbd2cSJim Jagielski // rKey.Insert( MNEMONIC_CHAR, nIndex );
349*b1cdbd2cSJim Jagielski // bChanged = sal_True;
350*b1cdbd2cSJim Jagielski // break;
351*b1cdbd2cSJim Jagielski // }
352*b1cdbd2cSJim Jagielski //
353*b1cdbd2cSJim Jagielski // // Search for next word
354*b1cdbd2cSJim Jagielski // do
355*b1cdbd2cSJim Jagielski // {
356*b1cdbd2cSJim Jagielski // nIndex++;
357*b1cdbd2cSJim Jagielski // c = aKey.GetChar( nIndex );
358*b1cdbd2cSJim Jagielski // if ( c == ' ' )
359*b1cdbd2cSJim Jagielski // break;
360*b1cdbd2cSJim Jagielski // }
361*b1cdbd2cSJim Jagielski // while ( nIndex < nLen );
362*b1cdbd2cSJim Jagielski // nIndex++;
363*b1cdbd2cSJim Jagielski // }
364*b1cdbd2cSJim Jagielski // while ( nIndex < nLen );
365*b1cdbd2cSJim Jagielski // }
366*b1cdbd2cSJim Jagielski
367*b1cdbd2cSJim Jagielski return bChanged;
368*b1cdbd2cSJim Jagielski }
369*b1cdbd2cSJim Jagielski
370*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
371*b1cdbd2cSJim Jagielski
GetCharClass()372*b1cdbd2cSJim Jagielski uno::Reference< i18n::XCharacterClassification > MnemonicGenerator::GetCharClass()
373*b1cdbd2cSJim Jagielski {
374*b1cdbd2cSJim Jagielski if ( !mxCharClass.is() )
375*b1cdbd2cSJim Jagielski mxCharClass = vcl::unohelper::CreateCharacterClassification();
376*b1cdbd2cSJim Jagielski return mxCharClass;
377*b1cdbd2cSJim Jagielski }
378*b1cdbd2cSJim Jagielski
379*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
380*b1cdbd2cSJim Jagielski
EraseAllMnemonicChars(const String & rStr)381*b1cdbd2cSJim Jagielski String MnemonicGenerator::EraseAllMnemonicChars( const String& rStr )
382*b1cdbd2cSJim Jagielski {
383*b1cdbd2cSJim Jagielski String aStr = rStr;
384*b1cdbd2cSJim Jagielski xub_StrLen nLen = aStr.Len();
385*b1cdbd2cSJim Jagielski xub_StrLen i = 0;
386*b1cdbd2cSJim Jagielski
387*b1cdbd2cSJim Jagielski while ( i < nLen )
388*b1cdbd2cSJim Jagielski {
389*b1cdbd2cSJim Jagielski if ( aStr.GetChar( i ) == '~' )
390*b1cdbd2cSJim Jagielski {
391*b1cdbd2cSJim Jagielski // check for CJK-style mnemonic
392*b1cdbd2cSJim Jagielski if( i > 0 && (i+2) < nLen )
393*b1cdbd2cSJim Jagielski {
394*b1cdbd2cSJim Jagielski sal_Unicode c = aStr.GetChar(i+1);
395*b1cdbd2cSJim Jagielski if( aStr.GetChar( i-1 ) == '(' &&
396*b1cdbd2cSJim Jagielski aStr.GetChar( i+2 ) == ')' &&
397*b1cdbd2cSJim Jagielski c >= MNEMONIC_RANGE_2_START && c <= MNEMONIC_RANGE_2_END )
398*b1cdbd2cSJim Jagielski {
399*b1cdbd2cSJim Jagielski aStr.Erase( i-1, 4 );
400*b1cdbd2cSJim Jagielski nLen -= 4;
401*b1cdbd2cSJim Jagielski i--;
402*b1cdbd2cSJim Jagielski continue;
403*b1cdbd2cSJim Jagielski }
404*b1cdbd2cSJim Jagielski }
405*b1cdbd2cSJim Jagielski
406*b1cdbd2cSJim Jagielski // remove standard mnemonics
407*b1cdbd2cSJim Jagielski aStr.Erase( i, 1 );
408*b1cdbd2cSJim Jagielski nLen--;
409*b1cdbd2cSJim Jagielski }
410*b1cdbd2cSJim Jagielski else
411*b1cdbd2cSJim Jagielski i++;
412*b1cdbd2cSJim Jagielski }
413*b1cdbd2cSJim Jagielski
414*b1cdbd2cSJim Jagielski return aStr;
415*b1cdbd2cSJim Jagielski }
416