1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #define _CTRLBOX_CXX
28 #include <tools/debug.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/field.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <unotools/charclass.hxx>
33 
34 #include <svtools/svtdata.hxx>
35 #include <svtools/svtools.hrc>
36 #include <svtools/ctrlbox.hxx>
37 #include <svtools/ctrltool.hxx>
38 
39 #include <vcl/i18nhelp.hxx>
40 
41 #define IMGTEXTSPACE    2
42 #define EXTRAFONTSIZE   5
43 
44 static sal_Unicode aImplSymbolFontText[] = {0xF021,0xF032,0xF043,0xF054,0xF065,0xF076,0xF0B7,0xF0C8,0};
45 static sal_Unicode aImplStarSymbolText[] = {0x2706,0x2704,0x270D,0xE033,0x2211,0x2288,0};
46 
47 // ========================================================================
48 // ColorListBox
49 // ========================================================================
50 
51 // --------------------
52 // - ImplColorListData -
53 // --------------------
54 
55 struct ImplColorListData
56 {
57     Color       aColor;
58     sal_Bool        bColor;
59 
ImplColorListDataImplColorListData60                 ImplColorListData() : aColor( COL_BLACK ) { bColor = sal_False; }
ImplColorListDataImplColorListData61                 ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = sal_True; }
62 };
63 
DECLARE_LIST(ImpColorList,ImplColorListData *)64 DECLARE_LIST( ImpColorList, ImplColorListData* )
65 
66 // -----------------------------------------------------------------------
67 
68 void ColorListBox::ImplInit()
69 {
70     pColorList = new ImpColorList( 256, 64 );
71     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
72     aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
73     EnableUserDraw( sal_True );
74     SetUserItemSize( aImageSize );
75 }
76 
77 // -----------------------------------------------------------------------
78 
ImplDestroyColorEntries()79 void ColorListBox::ImplDestroyColorEntries()
80 {
81     for ( sal_uInt16 n = (sal_uInt16) pColorList->Count(); n; )
82     {
83         ImplColorListData* pData = pColorList->GetObject( --n );
84         delete pData;
85     }
86     pColorList->Clear();
87 }
88 
89 // -----------------------------------------------------------------------
90 
ColorListBox(Window * pParent,WinBits nWinStyle)91 ColorListBox::ColorListBox( Window* pParent, WinBits nWinStyle ) :
92     ListBox( pParent, nWinStyle )
93 {
94     ImplInit();
95     SetEdgeBlending(true);
96 }
97 
98 // -----------------------------------------------------------------------
99 
ColorListBox(Window * pParent,const ResId & rResId)100 ColorListBox::ColorListBox( Window* pParent, const ResId& rResId ) :
101     ListBox( pParent, rResId )
102 {
103     ImplInit();
104     SetEdgeBlending(true);
105 }
106 
107 // -----------------------------------------------------------------------
108 
~ColorListBox()109 ColorListBox::~ColorListBox()
110 {
111     ImplDestroyColorEntries();
112     delete pColorList;
113 }
114 
115 // -----------------------------------------------------------------------
116 
InsertEntry(const XubString & rStr,sal_uInt16 nPos)117 sal_uInt16 ColorListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
118 {
119     nPos = ListBox::InsertEntry( rStr, nPos );
120     if ( nPos != LISTBOX_ERROR )
121     {
122         ImplColorListData* pData = new ImplColorListData;
123         pColorList->Insert( pData, nPos );
124     }
125     return nPos;
126 }
127 
128 // -----------------------------------------------------------------------
129 
InsertEntry(const Color & rColor,const XubString & rStr,sal_uInt16 nPos)130 sal_uInt16 ColorListBox::InsertEntry( const Color& rColor, const XubString& rStr,
131                                 sal_uInt16 nPos )
132 {
133     nPos = ListBox::InsertEntry( rStr, nPos );
134     if ( nPos != LISTBOX_ERROR )
135     {
136         ImplColorListData* pData = new ImplColorListData( rColor );
137         pColorList->Insert( pData, nPos );
138     }
139     return nPos;
140 }
141 
142 // -----------------------------------------------------------------------
143 
InsertAutomaticEntry()144 void ColorListBox::InsertAutomaticEntry()
145 {
146     // insert the "Automatic"-entry always on the first position
147     InsertEntry( Color( COL_AUTO ), SvtResId( STR_SVT_AUTOMATIC_COLOR ), 0 );
148 }
149 
150 // -----------------------------------------------------------------------
151 
RemoveEntry(sal_uInt16 nPos)152 void ColorListBox::RemoveEntry( sal_uInt16 nPos )
153 {
154     ListBox::RemoveEntry( nPos );
155     delete pColorList->Remove( nPos );
156 }
157 
158 // -----------------------------------------------------------------------
159 
Clear()160 void ColorListBox::Clear()
161 {
162     ImplDestroyColorEntries();
163     ListBox::Clear();
164 }
165 
166 // -----------------------------------------------------------------------
167 
CopyEntries(const ColorListBox & rBox)168 void ColorListBox::CopyEntries( const ColorListBox& rBox )
169 {
170     // Liste leeren
171     ImplDestroyColorEntries();
172 
173     // Daten kopieren
174     sal_uInt16 nCount = (sal_uInt16) rBox.pColorList->Count();
175     for ( sal_uInt16 n = 0; n < nCount; n++ )
176     {
177         ImplColorListData* pData = rBox.pColorList->GetObject( n );
178         sal_uInt16 nPos = InsertEntry( rBox.GetEntry( n ), LISTBOX_APPEND );
179         if ( nPos != LISTBOX_ERROR )
180             pColorList->Insert( new ImplColorListData( *pData ), nPos );
181     }
182 }
183 
184 // -----------------------------------------------------------------------
185 
GetEntryPos(const Color & rColor) const186 sal_uInt16 ColorListBox::GetEntryPos( const Color& rColor ) const
187 {
188     for( sal_uInt16 n = (sal_uInt16) pColorList->Count(); n; )
189     {
190         ImplColorListData* pData = pColorList->GetObject( --n );
191         if ( pData->bColor && ( pData->aColor == rColor ) )
192             return n;
193     }
194     return LISTBOX_ENTRY_NOTFOUND;
195 }
196 
197 // -----------------------------------------------------------------------
198 
GetEntryColor(sal_uInt16 nPos) const199 Color ColorListBox::GetEntryColor( sal_uInt16 nPos ) const
200 {
201     Color aColor;
202     ImplColorListData* pData = pColorList->GetObject( nPos );
203     if ( pData && pData->bColor )
204         aColor = pData->aColor;
205     return aColor;
206 }
207 
208 // -----------------------------------------------------------------------
209 
UserDraw(const UserDrawEvent & rUDEvt)210 void ColorListBox::UserDraw( const UserDrawEvent& rUDEvt )
211 {
212     ImplColorListData* pData = pColorList->GetObject( rUDEvt.GetItemId() );
213     if ( pData )
214     {
215         if ( pData->bColor )
216         {
217             Point aPos( rUDEvt.GetRect().TopLeft() );
218 
219             aPos.X() += 2;
220             aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;
221 
222             const Rectangle aRect(aPos, aImageSize);
223 
224             rUDEvt.GetDevice()->Push();
225             rUDEvt.GetDevice()->SetFillColor( pData->aColor );
226             rUDEvt.GetDevice()->SetLineColor( rUDEvt.GetDevice()->GetTextColor() );
227             rUDEvt.GetDevice()->DrawRect(aRect);
228             rUDEvt.GetDevice()->Pop();
229 
230             const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
231             const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
232 
233             if(nEdgeBlendingPercent)
234             {
235                 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
236                 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
237                 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
238                 const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));
239 
240                 if(!aBlendFrame.IsEmpty())
241                 {
242                     rUDEvt.GetDevice()->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
243                 }
244             }
245 
246             ListBox::DrawEntry( rUDEvt, sal_False, sal_True, sal_False );
247         }
248         else
249             ListBox::DrawEntry( rUDEvt, sal_False, sal_True, sal_True );
250     }
251     else
252         ListBox::DrawEntry( rUDEvt, sal_True, sal_True, sal_False );
253 }
254 
255 // =======================================================================
256 // LineListBox
257 // =======================================================================
258 
259 // -------------------
260 // - ImpListListData -
261 // -------------------
262 
263 struct ImpLineListData
264 {
265     long    nLine1;
266     long    nLine2;
267     long    nDistance;
268 };
269 
DECLARE_LIST(ImpLineList,ImpLineListData *) const270 DECLARE_LIST( ImpLineList, ImpLineListData* )
271 
272 // -----------------------------------------------------------------------
273 
274 inline const Color& LineListBox::GetPaintColor( void ) const
275 {
276 	return maPaintCol;
277 }
278 
279 // -----------------------------------------------------------------------
280 
ImpGetLine(long nLine1,long nLine2,long nDistance,Bitmap & rBmp,XubString & rStr)281 void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance,
282                             Bitmap& rBmp, XubString& rStr )
283 {
284     Size aSize = GetOutputSizePixel();
285     aSize.Width() -= 20;
286     aSize.Width() -= aTxtSize.Width();
287     aSize.Height() = aTxtSize.Height();
288 
289     // SourceUnit nach Twips
290     if ( eSourceUnit == FUNIT_POINT )
291     {
292         nLine1      *= 20;
293         nLine2      *= 20;
294         nDistance   *= 20;
295     }
296     else if ( eSourceUnit == FUNIT_MM )
297     {
298         nLine1      *= 14440;
299         nLine1      /= 254;
300         nLine2      *= 14440;
301         nLine2      /= 254;
302         nDistance   *= 14440;
303         nDistance   /= 254;
304     }
305 
306     // Linien malen
307     aSize = aVirDev.PixelToLogic( aSize );
308     long nPix = aVirDev.PixelToLogic( Size( 0, 1 ) ).Height();
309     long n1 = nLine1 / 100;
310     long n2 = nLine2 / 100;
311     long nDist  = nDistance / 100;
312     n1 += nPix-1;
313     n1 -= n1%nPix;
314     if ( n2 )
315     {
316         nDist += nPix-1;
317         nDist -= nDist%nPix;
318         n2    += nPix-1;
319         n2    -= n2%nPix;
320     }
321     long nVirHeight = n1+nDist+n2;
322     if ( nVirHeight > aSize.Height() )
323         aSize.Height() = nVirHeight;
324     // negative Breiten muss und darf man nicht painten
325     if ( aSize.Width() > 0 )
326     {
327         Size aVirSize = aVirDev.LogicToPixel( aSize );
328         if ( aVirDev.GetOutputSizePixel() != aVirSize )
329             aVirDev.SetOutputSizePixel( aVirSize );
330         aVirDev.SetFillColor( GetSettings().GetStyleSettings().GetFieldColor() );
331         aVirDev.DrawRect( Rectangle( Point(), aSize ) );
332 
333         aVirDev.SetFillColor( GetPaintColor() );
334         aVirDev.DrawRect( Rectangle( 0, 0, aSize.Width(), n1-nPix ) );
335         if ( n2 )
336         {
337             aVirDev.DrawRect( Rectangle( 0, n1+nDist,
338                                          aSize.Width(), n1+nDist+n2-nPix ) );
339         }
340         rBmp = aVirDev.GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
341     }
342     // Twips nach Unit
343     if ( eUnit == FUNIT_POINT )
344     {
345         nLine1      /= 20;
346         nLine2      /= 20;
347         nDistance   /= 20;
348         rStr.AssignAscii( " pt" );
349     }
350     else if ( eUnit == FUNIT_MM )
351     {
352         nLine1      *= 254;
353         nLine1      /= 14400;
354         nLine2      *= 254;
355         nLine2      /= 14400;
356         nDistance   *= 254;
357         nDistance   /= 14400;
358         rStr.AssignAscii( " mm" );
359     }
360 
361     String aNum( GetSettings().GetLocaleI18nHelper().GetNum( nLine1+nLine2+nDistance, 2 ) );
362     rStr.Insert( aNum, 0 );
363 }
364 
365 // -----------------------------------------------------------------------
366 
ImplInit()367 void LineListBox::ImplInit()
368 {
369     aTxtSize.Width()  = GetTextWidth( XubString( RTL_CONSTASCII_USTRINGPARAM( "99,99 mm" ) ) );
370     aTxtSize.Height() = GetTextHeight();
371     pLineList   = new ImpLineList;
372     eUnit       = FUNIT_POINT;
373     eSourceUnit = FUNIT_POINT;
374 
375     aVirDev.SetLineColor();
376     aVirDev.SetMapMode( MapMode( MAP_TWIP ) );
377 
378 	UpdatePaintLineColor();
379 }
380 
381 // -----------------------------------------------------------------------
382 
LineListBox(Window * pParent,WinBits nWinStyle)383 LineListBox::LineListBox( Window* pParent, WinBits nWinStyle ) :
384     ListBox( pParent, nWinStyle ),
385     aColor( COL_BLACK ),
386 	maPaintCol( COL_BLACK )
387 {
388     ImplInit();
389 }
390 
391 // -----------------------------------------------------------------------
392 
LineListBox(Window * pParent,const ResId & rResId)393 LineListBox::LineListBox( Window* pParent, const ResId& rResId ) :
394     ListBox( pParent, rResId ),
395     aColor( COL_BLACK ),
396 	maPaintCol( COL_BLACK )
397 {
398     ImplInit();
399 }
400 
401 // -----------------------------------------------------------------------
402 
~LineListBox()403 LineListBox::~LineListBox()
404 {
405     sal_uLong n = 0;
406     sal_uLong nCount = pLineList->Count();
407     while ( n < nCount )
408     {
409         ImpLineListData* pData = pLineList->GetObject( n );
410         if ( pData )
411             delete pData;
412         n++;
413     }
414     delete pLineList;
415 }
416 
417 // -----------------------------------------------------------------------
418 
InsertEntry(const XubString & rStr,sal_uInt16 nPos)419 sal_uInt16 LineListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
420 {
421     nPos = ListBox::InsertEntry( rStr, nPos );
422     if ( nPos != LISTBOX_ERROR )
423         pLineList->Insert( NULL, nPos );
424     return nPos;
425 }
426 
427 // -----------------------------------------------------------------------
428 
InsertEntry(long nLine1,long nLine2,long nDistance,sal_uInt16 nPos)429 sal_uInt16 LineListBox::InsertEntry( long nLine1, long nLine2, long nDistance,
430                                 sal_uInt16 nPos )
431 {
432     XubString   aStr;
433     Bitmap      aBmp;
434     ImpGetLine( nLine1, nLine2, nDistance, aBmp, aStr );
435     nPos = ListBox::InsertEntry( aStr, aBmp, nPos );
436     if ( nPos != LISTBOX_ERROR )
437     {
438         ImpLineListData* pData = new ImpLineListData;
439         pData->nLine1    = nLine1;
440         pData->nLine2    = nLine2;
441         pData->nDistance = nDistance;
442         pLineList->Insert( pData, nPos );
443     }
444 
445     return nPos;
446 }
447 
448 // -----------------------------------------------------------------------
449 
RemoveEntry(sal_uInt16 nPos)450 void LineListBox::RemoveEntry( sal_uInt16 nPos )
451 {
452     ListBox::RemoveEntry( nPos );
453     ImpLineListData* pData = pLineList->Remove( nPos );
454     if ( pData )
455         delete pData;
456 }
457 
458 // -----------------------------------------------------------------------
459 
Clear()460 void LineListBox::Clear()
461 {
462     sal_uLong n = 0;
463     sal_uLong nCount = pLineList->Count();
464     while ( n < nCount )
465     {
466         ImpLineListData* pData = pLineList->GetObject( n );
467         if ( pData )
468             delete pData;
469         n++;
470     }
471 
472     pLineList->Clear();
473     ListBox::Clear();
474 }
475 
476 // -----------------------------------------------------------------------
477 
GetEntryPos(long nLine1,long nLine2,long nDistance) const478 sal_uInt16 LineListBox::GetEntryPos( long nLine1, long nLine2,
479                                 long nDistance ) const
480 {
481     sal_uLong n = 0;
482     sal_uLong nCount = pLineList->Count();
483     while ( n < nCount )
484     {
485         ImpLineListData* pData = pLineList->GetObject( n );
486         if ( pData )
487         {
488             if ( (pData->nLine1    == nLine1) &&
489                 (pData->nLine2    == nLine2) &&
490                 (pData->nDistance == nDistance) )
491             return (sal_uInt16)n;
492         }
493 
494         n++;
495     }
496 
497     return LISTBOX_ENTRY_NOTFOUND;
498 }
499 
500 // -----------------------------------------------------------------------
501 
GetEntryLine1(sal_uInt16 nPos) const502 long LineListBox::GetEntryLine1( sal_uInt16 nPos ) const
503 {
504     ImpLineListData* pData = pLineList->GetObject( nPos );
505     if ( pData )
506         return pData->nLine1;
507     else
508         return 0;
509 }
510 
511 // -----------------------------------------------------------------------
512 
GetEntryLine2(sal_uInt16 nPos) const513 long LineListBox::GetEntryLine2( sal_uInt16 nPos ) const
514 {
515     ImpLineListData* pData = pLineList->GetObject( nPos );
516     if ( pData )
517         return pData->nLine2;
518     else
519         return 0;
520 }
521 
522 // -----------------------------------------------------------------------
523 
GetEntryDistance(sal_uInt16 nPos) const524 long LineListBox::GetEntryDistance( sal_uInt16 nPos ) const
525 {
526     ImpLineListData* pData = pLineList->GetObject( nPos );
527     if ( pData )
528         return pData->nDistance;
529     else
530         return 0;
531 }
532 
533 // -----------------------------------------------------------------------
534 
UpdateLineColors(void)535 void LineListBox::UpdateLineColors( void )
536 {
537 	if( UpdatePaintLineColor() )
538 	{
539 		sal_uLong		nCount = pLineList->Count();
540 		if( !nCount )
541 			return;
542 
543 		XubString	aStr;
544 		Bitmap		aBmp;
545 
546 		// exchange entries which containing lines
547 		SetUpdateMode( sal_False );
548 
549 		sal_uInt16		nSelEntry = GetSelectEntryPos();
550 		for( sal_uLong n = 0 ; n < nCount ; ++n )
551 		{
552 			ImpLineListData*	pData = pLineList->GetObject( n );
553 			if( pData )
554 			{
555 				// exchange listbox data
556 				ListBox::RemoveEntry( sal_uInt16( n ) );
557 				ImpGetLine( pData->nLine1, pData->nLine2, pData->nDistance, aBmp, aStr );
558 				ListBox::InsertEntry( aStr, aBmp, sal_uInt16( n ) );
559 			}
560 		}
561 
562 		if( nSelEntry != LISTBOX_ENTRY_NOTFOUND )
563 			SelectEntryPos( nSelEntry );
564 
565 		SetUpdateMode( sal_True );
566 		Invalidate();
567 	}
568 }
569 
570 // -----------------------------------------------------------------------
571 
UpdatePaintLineColor(void)572 sal_Bool LineListBox::UpdatePaintLineColor( void )
573 {
574 	sal_Bool					bRet = sal_True;
575 	const StyleSettings&	rSettings = GetSettings().GetStyleSettings();
576 	Color					aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
577 
578 	bRet = aNewCol != maPaintCol;
579 
580 	if( bRet )
581 		maPaintCol = aNewCol;
582 
583 	return bRet;
584 }
585 
586 // -----------------------------------------------------------------------
587 
DataChanged(const DataChangedEvent & rDCEvt)588 void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
589 {
590 	ListBox::DataChanged( rDCEvt );
591 
592 	if( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
593 		UpdateLineColors();
594 }
595 
596 // ===================================================================
597 // FontNameBox
598 // ===================================================================
599 
600 struct ImplFontNameListData
601 {
602     FontInfo    maInfo;
603     sal_uInt16      mnType;
604 
ImplFontNameListDataImplFontNameListData605                 ImplFontNameListData( const FontInfo& rInfo,
606                                     sal_uInt16 nType ) :
607                     maInfo( rInfo ),
608                     mnType( nType )
609                 {}
610 };
611 
DECLARE_LIST(ImplFontList,ImplFontNameListData *)612 DECLARE_LIST( ImplFontList, ImplFontNameListData* )
613 
614 // -------------------------------------------------------------------
615 
616 FontNameBox::FontNameBox( Window* pParent, WinBits nWinStyle ) :
617     ComboBox( pParent, nWinStyle )
618 {
619     InitBitmaps();
620     mpFontList = NULL;
621     mbWYSIWYG = sal_False;
622     mbSymbols = sal_False;
623 }
624 
625 // -------------------------------------------------------------------
626 
FontNameBox(Window * pParent,const ResId & rResId)627 FontNameBox::FontNameBox( Window* pParent, const ResId& rResId ) :
628     ComboBox( pParent, rResId )
629 {
630     InitBitmaps();
631     mpFontList = NULL;
632     mbWYSIWYG = sal_False;
633     mbSymbols = sal_False;
634 }
635 
636 // -------------------------------------------------------------------
637 
~FontNameBox()638 FontNameBox::~FontNameBox()
639 {
640     ImplDestroyFontList();
641 }
642 
643 // -------------------------------------------------------------------
644 
DataChanged(const DataChangedEvent & rDCEvt)645 void FontNameBox::DataChanged( const DataChangedEvent& rDCEvt )
646 {
647 	ComboBox::DataChanged( rDCEvt );
648 
649 	if( rDCEvt.GetType() == DATACHANGED_SETTINGS && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
650 		InitBitmaps();
651 }
652 
653 // -------------------------------------------------------------------
654 
InitBitmaps(void)655 void FontNameBox::InitBitmaps( void )
656 {
657 	sal_Bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
658 
659 	maImagePrinterFont = Image( SvtResId( bHC? RID_IMG_PRINTERFONT_HC : RID_IMG_PRINTERFONT ) );
660 	maImageBitmapFont = Image( SvtResId( bHC? RID_IMG_BITMAPFONT_HC : RID_IMG_BITMAPFONT ) );
661 	maImageScalableFont = Image( SvtResId( bHC? RID_IMG_SCALABLEFONT_HC : RID_IMG_SCALABLEFONT ) );
662 }
663 
664 // -------------------------------------------------------------------
665 
ImplDestroyFontList()666 void FontNameBox::ImplDestroyFontList()
667 {
668     if ( mpFontList )
669     {
670         ImplFontNameListData* pInfo = mpFontList->First();
671         while ( pInfo )
672         {
673             delete pInfo;
674             pInfo = mpFontList->Next();
675         }
676         delete mpFontList;
677     }
678 }
679 
680 // -------------------------------------------------------------------
681 
Fill(const FontList * pList)682 void FontNameBox::Fill( const FontList* pList )
683 {
684     // store old text and clear box
685     XubString aOldText = GetText();
686     Clear();
687 
688     ImplDestroyFontList();
689     mpFontList = new ImplFontList;
690 
691     // insert fonts
692     sal_uInt16 nFontCount = pList->GetFontNameCount();
693     for ( sal_uInt16 i = 0; i < nFontCount; i++ )
694     {
695         const FontInfo& rFontInfo = pList->GetFontName( i );
696         sal_uLong nIndex = InsertEntry( rFontInfo.GetName() );
697         if ( nIndex != LISTBOX_ERROR )
698         {
699             sal_uInt16 nType = pList->GetFontNameType( i );
700             ImplFontNameListData* pData = new ImplFontNameListData( rFontInfo, nType );
701             mpFontList->Insert( pData, nIndex );
702         }
703     }
704 
705     ImplCalcUserItemSize();
706 
707     // restore text
708     if ( aOldText.Len() )
709         SetText( aOldText );
710 }
711 
712 // -------------------------------------------------------------------
713 
EnableWYSIWYG(sal_Bool bEnable)714 void FontNameBox::EnableWYSIWYG( sal_Bool bEnable )
715 {
716     if ( bEnable != mbWYSIWYG )
717     {
718         mbWYSIWYG = bEnable;
719         EnableUserDraw( mbWYSIWYG | mbSymbols );
720         ImplCalcUserItemSize();
721     }
722 }
723 
724 // -------------------------------------------------------------------
725 
EnableSymbols(sal_Bool bEnable)726 void FontNameBox::EnableSymbols( sal_Bool bEnable )
727 {
728     if ( bEnable != mbSymbols )
729     {
730         mbSymbols = bEnable;
731         EnableUserDraw( mbWYSIWYG | mbSymbols );
732         ImplCalcUserItemSize();
733     }
734 }
735 
736 // -------------------------------------------------------------------
737 
ImplCalcUserItemSize()738 void FontNameBox::ImplCalcUserItemSize()
739 {
740     Size aUserItemSz;
741     if ( mbWYSIWYG && mpFontList )
742     {
743         sal_uInt16 nMaxLen = 0;
744         sal_Bool bSymbolFont = sal_False;
745         sal_Bool bStarSymbol = sal_False;
746         for ( sal_uInt16 n = GetEntryCount(); n; )
747         {
748             ImplFontNameListData* pData = mpFontList->GetObject( --n );
749             XubString aFontName = pData->maInfo.GetName();
750             if ( aFontName.Len() > nMaxLen )
751                 nMaxLen = aFontName.Len();
752             if ( pData->maInfo.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
753                 bSymbolFont = sal_True;
754             // starsymbol is a unicode font, but gets WYSIWIG symbols
755             if( aFontName.EqualsIgnoreCaseAscii( "starsymbol" )
756             ||  aFontName.EqualsIgnoreCaseAscii( "opensymbol" ) )
757                 bSymbolFont = bStarSymbol = sal_True;
758         }
759 
760         // guess maximimum width
761         Size aOneCharSz( GetTextWidth( String( 'X' ) ), GetTextHeight() );
762         Size aSz( aOneCharSz );
763         aSz.Width() *= nMaxLen;
764         // only XX% of width, because ListBox calculates the normal width...
765         aSz.Width() *= 1;
766         aSz.Width() /= 10;
767         if ( bSymbolFont )
768         {
769             int nLength = sizeof(aImplSymbolFontText)/sizeof(aImplSymbolFontText[0]) - 1;
770             int nLength2 = sizeof(aImplStarSymbolText)/sizeof(aImplStarSymbolText[0]) - 1;
771             if( bStarSymbol && (nLength < nLength2) )
772                 nLength = nLength2;
773             aSz.Width() += aOneCharSz.Width() * nLength;
774         }
775         aSz.Height() *= 14;
776         aSz.Height() /= 10;
777         aUserItemSz = aSz;
778     }
779     if ( mbSymbols )
780     {
781         Size aSz = maImageScalableFont.GetSizePixel();
782         aUserItemSz.Width() += aSz.Width() + IMGTEXTSPACE;
783         if ( aSz.Height() > aUserItemSz.Height() )
784             aUserItemSz.Height() = aSz.Height();
785     }
786     SetUserItemSize( aUserItemSz );
787 }
788 
789 // -------------------------------------------------------------------
790 
UserDraw(const UserDrawEvent & rUDEvt)791 void FontNameBox::UserDraw( const UserDrawEvent& rUDEvt )
792 {
793     ImplFontNameListData*   pData = mpFontList->GetObject( rUDEvt.GetItemId() );
794     const FontInfo&         rInfo = pData->maInfo;
795     sal_uInt16                  nType = pData->mnType;
796     Point                   aTopLeft = rUDEvt.GetRect().TopLeft();
797     long                    nX = aTopLeft.X();
798     long                    nH = rUDEvt.GetRect().GetHeight();
799 
800     if ( mbSymbols )
801     {
802         nX += IMGTEXTSPACE;
803         Image* pImg = NULL;
804         if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_PRINTER )
805             pImg = &maImagePrinterFont;
806         else if ( nType & FONTLIST_FONTNAMETYPE_SCALABLE )
807             pImg = &maImageScalableFont;
808         else
809             pImg = &maImageBitmapFont;
810 
811         if ( pImg )
812         {
813             Point aPos( nX, aTopLeft.Y() + (nH-pImg->GetSizePixel().Height())/2 );
814             rUDEvt.GetDevice()->DrawImage( aPos, *pImg );
815         }
816 
817         // X immer um gleiche Breite aendern, auch wenn kein Image ausgegeben.
818         nX += maImagePrinterFont.GetSizePixel().Width();
819     }
820 
821     if ( mbWYSIWYG && mpFontList )
822     {
823         nX += IMGTEXTSPACE;
824 
825         bool bSymbolFont = (rInfo.GetCharSet() == RTL_TEXTENCODING_SYMBOL);
826         // starsymbol is a unicode font, but cannot display its own name
827         const bool bOpenSymbol = rInfo.GetName().EqualsIgnoreCaseAscii( "starsymbol" )
828                               || rInfo.GetName().EqualsIgnoreCaseAscii( "opensymbol" );
829         bSymbolFont |= bOpenSymbol;
830 
831         if( bSymbolFont )
832         {
833             String aText( rInfo.GetName() );
834             aText.AppendAscii( "  " );
835             Point aPos( nX, aTopLeft.Y() + (nH-rUDEvt.GetDevice()->GetTextHeight())/2 );
836             rUDEvt.GetDevice()->DrawText( aPos, aText );
837             nX += rUDEvt.GetDevice()->GetTextWidth( aText );
838         }
839 
840         Color aTextColor = rUDEvt.GetDevice()->GetTextColor();
841         Font aOldFont( rUDEvt.GetDevice()->GetFont() );
842         Size aSize( aOldFont.GetSize() );
843         aSize.Height() += EXTRAFONTSIZE;
844         Font aFont( rInfo );
845         aFont.SetSize( aSize );
846         rUDEvt.GetDevice()->SetFont( aFont );
847         rUDEvt.GetDevice()->SetTextColor( aTextColor );
848 
849         FontCharMap aFontCharMap;
850         bool bHasCharMap = rUDEvt.GetDevice()->GetFontCharMap( aFontCharMap );
851 
852         String aString;
853         if( !bSymbolFont )
854         {
855   	        // preview the font name
856             aString = rInfo.GetName();
857 
858             // reset font if the name cannot be display in the preview font
859             if( STRING_LEN != rUDEvt.GetDevice()->HasGlyphs( aFont, aString ) )
860                 rUDEvt.GetDevice()->SetFont( aOldFont );
861         }
862         else if( bHasCharMap )
863         {
864             // use some sample characters available in the font
865             sal_Unicode aText[8];
866 
867             // start just above the PUA used by most symbol fonts
868             sal_uInt32 cNewChar = 0xFF00;
869 #ifdef QUARTZ
870             // on MacOSX there are too many non-presentable symbols above the codepoint 0x0192
871             if( !bOpenSymbol )
872                 cNewChar = 0x0192;
873 #endif
874             const int nMaxCount = sizeof(aText)/sizeof(*aText) - 1;
875             int nSkip = aFontCharMap.GetCharCount() / nMaxCount;
876             if( nSkip > 10 )
877                 nSkip = 10;
878             else if( nSkip <= 0 )
879                 nSkip = 1;
880             for( int i = 0; i < nMaxCount; ++i )
881             {
882                 sal_uInt32 cOldChar = cNewChar;
883                 for( int j = nSkip; --j >= 0; )
884                     cNewChar = aFontCharMap.GetPrevChar( cNewChar );
885                 if( cOldChar == cNewChar )
886                     break;
887                 aText[ i ] = static_cast<sal_Unicode>(cNewChar); // TODO: support UCS4 samples
888                 aText[ i+1 ] = 0;
889             }
890 
891             aString = String( aText );
892         }
893         else
894         {
895             const sal_Unicode* pText = aImplSymbolFontText;
896             if( bOpenSymbol )
897                 pText = aImplStarSymbolText;
898 
899             aString = String( pText );
900         }
901 
902         long nTextHeight = rUDEvt.GetDevice()->GetTextHeight();
903         Point aPos( nX, aTopLeft.Y() + (nH-nTextHeight)/2 );
904         rUDEvt.GetDevice()->DrawText( aPos, aString );
905 
906         rUDEvt.GetDevice()->SetFont( aOldFont );
907         DrawEntry( rUDEvt, sal_False, sal_False);   // draw seperator
908     }
909     else
910     {
911         DrawEntry( rUDEvt, sal_True, sal_True );
912     }
913 }
914 
915 // ===================================================================
916 // FontStyleBox
917 // ===================================================================
918 
FontStyleBox(Window * pParent,WinBits nWinStyle)919 FontStyleBox::FontStyleBox( Window* pParent, WinBits nWinStyle ) :
920     ComboBox( pParent, nWinStyle )
921 {
922 }
923 
924 // -------------------------------------------------------------------
925 
FontStyleBox(Window * pParent,const ResId & rResId)926 FontStyleBox::FontStyleBox( Window* pParent, const ResId& rResId ) :
927     ComboBox( pParent, rResId )
928 {
929     aLastStyle = GetText();
930 }
931 
932 // -------------------------------------------------------------------
933 
~FontStyleBox()934 FontStyleBox::~FontStyleBox()
935 {
936 }
937 
938 // -------------------------------------------------------------------
939 
Select()940 void FontStyleBox::Select()
941 {
942     // keep text over fill operation
943     aLastStyle = GetText();
944     ComboBox::Select();
945 }
946 
947 // -------------------------------------------------------------------
948 
LoseFocus()949 void FontStyleBox::LoseFocus()
950 {
951     // keep text over fill operation
952     aLastStyle = GetText();
953     ComboBox::LoseFocus();
954 }
955 
956 // -------------------------------------------------------------------
957 
Modify()958 void FontStyleBox::Modify()
959 {
960     CharClass   aChrCls( ::comphelper::getProcessServiceFactory(),
961                         GetSettings().GetLocale() );
962     XubString   aStr = GetText();
963     sal_uInt16      nEntryCount = GetEntryCount();
964 
965     if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
966     {
967         aChrCls.toUpper( aStr );
968         for ( sal_uInt16 i = 0; i < nEntryCount; i++ )
969         {
970             XubString aEntryText = GetEntry( i );
971             aChrCls.toUpper( aEntryText );
972 
973             if ( aStr == aEntryText )
974             {
975                 SetText( GetEntry( i ) );
976                 break;
977             }
978         }
979     }
980 
981     ComboBox::Modify();
982 }
983 
984 // -------------------------------------------------------------------
985 
Fill(const XubString & rName,const FontList * pList)986 void FontStyleBox::Fill( const XubString& rName, const FontList* pList )
987 {
988     // note: this method must call ComboBox::SetText(),
989     //   else aLastStyle will overwritten
990     // store prior selection position and clear box
991     XubString aOldText = GetText();
992     sal_uInt16 nPos = GetEntryPos( aOldText );
993     Clear();
994 
995     // does a font with this name already exist?
996     sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
997     if ( hFontInfo )
998     {
999         XubString   aStyleText;
1000         FontWeight  eLastWeight = WEIGHT_DONTKNOW;
1001         FontItalic  eLastItalic = ITALIC_NONE;
1002         FontWidth   eLastWidth = WIDTH_DONTKNOW;
1003         sal_Bool        bNormal = sal_False;
1004         sal_Bool        bItalic = sal_False;
1005         sal_Bool        bBold = sal_False;
1006         sal_Bool        bBoldItalic = sal_False;
1007         sal_Bool        bInsert = sal_False;
1008         FontInfo    aInfo;
1009         while ( hFontInfo )
1010         {
1011             aInfo = pList->GetFontInfo( hFontInfo );
1012 
1013             FontWeight  eWeight = aInfo.GetWeight();
1014             FontItalic  eItalic = aInfo.GetItalic();
1015             FontWidth   eWidth = aInfo.GetWidthType();
1016             // Only if the attributes are different, we insert the
1017             // Font to avoid double Entries in different languages
1018             if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
1019                  (eWidth != eLastWidth) )
1020             {
1021                 if ( bInsert )
1022                     InsertEntry( aStyleText );
1023 
1024                 if ( eWeight <= WEIGHT_NORMAL )
1025                 {
1026                     if ( eItalic != ITALIC_NONE )
1027                         bItalic = sal_True;
1028                     else
1029                         bNormal = sal_True;
1030                 }
1031                 else
1032                 {
1033                     if ( eItalic != ITALIC_NONE )
1034                         bBoldItalic = sal_True;
1035                     else
1036                         bBold = sal_True;
1037                 }
1038 
1039                 // For wrong StyleNames we replace this with the correct once
1040                 aStyleText = pList->GetStyleName( aInfo );
1041                 bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1042                 if ( !bInsert )
1043                 {
1044                     aStyleText = pList->GetStyleName( eWeight, eItalic );
1045                     bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1046                 }
1047 
1048                 eLastWeight = eWeight;
1049                 eLastItalic = eItalic;
1050                 eLastWidth = eWidth;
1051             }
1052             else
1053             {
1054                 if ( bInsert )
1055                 {
1056                     // If we have two names for the same attributes
1057                     // we prefer the translated standard names
1058                     const XubString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
1059                     if ( rAttrStyleText != aStyleText )
1060                     {
1061                         XubString aTempStyleText = pList->GetStyleName( aInfo );
1062                         if ( rAttrStyleText == aTempStyleText )
1063                             aStyleText = rAttrStyleText;
1064                         bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1065                     }
1066                 }
1067             }
1068 
1069             if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
1070                 bItalic = sal_True;
1071             else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
1072                 bBold = sal_True;
1073             else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
1074                 bBoldItalic = sal_True;
1075 
1076             hFontInfo = pList->GetNextFontInfo( hFontInfo );
1077         }
1078 
1079         if ( bInsert )
1080             InsertEntry( aStyleText );
1081 
1082         // Bestimmte Styles als Nachbildung
1083         if ( bNormal )
1084         {
1085             if ( !bItalic )
1086                 InsertEntry( pList->GetItalicStr() );
1087             if ( !bBold )
1088                 InsertEntry( pList->GetBoldStr() );
1089         }
1090         if ( !bBoldItalic )
1091         {
1092             if ( bNormal || bItalic || bBold )
1093                 InsertEntry( pList->GetBoldItalicStr() );
1094         }
1095         if ( aOldText.Len() )
1096         {
1097             if ( GetEntryPos( aLastStyle ) != LISTBOX_ENTRY_NOTFOUND )
1098                 ComboBox::SetText( aLastStyle );
1099             else
1100             {
1101                 if ( nPos >= GetEntryCount() )
1102                     ComboBox::SetText( GetEntry( 0 ) );
1103                 else
1104                     ComboBox::SetText( GetEntry( nPos ) );
1105             }
1106         }
1107     }
1108     else
1109     {
1110         // Wenn Font nicht, dann Standard-Styles einfuegen
1111         InsertEntry( pList->GetNormalStr() );
1112         InsertEntry( pList->GetItalicStr() );
1113         InsertEntry( pList->GetBoldStr() );
1114         InsertEntry( pList->GetBoldItalicStr() );
1115         if ( aOldText.Len() )
1116         {
1117             if ( nPos > GetEntryCount() )
1118                 ComboBox::SetText( GetEntry( 0 ) );
1119             else
1120                 ComboBox::SetText( GetEntry( nPos ) );
1121         }
1122     }
1123 }
1124 
1125 // ===================================================================
1126 // FontSizeBox
1127 // ===================================================================
1128 
FontSizeBox(Window * pParent,WinBits nWinSize)1129 FontSizeBox::FontSizeBox( Window* pParent, WinBits nWinSize ) :
1130     MetricBox( pParent, nWinSize )
1131 {
1132     ImplInit();
1133 }
1134 
1135 // -----------------------------------------------------------------------
1136 
FontSizeBox(Window * pParent,const ResId & rResId)1137 FontSizeBox::FontSizeBox( Window* pParent, const ResId& rResId ) :
1138     MetricBox( pParent, rResId )
1139 {
1140     ImplInit();
1141 }
1142 
1143 // -----------------------------------------------------------------------
1144 
~FontSizeBox()1145 FontSizeBox::~FontSizeBox()
1146 {
1147 }
1148 
1149 // -----------------------------------------------------------------------
1150 
ImplInit()1151 void FontSizeBox::ImplInit()
1152 {
1153     EnableAutocomplete( sal_False );
1154 
1155     bRelativeMode   = sal_False;
1156     bPtRelative     = sal_False;
1157     bRelative       = sal_False;
1158     bStdSize        = sal_False;
1159     pFontList       = NULL;
1160 
1161     SetShowTrailingZeros( sal_False );
1162     SetDecimalDigits( 1 );
1163     SetMin( 20 );
1164     SetMax( 9999 );
1165     SetProminentEntryType( PROMINENT_MIDDLE );
1166 }
1167 
1168 // -----------------------------------------------------------------------
1169 
Reformat()1170 void FontSizeBox::Reformat()
1171 {
1172     FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
1173     if ( !bRelativeMode || !aFontSizeNames.IsEmpty() )
1174     {
1175         long nNewValue = aFontSizeNames.Name2Size( GetText() );
1176         if ( nNewValue)
1177         {
1178             mnLastValue = nNewValue;
1179             return;
1180         }
1181     }
1182 
1183     MetricBox::Reformat();
1184 }
1185 
1186 // -----------------------------------------------------------------------
1187 
Modify()1188 void FontSizeBox::Modify()
1189 {
1190     MetricBox::Modify();
1191 
1192     if ( bRelativeMode )
1193     {
1194         XubString aStr = GetText();
1195         aStr.EraseLeadingChars();
1196 
1197         sal_Bool bNewMode = bRelative;
1198         sal_Bool bOldPtRelMode = bPtRelative;
1199 
1200         if ( bRelative )
1201         {
1202             bPtRelative = sal_False;
1203             const xub_Unicode* pStr = aStr.GetBuffer();
1204             while ( *pStr )
1205             {
1206                 if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') )
1207                 {
1208                     if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
1209                         bPtRelative = sal_True;
1210                     else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
1211                         ;
1212                     else
1213                     {
1214                         bNewMode = sal_False;
1215                         break;
1216                     }
1217                 }
1218                 pStr++;
1219             }
1220         }
1221         else
1222         {
1223             if ( STRING_NOTFOUND != aStr.Search( '%' ) )
1224             {
1225                 bNewMode = sal_True;
1226                 bPtRelative = sal_False;
1227             }
1228 
1229             if ( '-' == aStr.GetChar( 0 ) || '+' == aStr.GetChar( 0 ) )
1230             {
1231                 bNewMode = sal_True;
1232                 bPtRelative = sal_True;
1233             }
1234         }
1235 
1236         if ( bNewMode != bRelative || bPtRelative != bOldPtRelMode )
1237             SetRelative( bNewMode );
1238     }
1239 }
1240 
1241 // -----------------------------------------------------------------------
1242 
Fill(const FontInfo * pInfo,const FontList * pList)1243 void FontSizeBox::Fill( const FontInfo* pInfo, const FontList* pList )
1244 {
1245     // remember for relative mode
1246     pFontList = pList;
1247 
1248     // no font sizes need to be set for relative mode
1249     if ( bRelative )
1250         return;
1251 
1252     // query font sizes
1253     const long* pTempAry;
1254     const long* pAry = 0;
1255 
1256 	if( pInfo )
1257 	{
1258 		aFontInfo = *pInfo;
1259 		pAry = pList->GetSizeAry( *pInfo );
1260 	}
1261 	else
1262 	{
1263 		pAry = pList->GetStdSizeAry();
1264 	}
1265 
1266     // first insert font size names (for simplified/traditional chinese)
1267     FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
1268     if ( pAry == pList->GetStdSizeAry() )
1269     {
1270         // for standard sizes we don't need to bother
1271         if ( bStdSize && GetEntryCount() && aFontSizeNames.IsEmpty() )
1272             return;
1273         bStdSize = sal_True;
1274     }
1275     else
1276         bStdSize = sal_False;
1277 
1278     Selection aSelection = GetSelection();
1279     XubString aStr = GetText();
1280 
1281     Clear();
1282     sal_uInt16 nPos = 0;
1283 
1284     if ( !aFontSizeNames.IsEmpty() )
1285     {
1286         if ( pAry == pList->GetStdSizeAry() )
1287         {
1288             // for scalable fonts all font size names
1289             sal_uLong nCount = aFontSizeNames.Count();
1290             for( sal_uLong i = 0; i < nCount; i++ )
1291             {
1292                 String  aSizeName = aFontSizeNames.GetIndexName( i );
1293                 long    nSize = aFontSizeNames.GetIndexSize( i );
1294                 ComboBox::InsertEntry( aSizeName, nPos );
1295                 ComboBox::SetEntryData( nPos, (void*)(-nSize) ); // mark as special
1296                 nPos++;
1297             }
1298         }
1299         else
1300         {
1301             // for fixed size fonts only selectable font size names
1302             pTempAry = pAry;
1303             while ( *pTempAry )
1304             {
1305                 String aSizeName = aFontSizeNames.Size2Name( *pTempAry );
1306                 if ( aSizeName.Len() )
1307                 {
1308                     ComboBox::InsertEntry( aSizeName, nPos );
1309                     ComboBox::SetEntryData( nPos, (void*)(-(*pTempAry)) ); // mark as special
1310                     nPos++;
1311                 }
1312                 pTempAry++;
1313             }
1314         }
1315     }
1316 
1317     // then insert numerical font size values
1318     pTempAry = pAry;
1319     while ( *pTempAry )
1320     {
1321         InsertValue( *pTempAry, FUNIT_NONE, nPos );
1322         ComboBox::SetEntryData( nPos, (void*)(*pTempAry) );
1323         nPos++;
1324         pTempAry++;
1325     }
1326 
1327     SetText( aStr );
1328     SetSelection( aSelection );
1329 }
1330 
1331 // -----------------------------------------------------------------------
1332 
EnableRelativeMode(sal_uInt16 nMin,sal_uInt16 nMax,sal_uInt16 nStep)1333 void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax, sal_uInt16 nStep )
1334 {
1335     bRelativeMode = sal_True;
1336     nRelMin       = nMin;
1337     nRelMax       = nMax;
1338     nRelStep      = nStep;
1339     SetUnit( FUNIT_POINT );
1340 }
1341 
1342 // -----------------------------------------------------------------------
1343 
EnablePtRelativeMode(short nMin,short nMax,short nStep)1344 void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
1345 {
1346     bRelativeMode = sal_True;
1347     nPtRelMin     = nMin;
1348     nPtRelMax     = nMax;
1349     nPtRelStep    = nStep;
1350     SetUnit( FUNIT_POINT );
1351 }
1352 
1353 // -----------------------------------------------------------------------
1354 
SetRelative(sal_Bool bNewRelative)1355 void FontSizeBox::SetRelative( sal_Bool bNewRelative )
1356 {
1357     if ( bRelativeMode )
1358     {
1359         Selection aSelection = GetSelection();
1360         XubString  aStr = GetText();
1361         aStr.EraseLeadingChars();
1362 
1363         if ( bNewRelative )
1364         {
1365             bRelative = sal_True;
1366             bStdSize = sal_False;
1367 
1368             if ( bPtRelative )
1369             {
1370                 SetDecimalDigits( 1 );
1371                 SetMin( nPtRelMin );
1372                 SetMax( nPtRelMax );
1373                 SetUnit( FUNIT_POINT );
1374 
1375                 Clear();
1376 
1377                 short i = nPtRelMin, n = 0;
1378                 // JP 30.06.98: more than 100 values are not useful
1379                 while ( i <= nPtRelMax && n++ < 100 )
1380                 {
1381                     InsertValue( i );
1382                     i = i + nPtRelStep;
1383                 }
1384             }
1385             else
1386             {
1387                 SetDecimalDigits( 0 );
1388                 SetMin( nRelMin );
1389                 SetMax( nRelMax );
1390                 SetUnit( FUNIT_PERCENT );
1391 
1392                 Clear();
1393                 sal_uInt16 i = nRelMin;
1394                 while ( i <= nRelMax )
1395                 {
1396                     InsertValue( i );
1397                     i = i + nRelStep;
1398                 }
1399             }
1400         }
1401         else
1402         {
1403             bRelative = bPtRelative = sal_False;
1404             SetDecimalDigits( 1 );
1405             SetMin( 20 );
1406             SetMax( 9999 );
1407             SetUnit( FUNIT_POINT );
1408             if ( pFontList )
1409                 Fill( &aFontInfo, pFontList );
1410         }
1411 
1412         SetText( aStr );
1413         SetSelection( aSelection );
1414     }
1415 }
1416 
1417 // -----------------------------------------------------------------------
1418 
CreateFieldText(sal_Int64 nValue) const1419 XubString FontSizeBox::CreateFieldText( sal_Int64 nValue ) const
1420 {
1421     XubString sRet( MetricBox::CreateFieldText( nValue ) );
1422     if ( bRelativeMode && bPtRelative && (0 <= nValue) && sRet.Len() )
1423         sRet.Insert( '+', 0 );
1424     return sRet;
1425 }
1426 
1427 // -----------------------------------------------------------------------
1428 
SetValue(sal_Int64 nNewValue,FieldUnit eInUnit)1429 void FontSizeBox::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1430 {
1431     if ( !bRelative )
1432     {
1433         sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
1434         FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
1435         // conversion loses precision; however font sizes should
1436         // never have a problem with that
1437         String aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
1438         if ( aName.Len() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
1439         {
1440             mnLastValue = nTempValue;
1441             SetText( aName );
1442             mnFieldValue = mnLastValue;
1443             SetEmptyFieldValueData( sal_False );
1444 			return;
1445         }
1446     }
1447 
1448     MetricBox::SetValue( nNewValue, eInUnit );
1449 }
1450 
1451 // -----------------------------------------------------------------------
1452 
SetValue(sal_Int64 nNewValue)1453 void FontSizeBox::SetValue( sal_Int64 nNewValue )
1454 {
1455     SetValue( nNewValue, FUNIT_NONE );
1456 }
1457 
1458 // -----------------------------------------------------------------------
1459 
GetValue(sal_uInt16 nPos,FieldUnit eOutUnit) const1460 sal_Int64 FontSizeBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
1461 {
1462     if ( !bRelative )
1463     {
1464         sal_Int64 nComboVal = static_cast<sal_Int64>(reinterpret_cast<long>(ComboBox::GetEntryData( nPos )));
1465         if ( nComboVal < 0 )     // marked as special?
1466         {
1467             return MetricField::ConvertValue( -nComboVal, mnBaseValue, GetDecimalDigits(),
1468                                               meUnit, eOutUnit );
1469         }
1470     }
1471 
1472     // do normal font size processing
1473     sal_Int64 nRetValue = MetricBox::GetValue( nPos, eOutUnit );
1474     return nRetValue;
1475 }
1476 
1477 // -----------------------------------------------------------------------
1478 
GetValue(FieldUnit eOutUnit) const1479 sal_Int64 FontSizeBox::GetValue( FieldUnit eOutUnit ) const
1480 {
1481     if ( !bRelative )
1482     {
1483         FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
1484         sal_Int64 nValue = aFontSizeNames.Name2Size( GetText() );
1485         if ( nValue)
1486             return MetricField::ConvertValue( nValue, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit );
1487     }
1488 
1489     return MetricBox::GetValue( eOutUnit );
1490 }
1491 
1492 // -----------------------------------------------------------------------
1493 
GetValue() const1494 sal_Int64 FontSizeBox::GetValue() const
1495 {
1496     // implementation not inline, because it is a virtual function
1497     return GetValue( FUNIT_NONE );
1498 }
1499 
1500 // -----------------------------------------------------------------------
1501 
SetUserValue(sal_Int64 nNewValue,FieldUnit eInUnit)1502 void FontSizeBox::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1503 {
1504     if ( !bRelative )
1505     {
1506         sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
1507         FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
1508         // conversion loses precision
1509         // however font sizes should never have a problem with that
1510         String aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
1511         if ( aName.Len() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
1512         {
1513             mnLastValue = nTempValue;
1514             SetText( aName );
1515             return;
1516         }
1517     }
1518 
1519     MetricBox::SetUserValue( nNewValue, eInUnit );
1520 }
1521 
1522