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