merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / gdi / fontcfg.cxx
blob0a5ec82ff654de3348879d3576c8a0df16700ebc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fontcfg.cxx,v $
10 * $Revision: 1.49.114.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <vcl/fontcfg.hxx>
34 #include <vcl/configsettings.hxx>
35 #include <vcl/outdev.hxx>
36 #include <vcl/svdata.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/unohelp.hxx>
39 #include <com/sun/star/uno/Any.hxx>
40 #include <com/sun/star/uno/Sequence.hxx>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <unotools/configpathes.hxx>
43 #include <rtl/ustrbuf.hxx>
45 #if OSL_DEBUG_LEVEL > 1
46 #include <stdio.h>
47 #endif
49 #include <string.h>
50 #include <list>
51 #include <algorithm>
53 #define DEFAULTFONT_CONFIGNODE "VCL/DefaultFonts"
54 #define SUBSTFONT_CONFIGNODE "VCL/FontSubstitutions"
55 #define SETTINGS_CONFIGNODE "VCL/Settings"
57 using namespace vcl;
58 using namespace rtl;
59 using namespace utl;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::lang;
62 using namespace com::sun::star::beans;
63 using namespace com::sun::star::container;
67 * DefaultFontConfiguration
70 static const char* getKeyType( int nKeyType )
72 switch( nKeyType )
74 case DEFAULTFONT_CJK_DISPLAY: return "CJK_DISPLAY";
75 case DEFAULTFONT_CJK_HEADING: return "CJK_HEADING";
76 case DEFAULTFONT_CJK_PRESENTATION: return "CJK_PRESENTATION";
77 case DEFAULTFONT_CJK_SPREADSHEET: return "CJK_SPREADSHEET";
78 case DEFAULTFONT_CJK_TEXT: return "CJK_TEXT";
79 case DEFAULTFONT_CTL_DISPLAY: return "CTL_DISPLAY";
80 case DEFAULTFONT_CTL_HEADING: return "CTL_HEADING";
81 case DEFAULTFONT_CTL_PRESENTATION: return "CTL_PRESENTATION";
82 case DEFAULTFONT_CTL_SPREADSHEET: return "CTL_SPREADSHEET";
83 case DEFAULTFONT_CTL_TEXT: return "CTL_TEXT";
84 case DEFAULTFONT_FIXED: return "FIXED";
85 case DEFAULTFONT_LATIN_DISPLAY: return "LATIN_DISPLAY";
86 case DEFAULTFONT_LATIN_FIXED: return "LATIN_FIXED";
87 case DEFAULTFONT_LATIN_HEADING: return "LATIN_HEADING";
88 case DEFAULTFONT_LATIN_PRESENTATION: return "LATIN_PRESENTATION";
89 case DEFAULTFONT_LATIN_SPREADSHEET: return "LATIN_SPREADSHEET";
90 case DEFAULTFONT_LATIN_TEXT: return "LATIN_TEXT";
91 case DEFAULTFONT_SANS: return "SANS";
92 case DEFAULTFONT_SANS_UNICODE: return "SANS_UNICODE";
93 case DEFAULTFONT_SERIF: return "SERIF";
94 case DEFAULTFONT_SYMBOL: return "SYMBOL";
95 case DEFAULTFONT_UI_FIXED: return "UI_FIXED";
96 case DEFAULTFONT_UI_SANS: return "UI_SANS";
97 default:
98 DBG_ERROR( "unmatched type" );
99 return "";
103 DefaultFontConfiguration* DefaultFontConfiguration::get()
105 ImplSVData* pSVData = ImplGetSVData();
106 if( ! pSVData->maGDIData.mpDefaultFontConfiguration )
107 pSVData->maGDIData.mpDefaultFontConfiguration = new DefaultFontConfiguration();
108 return pSVData->maGDIData.mpDefaultFontConfiguration;
111 DefaultFontConfiguration::DefaultFontConfiguration()
115 // get service provider
116 Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
117 // create configuration hierachical access name
118 if( xSMgr.is() )
122 m_xConfigProvider =
123 Reference< XMultiServiceFactory >(
124 xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
125 "com.sun.star.configuration.ConfigurationProvider" ))),
126 UNO_QUERY );
127 if( m_xConfigProvider.is() )
129 Sequence< Any > aArgs(1);
130 PropertyValue aVal;
131 aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
132 aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.VCL/DefaultFonts" ) );
133 aArgs.getArray()[0] <<= aVal;
134 m_xConfigAccess =
135 Reference< XNameAccess >(
136 m_xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
137 "com.sun.star.configuration.ConfigurationAccess" )),
138 aArgs ),
139 UNO_QUERY );
140 if( m_xConfigAccess.is() )
142 Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
143 // fill config hash with empty interfaces
144 int nLocales = aLocales.getLength();
145 const OUString* pLocaleStrings = aLocales.getConstArray();
146 Locale aLoc;
147 for( int i = 0; i < nLocales; i++ )
149 sal_Int32 nIndex = 0;
150 aLoc.Language = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiLowerCase();
151 if( nIndex != -1 )
152 aLoc.Country = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
153 else
154 aLoc.Country = OUString();
155 if( nIndex != -1 )
156 aLoc.Variant = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
157 else
158 aLoc.Variant = OUString();
159 m_aConfig[ aLoc ] = LocaleAccess();
160 m_aConfig[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
165 catch( Exception& )
167 // configuration is awry
168 m_xConfigProvider.clear();
169 m_xConfigAccess.clear();
173 catch( WrappedTargetException& )
176 #if OSL_DEBUG_LEVEL > 1
177 fprintf( stderr, "config provider: %s, config access: %s\n",
178 m_xConfigProvider.is() ? "true" : "false",
179 m_xConfigAccess.is() ? "true" : "false"
181 #endif
184 DefaultFontConfiguration::~DefaultFontConfiguration()
186 // release all nodes
187 m_aConfig.clear();
188 // release top node
189 m_xConfigAccess.clear();
190 // release config provider
191 m_xConfigProvider.clear();
194 OUString DefaultFontConfiguration::tryLocale( const Locale& rLocale, const OUString& rType ) const
196 OUString aRet;
198 std::hash_map< Locale, LocaleAccess, LocaleHash >::const_iterator it =
199 m_aConfig.find( rLocale );
200 if( it != m_aConfig.end() )
202 if( !it->second.xAccess.is() )
206 Reference< XNameAccess > xNode;
207 if ( m_xConfigAccess->hasByName( it->second.aConfigLocaleString ) )
209 Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
210 if( aAny >>= xNode )
211 it->second.xAccess = xNode;
214 catch( NoSuchElementException )
217 catch( WrappedTargetException )
221 if( it->second.xAccess.is() )
225 if ( it->second.xAccess->hasByName( rType ) )
227 Any aAny = it->second.xAccess->getByName( rType );
228 aAny >>= aRet;
231 catch( NoSuchElementException& )
234 catch( WrappedTargetException& )
240 return aRet;
243 OUString DefaultFontConfiguration::getDefaultFont( const Locale& rLocale, int nType ) const
245 Locale aLocale;
246 aLocale.Language = rLocale.Language.toAsciiLowerCase();
247 aLocale.Country = rLocale.Country.toAsciiUpperCase();
248 aLocale.Variant = rLocale.Variant.toAsciiUpperCase();
250 OUString aType = OUString::createFromAscii( getKeyType( nType ) );
251 OUString aRet = tryLocale( aLocale, aType );
252 if( ! aRet.getLength() && aLocale.Variant.getLength() )
254 aLocale.Variant = OUString();
255 aRet = tryLocale( aLocale, aType );
257 if( ! aRet.getLength() && aLocale.Country.getLength() )
259 aLocale.Country = OUString();
260 aRet = tryLocale( aLocale, aType );
262 if( ! aRet.getLength() )
264 aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
265 aRet = tryLocale( aLocale, aType );
267 return aRet;
270 OUString DefaultFontConfiguration::getUserInterfaceFont( const Locale& rLocale ) const
272 Locale aLocale = rLocale;
273 if( ! aLocale.Language.getLength() )
274 aLocale = Application::GetSettings().GetUILocale();
276 OUString aUIFont = getDefaultFont( aLocale, DEFAULTFONT_UI_SANS );
278 if( aUIFont.getLength() )
279 return aUIFont;
281 // fallback mechanism (either no configuration or no entry in configuration
283 #define FALLBACKFONT_UI_SANS "Andale Sans UI;Albany;Albany AMT;Tahoma;Arial Unicode MS;Arial;Nimbus Sans L;Bitstream Vera Sans;gnu-unifont;Interface User;Geneva;WarpSans;Dialog;Swiss;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Helv;Times;Times New Roman;Interface System"
284 #define FALLBACKFONT_UI_SANS_LATIN2 "Andale Sans UI;Albany;Albany AMT;Tahoma;Arial Unicode MS;Arial;Nimbus Sans L;Luxi Sans;Bitstream Vera Sans;Interface User;Geneva;WarpSans;Dialog;Swiss;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Helv;Times;Times New Roman;Interface System"
285 #define FALLBACKFONT_UI_SANS_ARABIC "Tahoma;Traditional Arabic;Simplified Arabic;Lucidasans;Lucida Sans;Supplement;Andale Sans UI;clearlyU;Interface User;Arial Unicode MS;Lucida Sans Unicode;WarpSans;Geneva;MS Sans Serif;Helv;Dialog;Albany;Lucida;Helvetica;Charcoal;Chicago;Arial;Helmet;Interface System;Sans Serif"
286 #define FALLBACKFONT_UI_SANS_THAI "OONaksit;Tahoma;Lucidasans;Arial Unicode MS"
287 #define FALLBACKFONT_UI_SANS_KOREAN "SunGulim;BaekmukGulim;Gulim;Roundgothic;Arial Unicode MS;Lucida Sans Unicode;gnu-unifont;Andale Sans UI"
288 #define FALLBACKFONT_UI_SANS_JAPANESE1 "HG-GothicB-Sun;Andale Sans UI;HG MhinchoLightJ"
289 #define FALLBACKFONT_UI_SANS_JAPANESE2 "Kochi Gothic;Gothic"
290 #define FALLBACKFONT_UI_SANS_CHINSIM "Andale Sans UI;Arial Unicode MS;ZYSong18030;AR PL SungtiL GB;AR PL KaitiM GB;SimSun;Lucida Sans Unicode;Fangsong;Hei;Song;Kai;Ming;gnu-unifont;Interface User;"
291 #define FALLBACKFONT_UI_SANS_CHINTRD "Andale Sans UI;Arial Unicode MS;AR PL Mingti2L Big5;AR PL KaitiM Big5;Kai;PMingLiU;MingLiU;Ming;Lucida Sans Unicode;gnu-unifont;Interface User;"
293 // we need localized names for japanese fonts
294 static sal_Unicode const aMSGothic[] = { 0xFF2D, 0xFF33, ' ', 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
295 static sal_Unicode const aMSPGothic[] = { 0xFF2D, 0xFF33, ' ', 0xFF30, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
296 static sal_Unicode const aTLPGothic[] = { 0x0054, 0x004C, 0x0050, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
297 static sal_Unicode const aLXGothic[] = { 0x004C, 0x0058, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
298 static sal_Unicode const aKochiGothic[] = { 0x6771, 0x98A8, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0, 0 };
300 String aFallBackJapaneseLocalized( RTL_CONSTASCII_USTRINGPARAM( "MS UI Gothic;" ) );
301 aFallBackJapaneseLocalized += String( RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_JAPANESE1 ) );
302 aFallBackJapaneseLocalized += String( aMSPGothic );
303 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
304 aFallBackJapaneseLocalized += String( aMSGothic );
305 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
306 aFallBackJapaneseLocalized += String( aTLPGothic );
307 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
308 aFallBackJapaneseLocalized += String( aLXGothic );
309 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
310 aFallBackJapaneseLocalized += String( aKochiGothic );
311 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
312 aFallBackJapaneseLocalized += String(RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_JAPANESE2 ) );
313 static const OUString aFallBackJapanese( aFallBackJapaneseLocalized );
314 static const OUString aFallback (RTL_CONSTASCII_USTRINGPARAM(FALLBACKFONT_UI_SANS));
315 static const OUString aFallbackLatin2 (RTL_CONSTASCII_USTRINGPARAM(FALLBACKFONT_UI_SANS_LATIN2));
316 static const OUString aFallBackArabic (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_ARABIC ) );
317 static const OUString aFallBackThai (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_THAI ) );
318 static const OUString aFallBackChineseSIM (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_CHINSIM ) );
319 static const OUString aFallBackChineseTRD (RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_CHINTRD ) );
321 // we need localized names for korean fonts
322 static sal_Unicode const aSunGulim[] = { 0xC36C, 0xAD74, 0xB9BC, 0 };
323 static sal_Unicode const aBaekmukGulim[] = { 0xBC31, 0xBC35, 0xAD74, 0xB9BC, 0 };
324 String aFallBackKoreanLocalized( aSunGulim );
325 aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
326 aFallBackKoreanLocalized += String( aBaekmukGulim );
327 aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( ";" ) );
328 aFallBackKoreanLocalized += String(RTL_CONSTASCII_USTRINGPARAM( FALLBACKFONT_UI_SANS_KOREAN ) );
329 static const OUString aFallBackKorean( aFallBackKoreanLocalized );
331 // optimize font list for some locales, as long as Andale Sans UI does not support them
332 if( aLocale.Language.equalsAscii( "ar" ) ||
333 aLocale.Language.equalsAscii( "he" ) ||
334 aLocale.Language.equalsAscii( "iw" ) )
336 return aFallBackArabic;
338 else if( aLocale.Language.equalsAscii( "th" ) )
340 return aFallBackThai;
342 else if( aLocale.Language.equalsAscii( "ko" ) )
344 return aFallBackKorean;
346 else if( aLocale.Language.equalsAscii( "cs" ) ||
347 aLocale.Language.equalsAscii( "hu" ) ||
348 aLocale.Language.equalsAscii( "pl" ) ||
349 aLocale.Language.equalsAscii( "ro" ) ||
350 aLocale.Language.equalsAscii( "rm" ) ||
351 aLocale.Language.equalsAscii( "hr" ) ||
352 aLocale.Language.equalsAscii( "sk" ) ||
353 aLocale.Language.equalsAscii( "sl" ) ||
354 aLocale.Language.equalsAscii( "sb" ) )
356 return aFallbackLatin2;
358 else if( aLocale.Language.equalsAscii( "zh" ) )
360 if( ! aLocale.Country.equalsAscii( "cn" ) )
361 return aFallBackChineseTRD;
362 else
363 return aFallBackChineseSIM;
365 else if( aLocale.Language.equalsAscii( "ja" ) )
367 return aFallBackJapanese;
370 return aFallback;
373 // ------------------------------------------------------------------------------------
376 * FontSubstConfigItem::get
379 FontSubstConfiguration* FontSubstConfiguration::get()
381 ImplSVData* pSVData = ImplGetSVData();
382 if( ! pSVData->maGDIData.mpFontSubstConfiguration )
383 pSVData->maGDIData.mpFontSubstConfiguration = new FontSubstConfiguration();
384 return pSVData->maGDIData.mpFontSubstConfiguration;
388 * FontSubstConfigItem::FontSubstConfigItem
391 FontSubstConfiguration::FontSubstConfiguration() :
392 maSubstHash( 300 )
396 // get service provider
397 Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
398 // create configuration hierachical access name
399 if( xSMgr.is() )
403 m_xConfigProvider =
404 Reference< XMultiServiceFactory >(
405 xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
406 "com.sun.star.configuration.ConfigurationProvider" ))),
407 UNO_QUERY );
408 if( m_xConfigProvider.is() )
410 Sequence< Any > aArgs(1);
411 PropertyValue aVal;
412 aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
413 aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.VCL/FontSubstitutions" ) );
414 aArgs.getArray()[0] <<= aVal;
415 m_xConfigAccess =
416 Reference< XNameAccess >(
417 m_xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
418 "com.sun.star.configuration.ConfigurationAccess" )),
419 aArgs ),
420 UNO_QUERY );
421 if( m_xConfigAccess.is() )
423 Sequence< OUString > aLocales = m_xConfigAccess->getElementNames();
424 // fill config hash with empty interfaces
425 int nLocales = aLocales.getLength();
426 const OUString* pLocaleStrings = aLocales.getConstArray();
427 Locale aLoc;
428 for( int i = 0; i < nLocales; i++ )
430 sal_Int32 nIndex = 0;
431 aLoc.Language = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiLowerCase();
432 if( nIndex != -1 )
433 aLoc.Country = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
434 else
435 aLoc.Country = OUString();
436 if( nIndex != -1 )
437 aLoc.Variant = pLocaleStrings[i].getToken( 0, sal_Unicode('-'), nIndex ).toAsciiUpperCase();
438 else
439 aLoc.Variant = OUString();
440 m_aSubst[ aLoc ] = LocaleSubst();
441 m_aSubst[ aLoc ].aConfigLocaleString = pLocaleStrings[i];
446 catch( Exception& )
448 // configuration is awry
449 m_xConfigProvider.clear();
450 m_xConfigAccess.clear();
454 catch( WrappedTargetException& )
457 #if OSL_DEBUG_LEVEL > 1
458 fprintf( stderr, "config provider: %s, config access: %s\n",
459 m_xConfigProvider.is() ? "true" : "false",
460 m_xConfigAccess.is() ? "true" : "false"
462 #endif
466 * FontSubstConfigItem::~FontSubstConfigItem
469 FontSubstConfiguration::~FontSubstConfiguration()
471 // release config access
472 m_xConfigAccess.clear();
473 // release config provider
474 m_xConfigProvider.clear();
478 * FontSubstConfigItem::getMapName
480 // =======================================================================
482 static const char* const aImplKillLeadingList[] =
484 "microsoft",
485 "monotype",
486 "linotype",
487 "baekmuk",
488 "adobe",
489 "nimbus",
490 "zycjk",
491 "itc",
492 "sun",
493 "amt",
494 "ms",
495 "mt",
496 "cg",
497 "hg",
498 "fz",
499 "ipa",
500 "sazanami",
501 "kochi",
502 NULL
505 // -----------------------------------------------------------------------
507 static const char* const aImplKillTrailingList[] =
509 "microsoft",
510 "monotype",
511 "linotype",
512 "adobe",
513 "nimbus",
514 "itc",
515 "sun",
516 "amt",
517 "ms",
518 "mt",
519 "clm",
520 // Scripts, for compatibility with older versions
521 "we",
522 "cyr",
523 "tur",
524 "wt",
525 "greek",
526 "wl",
527 // CJK extensions
528 "gb",
529 "big5",
530 "pro",
531 "z01",
532 "z02",
533 "z03",
534 "z13",
535 "b01",
536 "w3x12",
537 // Old Printer Fontnames
538 "5cpi",
539 "6cpi",
540 "7cpi",
541 "8cpi",
542 "9cpi",
543 "10cpi",
544 "11cpi",
545 "12cpi",
546 "13cpi",
547 "14cpi",
548 "15cpi",
549 "16cpi",
550 "18cpi",
551 "24cpi",
552 "scale",
553 "pc",
554 NULL
557 // -----------------------------------------------------------------------
559 static const char* const aImplKillTrailingWithExceptionsList[] =
561 "ce", "monospace", "oldface", NULL,
562 "ps", "caps", NULL,
563 NULL
566 // -----------------------------------------------------------------------
568 struct ImplFontAttrWeightSearchData
570 const char* mpStr;
571 FontWeight meWeight;
574 static ImplFontAttrWeightSearchData const aImplWeightAttrSearchList[] =
576 // the attribute names are ordered by "first match wins"
577 // e.g. "semilight" should wins over "semi"
578 { "extrablack", WEIGHT_BLACK },
579 { "ultrablack", WEIGHT_BLACK },
580 { "ultrabold", WEIGHT_ULTRABOLD },
581 { "semibold", WEIGHT_SEMIBOLD },
582 { "semilight", WEIGHT_SEMILIGHT },
583 { "semi", WEIGHT_SEMIBOLD },
584 { "demi", WEIGHT_SEMIBOLD },
585 { "black", WEIGHT_BLACK },
586 { "bold", WEIGHT_BOLD },
587 { "heavy", WEIGHT_BLACK },
588 { "ultralight", WEIGHT_ULTRALIGHT },
589 { "light", WEIGHT_LIGHT },
590 { "medium", WEIGHT_MEDIUM },
591 { NULL, WEIGHT_DONTKNOW },
594 // -----------------------------------------------------------------------
596 struct ImplFontAttrWidthSearchData
598 const char* mpStr;
599 FontWidth meWidth;
602 static ImplFontAttrWidthSearchData const aImplWidthAttrSearchList[] =
604 { "narrow", WIDTH_CONDENSED },
605 { "semicondensed", WIDTH_SEMI_CONDENSED },
606 { "ultracondensed", WIDTH_ULTRA_CONDENSED },
607 { "semiexpanded", WIDTH_SEMI_EXPANDED },
608 { "ultraexpanded", WIDTH_ULTRA_EXPANDED },
609 { "expanded", WIDTH_EXPANDED },
610 { "wide", WIDTH_ULTRA_EXPANDED },
611 { "condensed", WIDTH_CONDENSED },
612 { "cond", WIDTH_CONDENSED },
613 { "cn", WIDTH_CONDENSED },
614 { NULL, WIDTH_DONTKNOW },
617 struct ImplFontAttrTypeSearchData
619 const char* mpStr;
620 ULONG mnType;
623 static ImplFontAttrTypeSearchData const aImplTypeAttrSearchList[] =
625 { "monotype", 0 },
626 { "linotype", 0 },
627 { "titling", IMPL_FONT_ATTR_TITLING },
628 { "captitals", IMPL_FONT_ATTR_CAPITALS },
629 { "captital", IMPL_FONT_ATTR_CAPITALS },
630 { "caps", IMPL_FONT_ATTR_CAPITALS },
631 { "italic", IMPL_FONT_ATTR_ITALIC },
632 { "oblique", IMPL_FONT_ATTR_ITALIC },
633 { "rounded", IMPL_FONT_ATTR_ROUNDED },
634 { "outline", IMPL_FONT_ATTR_OUTLINE },
635 { "shadow", IMPL_FONT_ATTR_SHADOW },
636 { "handwriting", IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
637 { "hand", IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
638 { "signet", IMPL_FONT_ATTR_HANDWRITING | IMPL_FONT_ATTR_SCRIPT },
639 { "script", IMPL_FONT_ATTR_BRUSHSCRIPT | IMPL_FONT_ATTR_SCRIPT },
640 { "calligraphy", IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
641 { "chancery", IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
642 { "corsiva", IMPL_FONT_ATTR_CHANCERY | IMPL_FONT_ATTR_SCRIPT },
643 { "gothic", IMPL_FONT_ATTR_SANSSERIF | IMPL_FONT_ATTR_GOTHIC },
644 { "schoolbook", IMPL_FONT_ATTR_SERIF | IMPL_FONT_ATTR_SCHOOLBOOK },
645 { "schlbk", IMPL_FONT_ATTR_SERIF | IMPL_FONT_ATTR_SCHOOLBOOK },
646 { "typewriter", IMPL_FONT_ATTR_TYPEWRITER | IMPL_FONT_ATTR_FIXED },
647 { "lineprinter", IMPL_FONT_ATTR_TYPEWRITER | IMPL_FONT_ATTR_FIXED },
648 { "monospaced", IMPL_FONT_ATTR_FIXED },
649 { "monospace", IMPL_FONT_ATTR_FIXED },
650 { "mono", IMPL_FONT_ATTR_FIXED },
651 { "fixed", IMPL_FONT_ATTR_FIXED },
652 { "sansserif", IMPL_FONT_ATTR_SANSSERIF },
653 { "sans", IMPL_FONT_ATTR_SANSSERIF },
654 { "swiss", IMPL_FONT_ATTR_SANSSERIF },
655 { "serif", IMPL_FONT_ATTR_SERIF },
656 { "bright", IMPL_FONT_ATTR_SERIF },
657 { "symbols", IMPL_FONT_ATTR_SYMBOL },
658 { "symbol", IMPL_FONT_ATTR_SYMBOL },
659 { "dingbats", IMPL_FONT_ATTR_SYMBOL },
660 { "dings", IMPL_FONT_ATTR_SYMBOL },
661 { "ding", IMPL_FONT_ATTR_SYMBOL },
662 { "bats", IMPL_FONT_ATTR_SYMBOL },
663 { "math", IMPL_FONT_ATTR_SYMBOL },
664 { "oldstyle", IMPL_FONT_ATTR_OTHERSTYLE },
665 { "oldface", IMPL_FONT_ATTR_OTHERSTYLE },
666 { "old", IMPL_FONT_ATTR_OTHERSTYLE },
667 { "new", 0 },
668 { "modern", 0 },
669 { "lucida", 0 },
670 { "regular", 0 },
671 { "extended", 0 },
672 { "extra", IMPL_FONT_ATTR_OTHERSTYLE },
673 { "ext", 0 },
674 { "scalable", 0 },
675 { "scale", 0 },
676 { "nimbus", 0 },
677 { "adobe", 0 },
678 { "itc", 0 },
679 { "amt", 0 },
680 { "mt", 0 },
681 { "ms", 0 },
682 { "cpi", 0 },
683 { "no", 0 },
684 { NULL, 0 },
687 // -----------------------------------------------------------------------
689 static bool ImplKillLeading( String& rName, const char* const* ppStr )
691 for(; *ppStr; ++ppStr )
693 const char* pStr = *ppStr;
694 const xub_Unicode* pNameStr = rName.GetBuffer();
695 while ( (*pNameStr == (xub_Unicode)(unsigned char)*pStr) && *pStr )
697 pNameStr++;
698 pStr++;
700 if ( !*pStr )
702 xub_StrLen nLen = sal::static_int_cast<xub_StrLen>(pNameStr - rName.GetBuffer());
703 rName.Erase( 0, nLen );
704 return true;
708 // special case for Baekmuk
709 // TODO: allow non-ASCII KillLeading list
710 const xub_Unicode* pNameStr = rName.GetBuffer();
711 if( (pNameStr[0]==0xBC31) && (pNameStr[1]==0xBC35) )
713 xub_StrLen nLen = (pNameStr[2]==0x0020) ? 3 : 2;
714 rName.Erase( 0, nLen );
715 return true;
718 return false;
721 // -----------------------------------------------------------------------
723 static xub_StrLen ImplIsTrailing( const String& rName, const char* pStr )
725 xub_StrLen nStrLen = static_cast<xub_StrLen>( strlen( pStr ) );
726 if( nStrLen >= rName.Len() )
727 return 0;
729 const xub_Unicode* pEndName = rName.GetBuffer() + rName.Len();
730 const sal_Unicode* pNameStr = pEndName - nStrLen;
731 do if( *(pNameStr++) != *(pStr++) )
732 return 0;
733 while( *pStr );
735 return nStrLen;
738 // -----------------------------------------------------------------------
740 static bool ImplKillTrailing( String& rName, const char* const* ppStr )
742 for(; *ppStr; ++ppStr )
744 xub_StrLen nTrailLen = ImplIsTrailing( rName, *ppStr );
745 if( nTrailLen )
747 rName.Erase( rName.Len()-nTrailLen );
748 return true;
752 return false;
755 // -----------------------------------------------------------------------
757 static bool ImplKillTrailingWithExceptions( String& rName, const char* const* ppStr )
759 for(; *ppStr; ++ppStr )
761 xub_StrLen nTrailLen = ImplIsTrailing( rName, *ppStr );
762 if( nTrailLen )
764 // check string match against string exceptions
765 while( *++ppStr )
766 if( ImplIsTrailing( rName, *ppStr ) )
767 return false;
769 rName.Erase( rName.Len()-nTrailLen );
770 return true;
772 else
774 // skip exception strings
775 while( *++ppStr ) ;
779 return false;
782 // -----------------------------------------------------------------------
784 static BOOL ImplFindAndErase( String& rName, const char* pStr )
786 xub_StrLen nPos = rName.SearchAscii( pStr );
787 if ( nPos == STRING_NOTFOUND )
788 return FALSE;
790 const char* pTempStr = pStr;
791 while ( *pTempStr )
792 pTempStr++;
793 rName.Erase( nPos, (xub_StrLen)(pTempStr-pStr) );
794 return TRUE;
797 // =======================================================================
799 void FontSubstConfiguration::getMapName( const String& rOrgName, String& rShortName,
800 String& rFamilyName, FontWeight& rWeight, FontWidth& rWidth, ULONG& rType )
802 rShortName = rOrgName;
804 // TODO: get rid of the crazy O(N*strlen) searches below
805 // they should be possible in O(strlen)
807 // Kill leading vendor names and other unimportant data
808 ImplKillLeading( rShortName, aImplKillLeadingList );
810 // Kill trailing vendor names and other unimportant data
811 ImplKillTrailing( rShortName, aImplKillTrailingList );
812 ImplKillTrailingWithExceptions( rShortName, aImplKillTrailingWithExceptionsList );
814 rFamilyName = rShortName;
816 // Kill attributes from the name and update the data
817 // Weight
818 const ImplFontAttrWeightSearchData* pWeightList = aImplWeightAttrSearchList;
819 while ( pWeightList->mpStr )
821 if ( ImplFindAndErase( rFamilyName, pWeightList->mpStr ) )
823 if ( (rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL) )
824 rWeight = pWeightList->meWeight;
825 break;
827 pWeightList++;
830 // Width
831 const ImplFontAttrWidthSearchData* pWidthList = aImplWidthAttrSearchList;
832 while ( pWidthList->mpStr )
834 if ( ImplFindAndErase( rFamilyName, pWidthList->mpStr ) )
836 if ( (rWidth == WIDTH_DONTKNOW) || (rWidth == WIDTH_NORMAL) )
837 rWidth = pWidthList->meWidth;
838 break;
840 pWidthList++;
843 // Type
844 rType = 0;
845 const ImplFontAttrTypeSearchData* pTypeList = aImplTypeAttrSearchList;
846 while ( pTypeList->mpStr )
848 if ( ImplFindAndErase( rFamilyName, pTypeList->mpStr ) )
849 rType |= pTypeList->mnType;
850 pTypeList++;
853 // Remove numbers
854 // TODO: also remove localized and fullwidth digits
855 xub_StrLen i = 0;
856 while ( i < rFamilyName.Len() )
858 sal_Unicode c = rFamilyName.GetChar( i );
859 if ( (c >= 0x0030) && (c <= 0x0039) )
860 rFamilyName.Erase( i, 1 );
861 else
862 i++;
867 struct StrictStringSort : public ::std::binary_function< const FontNameAttr&, const FontNameAttr&, bool >
869 bool operator()( const FontNameAttr& rLeft, const FontNameAttr& rRight )
870 { return rLeft.Name.CompareTo( rRight.Name ) == COMPARE_LESS ; }
873 static const char* const pAttribNames[] =
875 "default",
876 "standard",
877 "normal",
878 "symbol",
879 "fixed",
880 "sansserif",
881 "serif",
882 "decorative",
883 "special",
884 "italic",
885 "title",
886 "capitals",
887 "cjk",
888 "cjk_jp",
889 "cjk_sc",
890 "cjk_tc",
891 "cjk_kr",
892 "ctl",
893 "nonelatin",
894 "full",
895 "outline",
896 "shadow",
897 "rounded",
898 "typewriter",
899 "script",
900 "handwriting",
901 "chancery",
902 "comic",
903 "brushscript",
904 "gothic",
905 "schoolbook",
906 "other"
909 struct enum_convert
911 const char* pName;
912 int nEnum;
916 static const enum_convert pWeightNames[] =
918 { "normal", WEIGHT_NORMAL },
919 { "medium", WEIGHT_MEDIUM },
920 { "bold", WEIGHT_BOLD },
921 { "black", WEIGHT_BLACK },
922 { "semibold", WEIGHT_SEMIBOLD },
923 { "light", WEIGHT_LIGHT },
924 { "semilight", WEIGHT_SEMILIGHT },
925 { "ultrabold", WEIGHT_ULTRABOLD },
926 { "semi", WEIGHT_SEMIBOLD },
927 { "demi", WEIGHT_SEMIBOLD },
928 { "heavy", WEIGHT_BLACK },
929 { "unknown", WEIGHT_DONTKNOW },
930 { "thin", WEIGHT_THIN },
931 { "ultralight", WEIGHT_ULTRALIGHT }
934 static const enum_convert pWidthNames[] =
936 { "normal", WIDTH_NORMAL },
937 { "condensed", WIDTH_CONDENSED },
938 { "expanded", WIDTH_EXPANDED },
939 { "unknown", WIDTH_DONTKNOW },
940 { "ultracondensed", WIDTH_ULTRA_CONDENSED },
941 { "extracondensed", WIDTH_EXTRA_CONDENSED },
942 { "semicondensed", WIDTH_SEMI_CONDENSED },
943 { "semiexpanded", WIDTH_SEMI_EXPANDED },
944 { "extraexpanded", WIDTH_EXTRA_EXPANDED },
945 { "ultraexpanded", WIDTH_ULTRA_EXPANDED }
948 void FontSubstConfiguration::fillSubstVector( const com::sun::star::uno::Reference< XNameAccess > xFont,
949 const rtl::OUString& rType,
950 std::vector< String >& rSubstVector ) const
954 Any aAny = xFont->getByName( rType );
955 if( aAny.getValueTypeClass() == TypeClass_STRING )
957 const OUString* pLine = (const OUString*)aAny.getValue();
958 sal_Int32 nIndex = 0;
959 sal_Int32 nLength = pLine->getLength();
960 if( nLength )
962 const sal_Unicode* pStr = pLine->getStr();
963 sal_Int32 nTokens = 0;
964 // count tokens
965 while( nLength-- )
967 if( *pStr++ == sal_Unicode(';') )
968 nTokens++;
970 rSubstVector.clear();
971 // optimize performance, heap fragmentation
972 rSubstVector.reserve( nTokens );
973 while( nIndex != -1 )
975 OUString aSubst( pLine->getToken( 0, ';', nIndex ) );
976 if( aSubst.getLength() )
978 UniqueSubstHash::iterator aEntry = maSubstHash.find( aSubst );
979 if (aEntry != maSubstHash.end())
980 aSubst = *aEntry;
981 else
982 maSubstHash.insert( aSubst );
983 rSubstVector.push_back( aSubst );
989 catch( NoSuchElementException )
992 catch( WrappedTargetException )
997 FontWeight FontSubstConfiguration::getSubstWeight( const com::sun::star::uno::Reference< XNameAccess > xFont,
998 const rtl::OUString& rType ) const
1000 int weight = -1;
1003 Any aAny = xFont->getByName( rType );
1004 if( aAny.getValueTypeClass() == TypeClass_STRING )
1006 const OUString* pLine = (const OUString*)aAny.getValue();
1007 if( pLine->getLength() )
1009 for( weight=sizeof(pWeightNames)/sizeof(pWeightNames[0])-1; weight >= 0; weight-- )
1010 if( pLine->equalsIgnoreAsciiCaseAscii( pWeightNames[weight].pName ) )
1011 break;
1013 #if OSL_DEBUG_LEVEL > 1
1014 if( weight < 0 )
1015 fprintf( stderr, "Error: invalid weight %s\n",
1016 OUStringToOString( *pLine, RTL_TEXTENCODING_ASCII_US ).getStr() );
1017 #endif
1020 catch( NoSuchElementException )
1023 catch( WrappedTargetException )
1026 return (FontWeight)( weight >= 0 ? pWeightNames[weight].nEnum : WEIGHT_DONTKNOW );
1029 FontWidth FontSubstConfiguration::getSubstWidth( const com::sun::star::uno::Reference< XNameAccess > xFont,
1030 const rtl::OUString& rType ) const
1032 int width = -1;
1035 Any aAny = xFont->getByName( rType );
1036 if( aAny.getValueTypeClass() == TypeClass_STRING )
1038 const OUString* pLine = (const OUString*)aAny.getValue();
1039 if( pLine->getLength() )
1041 for( width=sizeof(pWidthNames)/sizeof(pWidthNames[0])-1; width >= 0; width-- )
1042 if( pLine->equalsIgnoreAsciiCaseAscii( pWidthNames[width].pName ) )
1043 break;
1045 #if OSL_DEBUG_LEVEL > 1
1046 if( width < 0 )
1047 fprintf( stderr, "Error: invalid width %s\n",
1048 OUStringToOString( *pLine, RTL_TEXTENCODING_ASCII_US ).getStr() );
1049 #endif
1052 catch( NoSuchElementException )
1055 catch( WrappedTargetException )
1058 return (FontWidth)( width >= 0 ? pWidthNames[width].nEnum : WIDTH_DONTKNOW );
1061 unsigned long FontSubstConfiguration::getSubstType( const com::sun::star::uno::Reference< XNameAccess > xFont,
1062 const rtl::OUString& rType ) const
1064 unsigned long type = 0;
1067 Any aAny = xFont->getByName( rType );
1068 if( aAny.getValueTypeClass() == TypeClass_STRING )
1070 const OUString* pLine = (const OUString*)aAny.getValue();
1071 if( pLine->getLength() )
1073 sal_Int32 nIndex = 0;
1074 while( nIndex != -1 )
1076 String aToken( pLine->getToken( 0, ',', nIndex ) );
1077 for( int k = 0; k < 32; k++ )
1078 if( aToken.EqualsIgnoreCaseAscii( pAttribNames[k] ) )
1080 type |= 1 << k;
1081 break;
1087 catch( NoSuchElementException )
1090 catch( WrappedTargetException )
1094 return type;
1097 void FontSubstConfiguration::readLocaleSubst( const com::sun::star::lang::Locale& rLocale ) const
1099 std::hash_map< Locale, LocaleSubst, LocaleHash >::const_iterator it =
1100 m_aSubst.find( rLocale );
1101 if( it != m_aSubst.end() )
1103 if( ! it->second.bConfigRead )
1105 it->second.bConfigRead = true;
1106 Reference< XNameAccess > xNode;
1109 Any aAny = m_xConfigAccess->getByName( it->second.aConfigLocaleString );
1110 aAny >>= xNode;
1112 catch( NoSuchElementException )
1115 catch( WrappedTargetException )
1118 if( xNode.is() )
1120 Sequence< OUString > aFonts = xNode->getElementNames();
1121 int nFonts = aFonts.getLength();
1122 const OUString* pFontNames = aFonts.getConstArray();
1123 // improve performance, heap fragmentation
1124 it->second.aSubstAttributes.reserve( nFonts );
1126 // strings for subst retrieval, construct only once
1127 OUString aSubstFontsStr ( RTL_CONSTASCII_USTRINGPARAM( "SubstFonts" ) );
1128 OUString aSubstFontsMSStr ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsMS" ) );
1129 OUString aSubstFontsPSStr ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsPS" ) );
1130 OUString aSubstFontsHTMLStr ( RTL_CONSTASCII_USTRINGPARAM( "SubstFontsHTML" ) );
1131 OUString aSubstWeightStr ( RTL_CONSTASCII_USTRINGPARAM( "FontWeight" ) );
1132 OUString aSubstWidthStr ( RTL_CONSTASCII_USTRINGPARAM( "FontWidth" ) );
1133 OUString aSubstTypeStr ( RTL_CONSTASCII_USTRINGPARAM( "FontType" ) );
1134 for( int i = 0; i < nFonts; i++ )
1136 Reference< XNameAccess > xFont;
1139 Any aAny = xNode->getByName( pFontNames[i] );
1140 aAny >>= xFont;
1142 catch( NoSuchElementException )
1145 catch( WrappedTargetException )
1148 if( ! xFont.is() )
1150 #if OSL_DEBUG_LEVEL > 1
1151 fprintf( stderr, "did not get font attributes for %s\n",
1152 OUStringToOString( pFontNames[i], RTL_TEXTENCODING_UTF8 ).getStr() );
1153 #endif
1154 continue;
1157 FontNameAttr aAttr;
1158 // read subst attributes from config
1159 aAttr.Name = pFontNames[i];
1160 fillSubstVector( xFont, aSubstFontsStr, aAttr.Substitutions );
1161 fillSubstVector( xFont, aSubstFontsMSStr, aAttr.MSSubstitutions );
1162 fillSubstVector( xFont, aSubstFontsPSStr, aAttr.PSSubstitutions );
1163 fillSubstVector( xFont, aSubstFontsHTMLStr, aAttr.HTMLSubstitutions );
1164 aAttr.Weight = getSubstWeight( xFont, aSubstWeightStr );
1165 aAttr.Width = getSubstWidth( xFont, aSubstWidthStr );
1166 aAttr.Type = getSubstType( xFont, aSubstTypeStr );
1168 // finally insert this entry
1169 it->second.aSubstAttributes.push_back( aAttr );
1171 std::sort( it->second.aSubstAttributes.begin(), it->second.aSubstAttributes.end(), StrictStringSort() );
1177 const FontNameAttr* FontSubstConfiguration::getSubstInfo( const String& rFontName, const Locale& rLocale ) const
1179 if( !rFontName.Len() )
1180 return NULL;
1182 // search if a (language dep.) replacement table for the given font exists
1183 // fallback is english
1184 String aSearchFont( rFontName );
1185 aSearchFont.ToLowerAscii();
1186 FontNameAttr aSearchAttr;
1187 aSearchAttr.Name = aSearchFont;
1189 Locale aLocale;
1190 aLocale.Language = rLocale.Language.toAsciiLowerCase();
1191 aLocale.Country = rLocale.Country.toAsciiUpperCase();
1192 aLocale.Variant = rLocale.Variant.toAsciiUpperCase();
1194 if( ! aLocale.Language.getLength() )
1195 aLocale = Application::GetSettings().GetUILocale();
1197 while( aLocale.Language.getLength() )
1199 std::hash_map< Locale, LocaleSubst, LocaleHash >::const_iterator lang = m_aSubst.find( aLocale );
1200 if( lang != m_aSubst.end() )
1202 if( ! lang->second.bConfigRead )
1203 readLocaleSubst( aLocale );
1204 // try to find an exact match
1205 // because the list is sorted this will also find fontnames of the form searchfontname*
1206 std::vector< FontNameAttr >::const_iterator it = ::std::lower_bound( lang->second.aSubstAttributes.begin(), lang->second.aSubstAttributes.end(), aSearchAttr, StrictStringSort() );
1207 if( it != lang->second.aSubstAttributes.end() && aSearchFont.CompareTo( it->Name, aSearchFont.Len() ) == COMPARE_EQUAL )
1208 return &(*it);
1210 // gradually become more unspecific
1211 if( aLocale.Variant.getLength() )
1212 aLocale.Variant = OUString();
1213 else if( aLocale.Country.getLength() )
1214 aLocale.Country = OUString();
1215 else if( ! aLocale.Language.equalsAscii( "en" ) )
1216 aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
1217 else
1218 aLocale.Language = OUString();
1220 return NULL;
1224 * SettingsConfigItem::get
1227 SettingsConfigItem* SettingsConfigItem::get()
1229 ImplSVData* pSVData = ImplGetSVData();
1230 if( ! pSVData->mpSettingsConfigItem )
1231 pSVData->mpSettingsConfigItem = new SettingsConfigItem();
1232 return pSVData->mpSettingsConfigItem;
1236 * SettignsConfigItem constructor
1239 SettingsConfigItem::SettingsConfigItem()
1241 ConfigItem( OUString( RTL_CONSTASCII_USTRINGPARAM( SETTINGS_CONFIGNODE ) ),
1242 CONFIG_MODE_DELAYED_UPDATE ),
1243 m_aSettings( 0 )
1245 getValues();
1249 * SettingsConfigItem destructor
1252 SettingsConfigItem::~SettingsConfigItem()
1254 if( IsModified() )
1255 Commit();
1259 * SettingsConfigItem::Commit
1262 void SettingsConfigItem::Commit()
1264 if( ! IsValidConfigMgr() )
1265 return;
1267 std::hash_map< OUString, SmallOUStrMap, rtl::OUStringHash >::const_iterator group;
1269 for( group = m_aSettings.begin(); group != m_aSettings.end(); ++group )
1271 String aKeyName( group->first );
1272 /*sal_Bool bAdded =*/ AddNode( OUString(), aKeyName );
1273 Sequence< PropertyValue > aValues( group->second.size() );
1274 PropertyValue* pValues = aValues.getArray();
1275 int nIndex = 0;
1276 SmallOUStrMap::const_iterator it;
1277 for( it = group->second.begin(); it != group->second.end(); ++it )
1279 String aName( aKeyName );
1280 aName.Append( '/' );
1281 aName.Append( String( it->first ) );
1282 pValues[nIndex].Name = aName;
1283 pValues[nIndex].Handle = 0;
1284 pValues[nIndex].Value <<= it->second;
1285 pValues[nIndex].State = PropertyState_DIRECT_VALUE;
1286 nIndex++;
1288 ReplaceSetProperties( aKeyName, aValues );
1293 * SettingsConfigItem::Notify
1296 void SettingsConfigItem::Notify( const Sequence< OUString >& )
1298 getValues();
1302 * SettingsConfigItem::getValues
1304 void SettingsConfigItem::getValues()
1306 if( ! IsValidConfigMgr() )
1307 return;
1309 m_aSettings.clear();
1311 Sequence< OUString > aNames( GetNodeNames( OUString() ) );
1312 m_aSettings.resize( aNames.getLength() );
1314 for( int j = 0; j < aNames.getLength(); j++ )
1316 #if OSL_DEBUG_LEVEL > 2
1317 fprintf( stderr, "found settings data for \"%s\"\n",
1318 OUStringToOString( aNames.getConstArray()[j], RTL_TEXTENCODING_ASCII_US ).getStr()
1320 #endif
1321 String aKeyName( aNames.getConstArray()[j] );
1322 Sequence< OUString > aKeys( GetNodeNames( aKeyName ) );
1323 Sequence< OUString > aSettingsKeys( aKeys.getLength() );
1324 const OUString* pFrom = aKeys.getConstArray();
1325 OUString* pTo = aSettingsKeys.getArray();
1326 for( int m = 0; m < aKeys.getLength(); m++ )
1328 String aName( aKeyName );
1329 aName.Append( '/' );
1330 aName.Append( String( pFrom[m] ) );
1331 pTo[m] = aName;
1333 Sequence< Any > aValues( GetProperties( aSettingsKeys ) );
1334 const Any* pValue = aValues.getConstArray();
1335 for( int i = 0; i < aValues.getLength(); i++, pValue++ )
1337 if( pValue->getValueTypeClass() == TypeClass_STRING )
1339 const OUString* pLine = (const OUString*)pValue->getValue();
1340 if( pLine->getLength() )
1341 m_aSettings[ aKeyName ][ pFrom[i] ] = *pLine;
1342 #if OSL_DEBUG_LEVEL > 2
1343 fprintf( stderr, " \"%s\"=\"%.30s\"\n",
1344 OUStringToOString( aKeys.getConstArray()[i], RTL_TEXTENCODING_ASCII_US ).getStr(),
1345 OUStringToOString( *pLine, RTL_TEXTENCODING_ASCII_US ).getStr()
1347 #endif
1354 * SettingsConfigItem::getDefaultFont
1357 const OUString& SettingsConfigItem::getValue( const OUString& rGroup, const OUString& rKey ) const
1359 ::std::hash_map< OUString, SmallOUStrMap, rtl::OUStringHash >::const_iterator group = m_aSettings.find( rGroup );
1360 if( group == m_aSettings.end() || group->second.find( rKey ) == group->second.end() )
1362 static OUString aEmpty;
1363 return aEmpty;
1365 return group->second.find(rKey)->second;
1369 * SettingsConfigItem::setDefaultFont
1372 void SettingsConfigItem::setValue( const OUString& rGroup, const OUString& rKey, const OUString& rValue )
1374 bool bModified = m_aSettings[ rGroup ][ rKey ] != rValue;
1375 if( bModified )
1377 m_aSettings[ rGroup ][ rKey ] = rValue;
1378 SetModified();