xref: /trunk/main/svtools/source/control/ctrltool.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #define CTRLTOOL_CXX
32 
33 #include <string.h>
34 
35 #include <tools/debug.hxx>
36 #include <i18npool/mslangid.hxx>
37 #include <vcl/window.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <svtools/svtools.hrc>
41 #include <svtools/svtdata.hxx>
42 #include <svtools/ctrltool.hxx>
43 
44 // =======================================================================
45 
46 // Standard Fontgroessen fuer scalierbare Fonts
47 static long aStdSizeAry[] =
48 {
49      60,
50      70,
51      80,
52      90,
53     100,
54     105,
55     110,
56     120,
57     130,
58     140,
59     150,
60     160,
61     180,
62     200,
63     220,
64     240,
65     260,
66     280,
67     320,
68     360,
69     400,
70     440,
71     480,
72     540,
73     600,
74     660,
75     720,
76     800,
77     880,
78     960,
79     0
80 };
81 
82 // =======================================================================
83 
84 // -----------------------------
85 // - class ImplFontListFonInfo -
86 // -----------------------------
87 
88 class ImplFontListFontInfo : public FontInfo
89 {
90     friend class FontList;
91 
92 private:
93     OutputDevice*           mpDevice;
94     ImplFontListFontInfo*   mpNext;
95 
96 public:
97                             ImplFontListFontInfo( const FontInfo& rInfo,
98                                                   OutputDevice* pDev ) :
99                                 FontInfo( rInfo )
100                             {
101                                 mpDevice = pDev;
102                             }
103 
104     OutputDevice*           GetDevice() const { return mpDevice; }
105 };
106 
107 // ------------------------------
108 // - class ImplFontListNameInfo -
109 // ------------------------------
110 
111 class ImplFontListNameInfo
112 {
113     friend class FontList;
114 
115 private:
116     XubString               maSearchName;
117     ImplFontListFontInfo*   mpFirst;
118     sal_uInt16                  mnType;
119 
120                             ImplFontListNameInfo( const XubString& rSearchName ) :
121                                 maSearchName( rSearchName )
122                             {}
123 
124     const XubString&        GetSearchName() const { return maSearchName; }
125 };
126 
127 // =======================================================================
128 
129 static StringCompare ImplCompareFontInfo( ImplFontListFontInfo* pInfo1,
130                                           ImplFontListFontInfo* pInfo2 )
131 {
132     if ( pInfo1->GetWeight() < pInfo2->GetWeight() )
133         return COMPARE_LESS;
134     else if ( pInfo1->GetWeight() > pInfo2->GetWeight() )
135         return COMPARE_GREATER;
136 
137     if ( pInfo1->GetItalic() < pInfo2->GetItalic() )
138         return COMPARE_LESS;
139     else if ( pInfo1->GetItalic() > pInfo2->GetItalic() )
140         return COMPARE_GREATER;
141 
142     return pInfo1->GetStyleName().CompareTo( pInfo2->GetStyleName() );
143 }
144 
145 // =======================================================================
146 
147 static void ImplMakeSearchString( XubString& rStr )
148 {
149     rStr.ToLowerAscii();
150 }
151 
152 // -----------------------------------------------------------------------
153 
154 static void ImplMakeSearchStringFromName( XubString& rStr )
155 {
156     // check for features before alternate font separator
157     if (rStr.Search(':') < rStr.Search(';'))
158         rStr = rStr.GetToken( 0, ':' );
159     else
160         rStr = rStr.GetToken( 0, ';' );
161     ImplMakeSearchString( rStr );
162 }
163 
164 // -----------------------------------------------------------------------
165 
166 ImplFontListNameInfo* FontList::ImplFind( const XubString& rSearchName, sal_uLong* pIndex ) const
167 {
168     // Wenn kein Eintrag in der Liste oder der Eintrag groesser ist als
169     // der Letzte, dann hinten dranhaengen. Wir vergleichen erst mit dem
170     // letzten Eintrag, da die Liste von VCL auch sortiert zurueckkommt
171     // und somit die Wahrscheinlichkeit das hinten angehaengt werden muss
172     // sehr gross ist.
173     StringCompare eComp;
174     sal_uLong nCnt = Count();
175     if ( !nCnt )
176     {
177         if ( pIndex )
178             *pIndex = LIST_APPEND;
179         return NULL;
180     }
181     else
182     {
183         ImplFontListNameInfo* pCmpData = (ImplFontListNameInfo*)List::GetObject( nCnt-1 );
184         eComp = rSearchName.CompareTo( pCmpData->maSearchName );
185         if ( eComp == COMPARE_GREATER )
186         {
187             if ( pIndex )
188                 *pIndex = LIST_APPEND;
189             return NULL;
190         }
191         else if ( eComp == COMPARE_EQUAL )
192             return pCmpData;
193     }
194 
195     // Fonts in der Liste suchen
196     ImplFontListNameInfo*   pCompareData;
197     ImplFontListNameInfo*   pFoundData = NULL;
198     sal_uLong                   nLow = 0;
199     sal_uLong                   nHigh = nCnt-1;
200     sal_uLong                   nMid;
201 
202     do
203     {
204         nMid = (nLow + nHigh) / 2;
205         pCompareData = (ImplFontListNameInfo*)List::GetObject( nMid );
206         eComp = rSearchName.CompareTo( pCompareData->maSearchName );
207         if ( eComp == COMPARE_LESS )
208         {
209             if ( !nMid )
210                 break;
211             nHigh = nMid-1;
212         }
213         else
214         {
215             if ( eComp == COMPARE_GREATER )
216                 nLow = nMid + 1;
217             else
218             {
219                 pFoundData = pCompareData;
220                 break;
221             }
222         }
223     }
224     while ( nLow <= nHigh );
225 
226     if ( pIndex )
227     {
228         eComp = rSearchName.CompareTo( pCompareData->maSearchName );
229         if ( eComp == COMPARE_GREATER )
230             *pIndex = (nMid+1);
231         else
232             *pIndex = nMid;
233     }
234 
235     return pFoundData;
236 }
237 
238 // -----------------------------------------------------------------------
239 
240 ImplFontListNameInfo* FontList::ImplFindByName( const XubString& rStr ) const
241 {
242     XubString aSearchName = rStr;
243     ImplMakeSearchStringFromName( aSearchName );
244     return ImplFind( aSearchName, NULL );
245 }
246 
247 // -----------------------------------------------------------------------
248 
249 void FontList::ImplInsertFonts( OutputDevice* pDevice, sal_Bool bAll,
250                                 sal_Bool bInsertData )
251 {
252     rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding();
253 
254     sal_uInt16 nType;
255     if ( pDevice->GetOutDevType() != OUTDEV_PRINTER )
256         nType = FONTLIST_FONTNAMETYPE_SCREEN;
257     else
258         nType = FONTLIST_FONTNAMETYPE_PRINTER;
259 
260     // Alle Fonts vom Device abfragen
261     int n = pDevice->GetDevFontCount();
262     sal_uInt16  i;
263     for( i = 0; i < n; i++ )
264     {
265         FontInfo aFontInfo = pDevice->GetDevFont( i );
266 
267         // Wenn keine Raster-Schriften angezeigt werden sollen,
268         // dann diese ignorieren
269         if ( !bAll && (aFontInfo.GetType() == TYPE_RASTER) )
270             continue;
271 
272         XubString               aSearchName = aFontInfo.GetName();
273         ImplFontListNameInfo*   pData;
274         sal_uLong                   nIndex;
275         ImplMakeSearchString( aSearchName );
276         pData = ImplFind( aSearchName, &nIndex );
277 
278         if ( !pData )
279         {
280             if ( bInsertData )
281             {
282                 ImplFontListFontInfo* pNewInfo = new ImplFontListFontInfo( aFontInfo, pDevice );
283                 pData = new ImplFontListNameInfo( aSearchName );
284                 pData->mpFirst      = pNewInfo;
285                 pNewInfo->mpNext    = NULL;
286                 pData->mnType       = 0;
287                 Insert( (void*)pData, nIndex );
288             }
289         }
290         else
291         {
292             if ( bInsertData )
293             {
294                 sal_Bool                    bInsert = sal_True;
295                 ImplFontListFontInfo*   pPrev = NULL;
296                 ImplFontListFontInfo*   pTemp = pData->mpFirst;
297                 ImplFontListFontInfo*   pNewInfo = new ImplFontListFontInfo( aFontInfo, pDevice );
298                 while ( pTemp )
299                 {
300                     StringCompare eComp = ImplCompareFontInfo( pNewInfo, pTemp );
301                     if ( (eComp == COMPARE_LESS) || (eComp == COMPARE_EQUAL) )
302                     {
303                         if ( eComp == COMPARE_EQUAL )
304                         {
305                             // Overwrite charset, because charset should match
306                             // with the system charset
307                             if ( (pTemp->GetCharSet() != eSystemEncoding) &&
308                                  (pNewInfo->GetCharSet() == eSystemEncoding) )
309                             {
310                                 ImplFontListFontInfo* pTemp2 = pTemp->mpNext;
311                                 *((FontInfo*)pTemp) = *((FontInfo*)pNewInfo);
312                                 pTemp->mpNext = pTemp2;
313                             }
314                             delete pNewInfo;
315                             bInsert = sal_False;
316                         }
317 
318                         break;
319                     }
320 
321                     pPrev = pTemp;
322                     pTemp = pTemp->mpNext;
323                 }
324 
325                 if ( bInsert )
326                 {
327                     pNewInfo->mpNext = pTemp;
328                     if ( pPrev )
329                         pPrev->mpNext = pNewInfo;
330                     else
331                         pData->mpFirst = pNewInfo;
332                 }
333             }
334         }
335 
336         if ( pData )
337         {
338             pData->mnType |= nType;
339             if ( aFontInfo.GetType() != TYPE_RASTER )
340                 pData->mnType |= FONTLIST_FONTNAMETYPE_SCALABLE;
341         }
342     }
343 }
344 
345 // =======================================================================
346 
347 FontList::FontList( OutputDevice* pDevice, OutputDevice* pDevice2, sal_Bool bAll ) :
348     List( 4096, sal::static_int_cast< sal_uInt16 >(pDevice->GetDevFontCount()), 32 )
349 {
350     // Variablen initialisieren
351     mpDev = pDevice;
352     mpDev2 = pDevice2;
353     mpSizeAry = NULL;
354 
355     // Stylenamen festlegen
356     maLight         = XubString( SvtResId( STR_SVT_STYLE_LIGHT ) );
357     maLightItalic   = XubString( SvtResId( STR_SVT_STYLE_LIGHT_ITALIC ) );
358     maNormal        = XubString( SvtResId( STR_SVT_STYLE_NORMAL ) );
359     maNormalItalic  = XubString( SvtResId( STR_SVT_STYLE_NORMAL_ITALIC ) );
360     maBold          = XubString( SvtResId( STR_SVT_STYLE_BOLD ) );
361     maBoldItalic    = XubString( SvtResId( STR_SVT_STYLE_BOLD_ITALIC ) );
362     maBlack         = XubString( SvtResId( STR_SVT_STYLE_BLACK ) );
363     maBlackItalic   = XubString( SvtResId( STR_SVT_STYLE_BLACK_ITALIC ) );
364 
365     ImplInsertFonts( pDevice, bAll, sal_True );
366 
367     // Gegebenenfalls muessen wir mit den Bildschirmfonts vergleichen,
368     // damit dort die eigentlich doppelten auf Equal mappen koennen
369     sal_Bool bCompareWindow = sal_False;
370     if ( !pDevice2 && (pDevice->GetOutDevType() == OUTDEV_PRINTER) )
371     {
372         bCompareWindow = sal_True;
373         pDevice2 = Application::GetDefaultDevice();
374     }
375 
376     if ( pDevice2 &&
377          (pDevice2->GetOutDevType() != pDevice->GetOutDevType()) )
378         ImplInsertFonts( pDevice2, bAll, !bCompareWindow );
379 }
380 
381 // -----------------------------------------------------------------------
382 
383 FontList::~FontList()
384 {
385     // Gegebenenfalls SizeArray loeschen
386     if ( mpSizeAry )
387         delete[] mpSizeAry;
388 
389     // FontInfos loeschen
390     ImplFontListNameInfo* pData = (ImplFontListNameInfo*)First();
391     while ( pData )
392     {
393         ImplFontListFontInfo* pTemp;
394         ImplFontListFontInfo* pInfo = pData->mpFirst;
395         while ( pInfo )
396         {
397             pTemp = pInfo->mpNext;
398             delete pInfo;
399             pInfo = pTemp;
400         }
401         ImplFontListNameInfo* pNext = (ImplFontListNameInfo*)Next();
402         delete pData;
403         pData = pNext;
404     }
405 }
406 // -----------------------------------------------------------------------
407 FontList* FontList::Clone() const
408 {
409     FontList* pReturn = new FontList(
410             mpDev, mpDev2, GetFontNameCount() == mpDev->GetDevFontCount());
411     return pReturn;
412 }
413 
414 // -----------------------------------------------------------------------
415 
416 const XubString& FontList::GetStyleName( FontWeight eWeight, FontItalic eItalic ) const
417 {
418     if ( eWeight > WEIGHT_BOLD )
419     {
420         if ( eItalic > ITALIC_NONE )
421             return maBlackItalic;
422         else
423             return maBlack;
424     }
425     else if ( eWeight > WEIGHT_MEDIUM )
426     {
427         if ( eItalic > ITALIC_NONE )
428             return maBoldItalic;
429         else
430             return maBold;
431     }
432     else if ( eWeight > WEIGHT_LIGHT )
433     {
434         if ( eItalic > ITALIC_NONE )
435             return maNormalItalic;
436         else
437             return maNormal;
438     }
439     else if ( eWeight != WEIGHT_DONTKNOW )
440     {
441         if ( eItalic > ITALIC_NONE )
442             return maLightItalic;
443         else
444             return maLight;
445     }
446     else
447     {
448         if ( eItalic > ITALIC_NONE )
449             return maNormalItalic;
450         else
451             return maNormal;
452     }
453 }
454 
455 // -----------------------------------------------------------------------
456 
457 XubString FontList::GetStyleName( const FontInfo& rInfo ) const
458 {
459     XubString   aStyleName = rInfo.GetStyleName();
460     FontWeight  eWeight = rInfo.GetWeight();
461     FontItalic  eItalic = rInfo.GetItalic();
462 
463     // Nur wenn kein StyleName gesetzt ist, geben wir einen syntetischen
464     // Namen zurueck
465     if ( !aStyleName.Len() )
466         aStyleName = GetStyleName( eWeight, eItalic );
467     else
468     {
469         // Translate StyleName to localized name
470         XubString aCompareStyleName = aStyleName;
471         aCompareStyleName.ToLowerAscii();
472         aCompareStyleName.EraseAllChars( ' ' );
473         if ( aCompareStyleName.EqualsAscii( "bold" ) )
474             aStyleName = maBold;
475         else if ( aCompareStyleName.EqualsAscii( "bolditalic" ) )
476             aStyleName = maBoldItalic;
477         else if ( aCompareStyleName.EqualsAscii( "italic" ) )
478             aStyleName = maNormalItalic;
479         else if ( aCompareStyleName.EqualsAscii( "standard" ) )
480             aStyleName = maNormal;
481         else if ( aCompareStyleName.EqualsAscii( "regular" ) )
482             aStyleName = maNormal;
483         else if ( aCompareStyleName.EqualsAscii( "medium" ) )
484             aStyleName = maNormal;
485         else if ( aCompareStyleName.EqualsAscii( "light" ) )
486             aStyleName = maLight;
487         else if ( aCompareStyleName.EqualsAscii( "lightitalic" ) )
488             aStyleName = maLightItalic;
489         else if ( aCompareStyleName.EqualsAscii( "black" ) )
490             aStyleName = maBlack;
491         else if ( aCompareStyleName.EqualsAscii( "blackitalic" ) )
492             aStyleName = maBlackItalic;
493 
494         // fix up StyleName, because the PS Printer driver from
495         // W2000 returns wrong StyleNames (e.g. Bold instead of Bold Italic
496         // for Helvetica)
497         if ( eItalic > ITALIC_NONE )
498         {
499             if ( (aStyleName == maNormal) ||
500                  (aStyleName == maBold) ||
501                  (aStyleName == maLight) ||
502                  (aStyleName == maBlack) )
503                 aStyleName = GetStyleName( eWeight, eItalic );
504         }
505     }
506 
507     return aStyleName;
508 }
509 
510 // -----------------------------------------------------------------------
511 
512 XubString FontList::GetFontMapText( const FontInfo& rInfo ) const
513 {
514     if ( !rInfo.GetName().Len() )
515     {
516         XubString aEmptryStr;
517         return aEmptryStr;
518     }
519 
520     // Search Fontname
521     ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetName() );
522     if ( !pData )
523     {
524         if ( !maMapNotAvailable.Len() )
525             ((FontList*)this)->maMapNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_NOTAVAILABLE ) );
526         return maMapNotAvailable;
527     }
528 
529     // search for synthetic style
530     sal_uInt16              nType       = pData->mnType;
531     const XubString&    rStyleName  = rInfo.GetStyleName();
532     if ( rStyleName.Len() )
533     {
534         sal_Bool                    bNotSynthetic = sal_False;
535         sal_Bool                    bNoneAvailable = sal_False;
536         FontWeight              eWeight = rInfo.GetWeight();
537         FontItalic              eItalic = rInfo.GetItalic();
538         ImplFontListFontInfo*   pFontInfo = pData->mpFirst;
539         while ( pFontInfo )
540         {
541             if ( (eWeight == pFontInfo->GetWeight()) &&
542                  (eItalic == pFontInfo->GetItalic()) )
543             {
544                 bNotSynthetic = sal_True;
545                 break;
546             }
547 
548             pFontInfo = pFontInfo->mpNext;
549         }
550 
551         if ( bNoneAvailable )
552         {
553             XubString aEmptryStr;
554             return aEmptryStr;
555         }
556         else if ( !bNotSynthetic )
557         {
558             if ( !maMapStyleNotAvailable.Len() )
559                 ((FontList*)this)->maMapStyleNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_STYLENOTAVAILABLE ) );
560             return maMapStyleNotAvailable;
561         }
562     }
563 
564     /* Size not available not implemented yet
565     if ( !(nType & FONTLIST_FONTNAMETYPE_SCALABLE) )
566     {
567         ...
568         {
569             if ( !maMapSizeNotAvailable.Len() )
570                  ((FontList*)this)->maMapSizeNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_SIZENOTAVAILABLE ) );
571             return maMapSizeNotAvailable;
572         }
573     }
574     */
575 
576     // Only Printer-Font?
577     if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_PRINTER )
578     {
579         if ( !maMapPrinterOnly.Len() )
580             ((FontList*)this)->maMapPrinterOnly = XubString( SvtResId( STR_SVT_FONTMAP_PRINTERONLY ) );
581         return maMapPrinterOnly;
582     }
583     // Only Screen-Font?
584     else if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_SCREEN
585             && rInfo.GetType() == TYPE_RASTER )
586     {
587         if ( !maMapScreenOnly.Len() )
588             ((FontList*)this)->maMapScreenOnly = XubString( SvtResId( STR_SVT_FONTMAP_SCREENONLY ) );
589         return maMapScreenOnly;
590     }
591     else
592     {
593         if ( !maMapBoth.Len() )
594             ((FontList*)this)->maMapBoth = XubString( SvtResId( STR_SVT_FONTMAP_BOTH ) );
595         return maMapBoth;
596     }
597 }
598 
599 // -----------------------------------------------------------------------
600 
601 sal_uInt16 FontList::GetFontNameType( const XubString& rFontName ) const
602 {
603     ImplFontListNameInfo* pData = ImplFindByName( rFontName );
604     if ( pData )
605         return pData->mnType;
606     else
607         return 0;
608 }
609 
610 // -----------------------------------------------------------------------
611 
612 FontInfo FontList::Get( const XubString& rName, const XubString& rStyleName ) const
613 {
614     ImplFontListNameInfo* pData = ImplFindByName( rName );
615     ImplFontListFontInfo* pFontInfo = NULL;
616     ImplFontListFontInfo* pFontNameInfo = NULL;
617     if ( pData )
618     {
619         ImplFontListFontInfo* pSearchInfo = pData->mpFirst;
620         pFontNameInfo = pSearchInfo;
621         pSearchInfo = pData->mpFirst;
622         while ( pSearchInfo )
623         {
624             if ( rStyleName.EqualsIgnoreCaseAscii( GetStyleName( *pSearchInfo ) ) )
625             {
626                 pFontInfo = pSearchInfo;
627                 break;
628             }
629 
630             pSearchInfo = pSearchInfo->mpNext;
631         }
632     }
633 
634     // Konnten die Daten nicht gefunden werden, dann muessen bestimmte
635     // Attribute nachgebildet werden
636     FontInfo aInfo;
637     if ( !pFontInfo )
638     {
639         if ( pFontNameInfo )
640             aInfo = *pFontNameInfo;
641 
642         if ( rStyleName == maNormal )
643         {
644             aInfo.SetItalic( ITALIC_NONE );
645             aInfo.SetWeight( WEIGHT_NORMAL );
646         }
647         else if ( rStyleName == maNormalItalic )
648         {
649             aInfo.SetItalic( ITALIC_NORMAL );
650             aInfo.SetWeight( WEIGHT_NORMAL );
651         }
652         else if ( rStyleName == maBold )
653         {
654             aInfo.SetItalic( ITALIC_NONE );
655             aInfo.SetWeight( WEIGHT_BOLD );
656         }
657         else if ( rStyleName == maBoldItalic )
658         {
659             aInfo.SetItalic( ITALIC_NORMAL );
660             aInfo.SetWeight( WEIGHT_BOLD );
661         }
662         else if ( rStyleName == maLight )
663         {
664             aInfo.SetItalic( ITALIC_NONE );
665             aInfo.SetWeight( WEIGHT_LIGHT );
666         }
667         else if ( rStyleName == maLightItalic )
668         {
669             aInfo.SetItalic( ITALIC_NORMAL );
670             aInfo.SetWeight( WEIGHT_LIGHT );
671         }
672         else if ( rStyleName == maBlack )
673         {
674             aInfo.SetItalic( ITALIC_NONE );
675             aInfo.SetWeight( WEIGHT_BLACK );
676         }
677         else if ( rStyleName == maBlackItalic )
678         {
679             aInfo.SetItalic( ITALIC_NORMAL );
680             aInfo.SetWeight( WEIGHT_BLACK );
681         }
682         else
683         {
684             aInfo.SetItalic( ITALIC_NONE );
685             aInfo.SetWeight( WEIGHT_DONTKNOW );
686         }
687     }
688     else
689         aInfo = *pFontInfo;
690 
691     // set Fontname to keep FontAlias
692     aInfo.SetName( rName );
693     aInfo.SetStyleName( rStyleName );
694 
695     return aInfo;
696 }
697 
698 // -----------------------------------------------------------------------
699 
700 FontInfo FontList::Get( const XubString& rName,
701                         FontWeight eWeight, FontItalic eItalic ) const
702 {
703     ImplFontListNameInfo* pData = ImplFindByName( rName );
704     ImplFontListFontInfo* pFontInfo = NULL;
705     ImplFontListFontInfo* pFontNameInfo = NULL;
706     if ( pData )
707     {
708         ImplFontListFontInfo* pSearchInfo = pData->mpFirst;
709         pFontNameInfo = pSearchInfo;
710         while ( pSearchInfo )
711         {
712             if ( (eWeight == pSearchInfo->GetWeight()) &&
713                  (eItalic == pSearchInfo->GetItalic()) )
714             {
715                 pFontInfo = pSearchInfo;
716                 break;
717             }
718 
719             pSearchInfo = pSearchInfo->mpNext;
720         }
721     }
722 
723     // Konnten die Daten nicht gefunden werden, dann muessen bestimmte
724     // Attribute nachgebildet werden
725     FontInfo aInfo;
726     if ( !pFontInfo )
727     {
728         // Falls der Fontname stimmt, uebernehmen wir soviel wie moeglich
729         if ( pFontNameInfo )
730         {
731             aInfo = *pFontNameInfo;
732             aInfo.SetStyleName( XubString() );
733         }
734 
735         aInfo.SetWeight( eWeight );
736         aInfo.SetItalic( eItalic );
737     }
738     else
739         aInfo = *pFontInfo;
740 
741     // set Fontname to keep FontAlias
742     aInfo.SetName( rName );
743 
744     return aInfo;
745 }
746 
747 // -----------------------------------------------------------------------
748 
749 sal_Bool FontList::IsAvailable( const XubString& rName ) const
750 {
751     return (ImplFindByName( rName ) != 0);
752 }
753 
754 // -----------------------------------------------------------------------
755 
756 const FontInfo& FontList::GetFontName( sal_uInt16 nFont ) const
757 {
758     DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontName(): nFont >= Count" );
759 
760     ImplFontListNameInfo* pData = (ImplFontListNameInfo*)List::GetObject( nFont );
761     return *(pData->mpFirst);
762 }
763 
764 // -----------------------------------------------------------------------
765 
766 sal_uInt16 FontList::GetFontNameType( sal_uInt16 nFont ) const
767 {
768     DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontNameType(): nFont >= Count" );
769 
770     ImplFontListNameInfo* pData = (ImplFontListNameInfo*)List::GetObject( nFont );
771     return pData->mnType;
772 }
773 
774 // -----------------------------------------------------------------------
775 
776 sal_Handle FontList::GetFirstFontInfo( const XubString& rName ) const
777 {
778     ImplFontListNameInfo* pData = ImplFindByName( rName );
779     if ( !pData )
780         return (sal_Handle)NULL;
781     else
782         return (sal_Handle)pData->mpFirst;
783 }
784 
785 // -----------------------------------------------------------------------
786 
787 sal_Handle FontList::GetNextFontInfo( sal_Handle hFontInfo ) const
788 {
789     ImplFontListFontInfo* pInfo = (ImplFontListFontInfo*)(void*)hFontInfo;
790     return (sal_Handle)(pInfo->mpNext);
791 }
792 
793 // -----------------------------------------------------------------------
794 
795 const FontInfo& FontList::GetFontInfo( sal_Handle hFontInfo ) const
796 {
797     ImplFontListFontInfo* pInfo = (ImplFontListFontInfo*)(void*)hFontInfo;
798     return *pInfo;
799 }
800 
801 // -----------------------------------------------------------------------
802 
803 const long* FontList::GetSizeAry( const FontInfo& rInfo ) const
804 {
805     // Size-Array vorher loeschen
806     if ( mpSizeAry )
807     {
808         delete[] ((FontList*)this)->mpSizeAry;
809         ((FontList*)this)->mpSizeAry = NULL;
810     }
811 
812     // Falls kein Name, dann Standardgroessen
813     if ( !rInfo.GetName().Len() )
814         return aStdSizeAry;
815 
816     // Zuerst nach dem Fontnamen suchen um das Device dann von dem
817     // entsprechenden Font zu nehmen
818     OutputDevice*           pDevice = mpDev;
819     ImplFontListNameInfo*   pData = ImplFindByName( rInfo.GetName() );
820     if ( pData )
821         pDevice = pData->mpFirst->GetDevice();
822 
823     int nDevSizeCount = pDevice->GetDevFontSizeCount( rInfo );
824     if ( !nDevSizeCount ||
825          (pDevice->GetDevFontSize( rInfo, 0 ).Height() == 0) )
826         return aStdSizeAry;
827 
828     MapMode aOldMapMode = pDevice->GetMapMode();
829     MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
830     pDevice->SetMapMode( aMap );
831 
832     sal_uInt16  i;
833     sal_uInt16  nRealCount = 0;
834     long    nOldHeight = 0;
835     ((FontList*)this)->mpSizeAry = new long[nDevSizeCount+1];
836     for ( i = 0; i < nDevSizeCount; i++ )
837     {
838         Size aSize = pDevice->GetDevFontSize( rInfo, i );
839         if ( aSize.Height() != nOldHeight )
840         {
841             nOldHeight = aSize.Height();
842             ((FontList*)this)->mpSizeAry[nRealCount] = nOldHeight;
843             nRealCount++;
844         }
845     }
846     ((FontList*)this)->mpSizeAry[nRealCount] = 0;
847 
848     pDevice->SetMapMode( aOldMapMode );
849     return mpSizeAry;
850 }
851 
852 // -----------------------------------------------------------------------
853 
854 const long* FontList::GetStdSizeAry()
855 {
856     return aStdSizeAry;
857 }
858 
859 // =======================================================================
860 
861 // ---------------------------------
862 // - FontSizeNames & FsizeNameItem -
863 // ---------------------------------
864 
865 struct ImplFSNameItem
866 {
867     long        mnSize;
868     const char* mszUtf8Name;
869 };
870 
871 //------------------------------------------------------------------------
872 
873 static ImplFSNameItem aImplSimplifiedChinese[] =
874 {
875     {  50, "\xe5\x85\xab\xe5\x8f\xb7" },
876     {  55, "\xe4\xb8\x83\xe5\x8f\xb7" },
877     {  65, "\xe5\xb0\x8f\xe5\x85\xad" },
878     {  75, "\xe5\x85\xad\xe5\x8f\xb7" },
879     {  90, "\xe5\xb0\x8f\xe4\xba\x94" },
880     { 105, "\xe4\xba\x94\xe5\x8f\xb7" },
881     { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" },
882     { 140, "\xe5\x9b\x9b\xe5\x8f\xb7" },
883     { 150, "\xe5\xb0\x8f\xe4\xb8\x89" },
884     { 160, "\xe4\xb8\x89\xe5\x8f\xb7" },
885     { 180, "\xe5\xb0\x8f\xe4\xba\x8c" },
886     { 220, "\xe4\xba\x8c\xe5\x8f\xb7" },
887     { 240, "\xe5\xb0\x8f\xe4\xb8\x80" },
888     { 260, "\xe4\xb8\x80\xe5\x8f\xb7" },
889     { 360, "\xe5\xb0\x8f\xe5\x88\x9d" },
890     { 420, "\xe5\x88\x9d\xe5\x8f\xb7" }
891 };
892 
893 // -----------------------------------------------------------------------
894 
895 #if 0 // #i89077# disabled by popular request
896 static ImplFSNameItem aImplTraditionalChinese[] =
897 {
898     {  50, "\xe5\x85\xab\xe8\x99\x9f" },
899     {  55, "\xe4\xb8\x83\xe8\x99\x9f" },
900     {  65, "\xe5\xb0\x8f\xe5\x85\xad" },
901     {  75, "\xe5\x85\xad\xe8\x99\x9f" },
902     {  90, "\xe5\xb0\x8f\xe4\xba\x94" },
903     { 105, "\xe4\xba\x94\xe8\x99\x9f" },
904     { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" },
905     { 140, "\xe5\x9b\x9b\xe8\x99\x9f" },
906     { 150, "\xe5\xb0\x8f\xe4\xb8\x89" },
907     { 160, "\xe4\xb8\x89\xe8\x99\x9f" },
908     { 180, "\xe5\xb0\x8f\xe4\xba\x8c" },
909     { 220, "\xe4\xba\x8c\xe8\x99\x9f" },
910     { 240, "\xe5\xb0\x8f\xe4\xb8\x80" },
911     { 260, "\xe4\xb8\x80\xe8\x99\x9f" },
912     { 360, "\xe5\xb0\x8f\xe5\x88\x9d" },
913     { 420, "\xe5\x88\x9d\xe8\x99\x9f" }
914 };
915 #endif
916 
917 //------------------------------------------------------------------------
918 
919 FontSizeNames::FontSizeNames( LanguageType eLanguage )
920 {
921     if ( eLanguage == LANGUAGE_DONTKNOW )
922         eLanguage = Application::GetSettings().GetUILanguage();
923     if ( eLanguage == LANGUAGE_SYSTEM )
924         eLanguage = MsLangId::getSystemUILanguage();
925 
926     switch( eLanguage )
927     {
928         case LANGUAGE_CHINESE:
929         case LANGUAGE_CHINESE_SIMPLIFIED:
930             mpArray = aImplSimplifiedChinese;
931             mnElem = sizeof(aImplSimplifiedChinese) / sizeof(aImplSimplifiedChinese[0]);
932             break;
933 
934 #if 0 // #i89077# disabled by popular request
935         case LANGUAGE_CHINESE_HONGKONG:
936         case LANGUAGE_CHINESE_SINGAPORE:
937         case LANGUAGE_CHINESE_MACAU:
938         case LANGUAGE_CHINESE_TRADITIONAL:
939             mpArray = aImplTraditionalChinese;
940             mnElem = sizeof(aImplTraditionalChinese) / sizeof(aImplTraditionalChinese[0]);
941             break;
942 #endif
943 
944         default:
945             mpArray = NULL;
946             mnElem = 0;
947             break;
948     };
949 }
950 
951 //------------------------------------------------------------------------
952 
953 long FontSizeNames::Name2Size( const String& rName ) const
954 {
955     if ( mnElem )
956     {
957         ByteString aName( rName, RTL_TEXTENCODING_UTF8 );
958 
959         // linear search is sufficient for this rare case
960         for( long i = mnElem; --i >= 0; )
961             if ( aName == mpArray[i].mszUtf8Name )
962                 return mpArray[i].mnSize;
963     }
964 
965     return 0;
966 }
967 
968 //------------------------------------------------------------------------
969 
970 String FontSizeNames::Size2Name( long nValue ) const
971 {
972     String aStr;
973 
974     // binary search
975     for( long lower = 0, upper = mnElem - 1; lower <= upper; )
976     {
977         long mid = (upper + lower) >> 1;
978         if ( nValue == mpArray[mid].mnSize )
979         {
980             aStr = String( mpArray[mid].mszUtf8Name, RTL_TEXTENCODING_UTF8 );
981             break;
982         }
983         else if ( nValue < mpArray[mid].mnSize )
984             upper = mid - 1;
985         else /* ( nValue > mpArray[mid].mnSize ) */
986             lower = mid + 1;
987     }
988 
989     return aStr;
990 }
991 
992 //------------------------------------------------------------------------
993 
994 String FontSizeNames::GetIndexName( sal_uLong nIndex ) const
995 {
996     String aStr;
997 
998     if ( nIndex < mnElem )
999         aStr = String( mpArray[nIndex].mszUtf8Name, RTL_TEXTENCODING_UTF8 );
1000 
1001     return aStr;
1002 }
1003 
1004 //------------------------------------------------------------------------
1005 
1006 long FontSizeNames::GetIndexSize( sal_uLong nIndex ) const
1007 {
1008     if ( nIndex >= mnElem )
1009         return 0;
1010     return mpArray[nIndex].mnSize;
1011 }
1012