LCOV - code coverage report
Current view: top level - svtools/source/control - ctrlbox.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 314 987 31.8 %
Date: 2015-06-13 12:38:46 Functions: 42 100 42.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_folders.h>
      21             : 
      22             : #include <i18nutil/unicode.hxx>
      23             : #include <tools/stream.hxx>
      24             : #include <vcl/builderfactory.hxx>
      25             : #include <vcl/svapp.hxx>
      26             : #include <vcl/field.hxx>
      27             : #include <vcl/helper.hxx>
      28             : #include <vcl/settings.hxx>
      29             : #include <sal/macros.h>
      30             : #include <comphelper/processfactory.hxx>
      31             : #include <comphelper/string.hxx>
      32             : #include <unotools/charclass.hxx>
      33             : 
      34             : #include <svtools/sampletext.hxx>
      35             : #include <svtools/svtresid.hxx>
      36             : #include <svtools/svtools.hrc>
      37             : #include <svtools/ctrlbox.hxx>
      38             : #include <svtools/ctrltool.hxx>
      39             : #include <svtools/borderhelper.hxx>
      40             : 
      41             : #include <vcl/i18nhelp.hxx>
      42             : #include <vcl/fontcapabilities.hxx>
      43             : #include <basegfx/polygon/b2dpolygon.hxx>
      44             : #include <basegfx/polygon/b2dpolygontools.hxx>
      45             : 
      46             : #include <com/sun/star/table/BorderLineStyle.hpp>
      47             : 
      48             : #include <rtl/bootstrap.hxx>
      49             : 
      50             : #include <stdio.h>
      51             : 
      52             : #define IMGOUTERTEXTSPACE 5
      53             : #define EXTRAFONTSIZE 5
      54             : #define GAPTOEXTRAPREVIEW 10
      55             : #define MAXPREVIEWWIDTH 120
      56             : #define MINGAPWIDTH 2
      57             : 
      58             : #define FONTNAMEBOXMRUENTRIESFILE "/user/config/fontnameboxmruentries"
      59             : 
      60             : using namespace ::com::sun::star;
      61             : 
      62             : class ImplColorListData
      63             : {
      64             : public:
      65             :     Color       aColor;
      66             :     bool        bColor;
      67             : 
      68           0 :                 ImplColorListData() : aColor( COL_BLACK ) { bColor = false; }
      69           0 :                 explicit ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = true; }
      70             : };
      71             : 
      72          51 : void ColorListBox::ImplInit()
      73             : {
      74          51 :     pColorList = new ImpColorList();
      75             : 
      76          51 :     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
      77          51 :     aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
      78          51 :     EnableUserDraw( true );
      79          51 :     SetUserItemSize( aImageSize );
      80          51 : }
      81             : 
      82          51 : void ColorListBox::ImplDestroyColorEntries()
      83             : {
      84         102 :     for ( size_t n = pColorList->size(); n; )
      85           0 :         delete (*pColorList)[ --n ];
      86          51 :     pColorList->clear();
      87          51 : }
      88             : 
      89          51 : ColorListBox::ColorListBox( vcl::Window* pParent, WinBits nWinStyle ) :
      90          51 :     ListBox( pParent, nWinStyle )
      91             : {
      92          51 :     ImplInit();
      93          51 :     SetEdgeBlending(true);
      94          51 : }
      95             : 
      96           0 : ColorListBox::ColorListBox( vcl::Window* pParent, const ResId& rResId ) :
      97           0 :     ListBox( pParent, rResId )
      98             : {
      99           0 :     ImplInit();
     100           0 :     SetEdgeBlending(true);
     101           0 : }
     102             : 
     103           0 : VCL_BUILDER_DECL_FACTORY(ColorListBox)
     104             : {
     105           0 :     bool bDropdown = VclBuilder::extractDropdown(rMap);
     106           0 :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
     107           0 :     if (bDropdown)
     108           0 :         nWinBits |= WB_DROPDOWN;
     109           0 :     VclPtrInstance<ColorListBox> pListBox(pParent, nWinBits);
     110           0 :     if (bDropdown)
     111           0 :         pListBox->EnableAutoSize(true);
     112           0 :     rRet = pListBox;
     113           0 : }
     114             : 
     115         102 : ColorListBox::~ColorListBox()
     116             : {
     117          51 :     disposeOnce();
     118          51 : }
     119             : 
     120          51 : void ColorListBox::dispose()
     121             : {
     122          51 :     if ( pColorList )
     123             :     {
     124          51 :         ImplDestroyColorEntries();
     125          51 :         delete pColorList;
     126          51 :         pColorList = NULL;
     127             :     }
     128          51 :     ListBox::dispose();
     129          51 : }
     130             : 
     131           0 : sal_Int32 ColorListBox::InsertEntry( const OUString& rStr, sal_Int32 nPos )
     132             : {
     133           0 :     nPos = ListBox::InsertEntry( rStr, nPos );
     134           0 :     if ( nPos != LISTBOX_ERROR )
     135             :     {
     136           0 :         ImplColorListData* pData = new ImplColorListData;
     137           0 :         if ( static_cast<size_t>(nPos) < pColorList->size() )
     138             :         {
     139           0 :             ImpColorList::iterator it = pColorList->begin();
     140           0 :             ::std::advance( it, nPos );
     141           0 :             pColorList->insert( it, pData );
     142             :         }
     143             :         else
     144             :         {
     145           0 :             pColorList->push_back( pData );
     146           0 :             nPos = pColorList->size() - 1;
     147             :         }
     148             :     }
     149           0 :     return nPos;
     150             : }
     151             : 
     152           0 : sal_Int32 ColorListBox::InsertEntry( const Color& rColor, const OUString& rStr,
     153             :                                 sal_Int32 nPos )
     154             : {
     155           0 :     nPos = ListBox::InsertEntry( rStr, nPos );
     156           0 :     if ( nPos != LISTBOX_ERROR )
     157             :     {
     158           0 :         ImplColorListData* pData = new ImplColorListData( rColor );
     159           0 :         if ( static_cast<size_t>(nPos) < pColorList->size() )
     160             :         {
     161           0 :             ImpColorList::iterator it = pColorList->begin();
     162           0 :             ::std::advance( it, nPos );
     163           0 :             pColorList->insert( it, pData );
     164             :         }
     165             :         else
     166             :         {
     167           0 :             pColorList->push_back( pData );
     168           0 :             nPos = pColorList->size() - 1;
     169             :         }
     170             :     }
     171           0 :     return nPos;
     172             : }
     173             : 
     174           0 : void ColorListBox::InsertAutomaticEntryColor(const Color &rColor)
     175             : {
     176             :     // insert the "Automatic"-entry always on the first position
     177           0 :     InsertEntry( rColor, SVT_RESSTR(STR_SVT_AUTOMATIC_COLOR), 0 );
     178           0 : }
     179             : 
     180           0 : void ColorListBox::RemoveEntry( sal_Int32 nPos )
     181             : {
     182           0 :     ListBox::RemoveEntry( nPos );
     183           0 :     if ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() )
     184             :     {
     185           0 :             ImpColorList::iterator it = pColorList->begin();
     186           0 :             ::std::advance( it, nPos );
     187           0 :             delete *it;
     188           0 :             pColorList->erase( it );
     189             :     }
     190           0 : }
     191             : 
     192           0 : void ColorListBox::Clear()
     193             : {
     194           0 :     ImplDestroyColorEntries();
     195           0 :     ListBox::Clear();
     196           0 : }
     197             : 
     198           0 : void ColorListBox::CopyEntries( const ColorListBox& rBox )
     199             : {
     200             :     // Liste leeren
     201           0 :     ImplDestroyColorEntries();
     202             : 
     203             :     // Daten kopieren
     204           0 :     size_t nCount = rBox.pColorList->size();
     205           0 :     for ( size_t n = 0; n < nCount; n++ )
     206             :     {
     207           0 :         ImplColorListData* pData = (*rBox.pColorList)[ n ];
     208           0 :         sal_Int32 nPos = InsertEntry( rBox.GetEntry( n ), LISTBOX_APPEND );
     209           0 :         if ( nPos != LISTBOX_ERROR )
     210             :         {
     211           0 :             if ( static_cast<size_t>(nPos) < pColorList->size() )
     212             :             {
     213           0 :                 ImpColorList::iterator it = pColorList->begin();
     214           0 :                 ::std::advance( it, nPos );
     215           0 :                 pColorList->insert( it, new ImplColorListData( *pData ) );
     216             :             }
     217             :             else
     218             :             {
     219           0 :                 pColorList->push_back( new ImplColorListData( *pData ) );
     220             :             }
     221             :         }
     222             :     }
     223           0 : }
     224             : 
     225           0 : sal_Int32 ColorListBox::GetEntryPos( const Color& rColor ) const
     226             : {
     227           0 :     for( sal_Int32 n = (sal_Int32) pColorList->size(); n; )
     228             :     {
     229           0 :         ImplColorListData* pData = (*pColorList)[ --n ];
     230           0 :         if ( pData->bColor && ( pData->aColor == rColor ) )
     231           0 :             return n;
     232             :     }
     233           0 :     return LISTBOX_ENTRY_NOTFOUND;
     234             : }
     235             : 
     236           0 : Color ColorListBox::GetEntryColor( sal_Int32 nPos ) const
     237             : {
     238           0 :     Color aColor;
     239           0 :     ImplColorListData* pData = ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() ) ?
     240           0 :         (*pColorList)[ nPos ] : NULL;
     241           0 :     if ( pData && pData->bColor )
     242           0 :         aColor = pData->aColor;
     243           0 :     return aColor;
     244             : }
     245             : 
     246           1 : void ColorListBox::UserDraw( const UserDrawEvent& rUDEvt )
     247             : {
     248           1 :     size_t nPos = rUDEvt.GetItemId();
     249           1 :     ImplColorListData* pData = ( nPos < pColorList->size() ) ? (*pColorList)[ nPos ] : NULL;
     250           1 :     if ( pData )
     251             :     {
     252           0 :         if ( pData->bColor )
     253             :         {
     254           0 :             Point aPos( rUDEvt.GetRect().TopLeft() );
     255             : 
     256           0 :             aPos.X() += 2;
     257           0 :             aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;
     258             : 
     259           0 :             const Rectangle aRect(aPos, aImageSize);
     260             : 
     261           0 :             rUDEvt.GetDevice()->Push();
     262           0 :             rUDEvt.GetDevice()->SetFillColor( pData->aColor );
     263           0 :             rUDEvt.GetDevice()->SetLineColor( rUDEvt.GetDevice()->GetTextColor() );
     264           0 :             rUDEvt.GetDevice()->DrawRect(aRect);
     265           0 :             rUDEvt.GetDevice()->Pop();
     266             : 
     267           0 :             const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
     268           0 :             const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
     269             : 
     270           0 :             if(nEdgeBlendingPercent)
     271             :             {
     272           0 :                 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
     273           0 :                 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
     274           0 :                 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
     275           0 :                 const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));
     276             : 
     277           0 :                 if(!aBlendFrame.IsEmpty())
     278             :                 {
     279           0 :                     rUDEvt.GetDevice()->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
     280           0 :                 }
     281             :             }
     282             : 
     283           0 :             ListBox::DrawEntry( rUDEvt, false, true, false );
     284             :         }
     285             :         else
     286           0 :             ListBox::DrawEntry( rUDEvt, false, true, true );
     287             :     }
     288             :     else
     289           1 :         ListBox::DrawEntry( rUDEvt, true, true, false );
     290           1 : }
     291             : 
     292      529500 : BorderWidthImpl::BorderWidthImpl( BorderWidthImplFlags nFlags, double nRate1, double nRate2, double nRateGap ):
     293             :     m_nFlags( nFlags ),
     294             :     m_nRate1( nRate1 ),
     295             :     m_nRate2( nRate2 ),
     296      529500 :     m_nRateGap( nRateGap )
     297             : {
     298      529500 : }
     299             : 
     300      469422 : BorderWidthImpl& BorderWidthImpl::operator= ( const BorderWidthImpl& r )
     301             : {
     302      469422 :     m_nFlags = r.m_nFlags;
     303      469422 :     m_nRate1 = r.m_nRate1;
     304      469422 :     m_nRate2 = r.m_nRate2;
     305      469422 :     m_nRateGap = r.m_nRateGap;
     306      469422 :     return *this;
     307             : }
     308             : 
     309      199528 : bool BorderWidthImpl::operator== ( const BorderWidthImpl& r ) const
     310             : {
     311      398932 :     return ( m_nFlags == r.m_nFlags ) &&
     312      398769 :            ( m_nRate1 == r.m_nRate1 ) &&
     313      598222 :            ( m_nRate2 == r.m_nRate2 ) &&
     314      398857 :            ( m_nRateGap == r.m_nRateGap );
     315             : }
     316             : 
     317     1266685 : long BorderWidthImpl::GetLine1( long nWidth ) const
     318             : {
     319     1266685 :     long result = static_cast<long>(m_nRate1);
     320     1266685 :     if ( m_nFlags & BorderWidthImplFlags::CHANGE_LINE1 )
     321             :     {
     322     1263959 :         long const nConstant2 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE2) ? 0 : m_nRate2;
     323     1263959 :         long const nConstantD = (m_nFlags & BorderWidthImplFlags::CHANGE_DIST ) ? 0 : m_nRateGap;
     324             :         result = std::max<long>(0,
     325     1263959 :                     static_cast<long>((m_nRate1 * nWidth) + 0.5)
     326     1263959 :                         - (nConstant2 + nConstantD));
     327     1263959 :         if (result == 0 && m_nRate1 > 0.0 && nWidth > 0)
     328             :         {   // fdo#51777: hack to essentially treat 1 twip DOUBLE border
     329           8 :             result = 1;  // as 1 twip SINGLE border
     330             :         }
     331             :     }
     332     1266685 :     return result;
     333             : }
     334             : 
     335     1213054 : long BorderWidthImpl::GetLine2( long nWidth ) const
     336             : {
     337     1213054 :     long result = static_cast<long>(m_nRate2);
     338     1213054 :     if ( m_nFlags & BorderWidthImplFlags::CHANGE_LINE2)
     339             :     {
     340        1366 :         long const nConstant1 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE1) ? 0 : m_nRate1;
     341        1366 :         long const nConstantD = (m_nFlags & BorderWidthImplFlags::CHANGE_DIST ) ? 0 : m_nRateGap;
     342             :         result = std::max<long>(0,
     343        1366 :                     static_cast<long>((m_nRate2 * nWidth) + 0.5)
     344        1366 :                         - (nConstant1 + nConstantD));
     345             :     }
     346     1213054 :     return result;
     347             : }
     348             : 
     349     1094392 : long BorderWidthImpl::GetGap( long nWidth ) const
     350             : {
     351     1094392 :     long result = static_cast<long>(m_nRateGap);
     352     1094392 :     if ( m_nFlags & BorderWidthImplFlags::CHANGE_DIST )
     353             :     {
     354        3222 :         long const nConstant1 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE1) ? 0 : m_nRate1;
     355        3222 :         long const nConstant2 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE2) ? 0 : m_nRate2;
     356             :         result = std::max<long>(0,
     357        3222 :                     static_cast<long>((m_nRateGap * nWidth) + 0.5)
     358        3222 :                         - (nConstant1 + nConstant2));
     359             :     }
     360             : 
     361             :     // Avoid having too small distances (less than 0.1pt)
     362     1094392 :     if ( result < MINGAPWIDTH && m_nRate1 > 0 && m_nRate2 > 0 )
     363          16 :         result = MINGAPWIDTH;
     364             : 
     365     1094392 :     return result;
     366             : }
     367             : 
     368       57642 : static double lcl_getGuessedWidth( long nTested, double nRate, bool nChanging )
     369             : {
     370       57642 :     double nWidth = -1.0;
     371       57642 :     if ( nChanging )
     372       20022 :         nWidth = double( nTested ) / nRate;
     373             :     else
     374             :     {
     375       37620 :         if ( double( nTested ) == nRate )
     376       36322 :             nWidth = nRate;
     377             :     }
     378             : 
     379       57642 :     return nWidth;
     380             : }
     381             : 
     382       19214 : long BorderWidthImpl::GuessWidth( long nLine1, long nLine2, long nGap )
     383             : {
     384       19214 :     std::vector< double > aToCompare;
     385       19214 :     bool bInvalid = false;
     386             : 
     387       19214 :     bool bLine1Change = bool( m_nFlags & BorderWidthImplFlags::CHANGE_LINE1 );
     388       19214 :     double nWidth1 = lcl_getGuessedWidth( nLine1, m_nRate1, bLine1Change );
     389       19214 :     if ( bLine1Change )
     390       18735 :         aToCompare.push_back( nWidth1 );
     391         479 :     else if ( !bLine1Change && nWidth1 < 0 )
     392         462 :         bInvalid = true;
     393             : 
     394       19214 :     bool bLine2Change = bool( m_nFlags & BorderWidthImplFlags::CHANGE_LINE2 );
     395       19214 :     double nWidth2 = lcl_getGuessedWidth( nLine2, m_nRate2, bLine2Change );
     396       19214 :     if ( bLine2Change )
     397         523 :         aToCompare.push_back( nWidth2 );
     398       18691 :     else if ( !bLine2Change && nWidth2 < 0 )
     399         547 :         bInvalid = true;
     400             : 
     401       19214 :     bool bGapChange = bool( m_nFlags & BorderWidthImplFlags::CHANGE_DIST );
     402       19214 :     double nWidthGap = lcl_getGuessedWidth( nGap, m_nRateGap, bGapChange );
     403       19214 :     if ( bGapChange && nGap > MINGAPWIDTH )
     404         758 :         aToCompare.push_back( nWidthGap );
     405       18456 :     else if ( !bGapChange && nWidthGap < 0 )
     406         289 :         bInvalid = true;
     407             : 
     408             :     // non-constant line width factors must sum to 1
     409             :     assert((((bLine1Change) ? m_nRate1 : 0) +
     410             :             ((bLine2Change) ? m_nRate2 : 0) +
     411             :             ((bGapChange) ? m_nRateGap : 0)) - 1.0 < 0.00001 );
     412             : 
     413       19214 :     double nWidth = 0.0;
     414       19214 :     if ( (!bInvalid) && (!aToCompare.empty()) )
     415             :     {
     416       18557 :         nWidth = *aToCompare.begin();
     417       18557 :         std::vector< double >::iterator pIt = aToCompare.begin();
     418       56163 :         while ( pIt != aToCompare.end() && !bInvalid )
     419             :         {
     420       19049 :             bInvalid = ( nWidth != *pIt );
     421       19049 :             ++pIt;
     422             :         }
     423       18557 :         nWidth = (bInvalid) ?  0.0 : nLine1 + nLine2 + nGap;
     424             :     }
     425             : 
     426       19214 :     return nWidth;
     427             : }
     428             : 
     429             : /** Utility class storing the border line width, style and colors. The widths
     430             :     are defined in Twips.
     431             :   */
     432             : class ImpLineListData
     433             : {
     434             : private:
     435             :     BorderWidthImpl m_aWidthImpl;
     436             : 
     437             :     Color  ( *m_pColor1Fn )( Color );
     438             :     Color  ( *m_pColor2Fn )( Color );
     439             :     Color  ( *m_pColorDistFn )( Color, Color );
     440             : 
     441             :     long   m_nMinWidth;
     442             :     sal_uInt16 m_nStyle;
     443             : 
     444             : public:
     445             :     ImpLineListData( BorderWidthImpl aWidthImpl, sal_uInt16 nStyle,
     446             :             long nMinWidth=0, Color ( *pColor1Fn ) ( Color ) = &sameColor,
     447             :             Color ( *pColor2Fn ) ( Color ) = &sameColor, Color ( *pColorDistFn ) ( Color, Color ) = &sameDistColor );
     448             : 
     449             :     /** Returns the computed width of the line 1 in twips. */
     450           0 :     long GetLine1ForWidth( long nWidth ) { return m_aWidthImpl.GetLine1( nWidth ); }
     451             : 
     452             :     /** Returns the computed width of the line 2 in twips. */
     453           0 :     long GetLine2ForWidth( long nWidth ) { return m_aWidthImpl.GetLine2( nWidth ); }
     454             : 
     455             :     /** Returns the computed width of the gap in twips. */
     456           0 :     long GetDistForWidth( long nWidth ) { return m_aWidthImpl.GetGap( nWidth ); }
     457             : 
     458             :     Color  GetColorLine1( const Color& aMain );
     459             :     Color  GetColorLine2( const Color& aMain );
     460             :     Color  GetColorDist( const Color& aMain, const Color& rDefault );
     461             : 
     462             :     /** Returns the minimum width in twips */
     463           0 :     long   GetMinWidth( ) { return m_nMinWidth;}
     464           0 :     sal_uInt16 GetStyle( ) { return m_nStyle;}
     465             : };
     466             : 
     467           0 : ImpLineListData::ImpLineListData( BorderWidthImpl aWidthImpl,
     468             :        sal_uInt16 nStyle, long nMinWidth, Color ( *pColor1Fn )( Color ),
     469             :        Color ( *pColor2Fn )( Color ), Color ( *pColorDistFn )( Color, Color ) ) :
     470             :     m_aWidthImpl( aWidthImpl ),
     471             :     m_pColor1Fn( pColor1Fn ),
     472             :     m_pColor2Fn( pColor2Fn ),
     473             :     m_pColorDistFn( pColorDistFn ),
     474             :     m_nMinWidth( nMinWidth ),
     475           0 :     m_nStyle( nStyle )
     476             : {
     477           0 : }
     478             : 
     479             : 
     480           0 : Color ImpLineListData::GetColorLine1( const Color& rMain )
     481             : {
     482           0 :     return ( *m_pColor1Fn )( rMain );
     483             : }
     484             : 
     485           0 : Color ImpLineListData::GetColorLine2( const Color& rMain )
     486             : {
     487           0 :     return ( *m_pColor2Fn )( rMain );
     488             : }
     489             : 
     490           0 : Color ImpLineListData::GetColorDist( const Color& rMain, const Color& rDefault )
     491             : {
     492           0 :     return ( *m_pColorDistFn )( rMain, rDefault );
     493             : }
     494             : 
     495           0 : sal_uInt16 LineListBox::GetSelectEntryStyle( sal_Int32 nSelIndex ) const
     496             : {
     497           0 :     sal_uInt16 nStyle = table::BorderLineStyle::SOLID;
     498           0 :     sal_Int32 nPos = GetSelectEntryPos( nSelIndex );
     499           0 :     if ( nPos != LISTBOX_ENTRY_NOTFOUND )
     500             :     {
     501           0 :         if (!m_sNone.isEmpty())
     502           0 :             nPos--;
     503           0 :         nStyle = GetEntryStyle( nPos );
     504             :     }
     505             : 
     506           0 :     return nStyle;
     507             : }
     508             : 
     509             : 
     510           2 : void lclDrawPolygon( OutputDevice& rDev, const basegfx::B2DPolygon& rPolygon, long nWidth, sal_uInt16 nDashing )
     511             : {
     512           2 :     AntialiasingFlags nOldAA = rDev.GetAntialiasing();
     513           2 :     rDev.SetAntialiasing( nOldAA & ~AntialiasingFlags::EnableB2dDraw );
     514             : 
     515           2 :     long nPix = rDev.PixelToLogic(Size(1, 1)).Width();
     516           2 :     basegfx::B2DPolyPolygon aPolygons = svtools::ApplyLineDashing(rPolygon, nDashing, nPix);
     517             : 
     518             :     // Handle problems of width 1px in Pixel mode: 0.5px gives a 1px line
     519           2 :     if (rDev.GetMapMode().GetMapUnit() == MAP_PIXEL && nWidth == nPix)
     520           0 :         nWidth = 0;
     521             : 
     522           4 :     for ( sal_uInt32 i = 0; i < aPolygons.count( ); i++ )
     523             :     {
     524           2 :         basegfx::B2DPolygon aDash = aPolygons.getB2DPolygon( i );
     525           4 :         basegfx::B2DPoint aStart = aDash.getB2DPoint( 0 );
     526           4 :         basegfx::B2DPoint aEnd = aDash.getB2DPoint( aDash.count() - 1 );
     527             : 
     528           4 :         basegfx::B2DVector aVector( aEnd - aStart );
     529           2 :         aVector.normalize( );
     530           4 :         const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));
     531             : 
     532           4 :         const basegfx::B2DVector aWidthOffset( double( nWidth ) / 2 * aPerpendicular);
     533           4 :         basegfx::B2DPolygon aDashPolygon;
     534           2 :         aDashPolygon.append( aStart + aWidthOffset );
     535           2 :         aDashPolygon.append( aEnd + aWidthOffset );
     536           2 :         aDashPolygon.append( aEnd - aWidthOffset );
     537           2 :         aDashPolygon.append( aStart - aWidthOffset );
     538           2 :         aDashPolygon.setClosed( true );
     539             : 
     540           2 :         rDev.DrawPolygon( aDashPolygon );
     541           2 :     }
     542             : 
     543           2 :     rDev.SetAntialiasing( nOldAA );
     544           2 : }
     545             : 
     546             : namespace svtools {
     547             : 
     548             : /**
     549             :  * Dashing array must start with a line width and end with a blank width.
     550             :  */
     551         132 : std::vector<double> GetDashing( sal_uInt16 nDashing )
     552             : {
     553         132 :     std::vector<double> aPattern;
     554         132 :     switch (nDashing)
     555             :     {
     556             :         case table::BorderLineStyle::DOTTED:
     557          61 :             aPattern.push_back( 1.0 ); // line
     558          61 :             aPattern.push_back( 2.0 ); // blank
     559          61 :         break;
     560             :         case table::BorderLineStyle::DASHED:
     561          21 :             aPattern.push_back( 16.0 ); // line
     562          21 :             aPattern.push_back( 5.0 );  // blank
     563          21 :         break;
     564             :         case table::BorderLineStyle::FINE_DASHED:
     565          20 :             aPattern.push_back( 6.0 ); // line
     566          20 :             aPattern.push_back( 2.0 ); // blank
     567          20 :         break;
     568             :         case table::BorderLineStyle::DASH_DOT:
     569           0 :             aPattern.push_back( 16.0 ); // line
     570           0 :             aPattern.push_back( 5.0 );  // blank
     571           0 :             aPattern.push_back( 5.0 );  // line
     572           0 :             aPattern.push_back( 5.0 );  // blank
     573           0 :         break;
     574             :         case table::BorderLineStyle::DASH_DOT_DOT:
     575           0 :             aPattern.push_back( 16.0 ); // line
     576           0 :             aPattern.push_back( 5.0 );  // blank
     577           0 :             aPattern.push_back( 5.0 );  // line
     578           0 :             aPattern.push_back( 5.0 );  // blank
     579           0 :             aPattern.push_back( 5.0 );  // line
     580           0 :             aPattern.push_back( 5.0 );  // blank
     581           0 :         break;
     582             :         default:
     583             :             ;
     584             :     }
     585             : 
     586         132 :     return aPattern;
     587             : }
     588             : 
     589             : namespace {
     590             : 
     591             : class ApplyScale : std::unary_function<double, void>
     592             : {
     593             :     double mfScale;
     594             : public:
     595         132 :     explicit ApplyScale( double fScale ) : mfScale(fScale) {}
     596         204 :     void operator() ( double& rVal )
     597             :     {
     598         204 :         rVal *= mfScale;
     599         204 :     }
     600             : };
     601             : 
     602             : }
     603             : 
     604          97 : std::vector<double> GetLineDashing( sal_uInt16 nDashing, double fScale )
     605             : {
     606          97 :     std::vector<double> aPattern = GetDashing(nDashing);
     607          97 :     std::for_each(aPattern.begin(), aPattern.end(), ApplyScale(fScale));
     608          97 :     return aPattern;
     609             : }
     610             : 
     611          35 : basegfx::B2DPolyPolygon ApplyLineDashing( const basegfx::B2DPolygon& rPolygon, sal_uInt16 nDashing, double fScale )
     612             : {
     613          35 :     std::vector<double> aPattern = GetDashing(nDashing);
     614          35 :     std::for_each(aPattern.begin(), aPattern.end(), ApplyScale(fScale));
     615             : 
     616          35 :     basegfx::B2DPolyPolygon aPolygons;
     617             : 
     618          35 :     if (aPattern.empty())
     619          30 :         aPolygons.append(rPolygon);
     620             :     else
     621           5 :         basegfx::tools::applyLineDashing(rPolygon, aPattern, &aPolygons);
     622             : 
     623          35 :     return aPolygons;
     624             : }
     625             : 
     626           2 : void DrawLine( OutputDevice& rDev, const Point& rP1, const Point& rP2,
     627             :     sal_uInt32 nWidth, sal_uInt16 nDashing )
     628             : {
     629           4 :     DrawLine( rDev, basegfx::B2DPoint( rP1.X(), rP1.Y() ),
     630           6 :             basegfx::B2DPoint( rP2.X(), rP2.Y( ) ), nWidth, nDashing );
     631           2 : }
     632             : 
     633           2 : void DrawLine( OutputDevice& rDev, const basegfx::B2DPoint& rP1, const basegfx::B2DPoint& rP2,
     634             :     sal_uInt32 nWidth, sal_uInt16 nDashing )
     635             : {
     636           2 :     basegfx::B2DPolygon aPolygon;
     637           2 :     aPolygon.append( rP1 );
     638           2 :     aPolygon.append( rP2 );
     639           2 :     lclDrawPolygon( rDev, aPolygon, nWidth, nDashing );
     640           2 : }
     641             : 
     642             : }
     643             : 
     644           0 : void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance,
     645             :                             Color aColor1, Color aColor2, Color aColorDist,
     646             :                             sal_uInt16 nStyle, Bitmap& rBmp )
     647             : {
     648             :     //TODO, rather than including the " " text to force
     649             :     //the line height, better would be do drop
     650             :     //this calculation and draw a bitmap of height
     651             :     //equal to normal text line and center the
     652             :     //line within that
     653           0 :     long nMinWidth = GetTextWidth(OUString("----------"));
     654           0 :     Size aSize = CalcSubEditSize();
     655           0 :     aSize.Width() = std::max(nMinWidth, aSize.Width());
     656           0 :     aSize.Width() -= aTxtSize.Width();
     657           0 :     aSize.Width() -= 6;
     658           0 :     aSize.Height() = aTxtSize.Height();
     659             : 
     660             :     // SourceUnit nach Twips
     661           0 :     if ( eSourceUnit == FUNIT_POINT )
     662             :     {
     663           0 :         nLine1      /= 5;
     664           0 :         nLine2      /= 5;
     665           0 :         nDistance   /= 5;
     666             :     }
     667             : 
     668             :     // Linien malen
     669           0 :     aSize = aVirDev->PixelToLogic( aSize );
     670           0 :     long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height();
     671           0 :     sal_uInt32 n1 = nLine1;
     672           0 :     sal_uInt32 n2 = nLine2;
     673           0 :     long nDist  = nDistance;
     674           0 :     n1 += nPix-1;
     675           0 :     n1 -= n1%nPix;
     676           0 :     if ( n2 )
     677             :     {
     678           0 :         nDist += nPix-1;
     679           0 :         nDist -= nDist%nPix;
     680           0 :         n2    += nPix-1;
     681           0 :         n2    -= n2%nPix;
     682             :     }
     683           0 :     long nVirHeight = n1+nDist+n2;
     684           0 :     if ( nVirHeight > aSize.Height() )
     685           0 :         aSize.Height() = nVirHeight;
     686             :     // negative width should not be drawn
     687           0 :     if ( aSize.Width() > 0 )
     688             :     {
     689           0 :         Size aVirSize = aVirDev->LogicToPixel( aSize );
     690           0 :         if ( aVirDev->GetOutputSizePixel() != aVirSize )
     691           0 :             aVirDev->SetOutputSizePixel( aVirSize );
     692           0 :         aVirDev->SetFillColor( aColorDist );
     693           0 :         aVirDev->DrawRect( Rectangle( Point(), aSize ) );
     694             : 
     695           0 :         aVirDev->SetFillColor( aColor1 );
     696             : 
     697           0 :         double y1 = double( n1 ) / 2;
     698           0 :         svtools::DrawLine( *aVirDev.get(), basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle );
     699             : 
     700           0 :         if ( n2 )
     701             :         {
     702           0 :             double y2 =  n1 + nDist + double( n2 ) / 2;
     703           0 :             aVirDev->SetFillColor( aColor2 );
     704           0 :             svtools::DrawLine( *aVirDev.get(), basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, table::BorderLineStyle::SOLID );
     705             :         }
     706           0 :         rBmp = aVirDev->GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
     707             :     }
     708           0 : }
     709             : 
     710           0 : void LineListBox::ImplInit()
     711             : {
     712           0 :     aTxtSize.Width()  = GetTextWidth( OUString( " " ) );
     713           0 :     aTxtSize.Height() = GetTextHeight();
     714           0 :     pLineList   = new ImpLineList();
     715           0 :     eUnit       = FUNIT_POINT;
     716           0 :     eSourceUnit = FUNIT_POINT;
     717             : 
     718           0 :     aVirDev->SetLineColor();
     719           0 :     aVirDev->SetMapMode( MapMode( MAP_TWIP ) );
     720             : 
     721           0 :     UpdatePaintLineColor();
     722           0 : }
     723             : 
     724           0 : LineListBox::LineListBox( vcl::Window* pParent, WinBits nWinStyle ) :
     725             :     ListBox( pParent, nWinStyle ),
     726             :     m_nWidth( 5 ),
     727             :     m_sNone( ),
     728             :     aVirDev( VclPtr<VirtualDevice>::Create() ),
     729             :     aColor( COL_BLACK ),
     730           0 :     maPaintCol( COL_BLACK )
     731             : {
     732           0 :     ImplInit();
     733           0 : }
     734             : 
     735           0 : VCL_BUILDER_DECL_FACTORY(LineListBox)
     736             : {
     737           0 :     bool bDropdown = VclBuilder::extractDropdown(rMap);
     738           0 :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
     739           0 :     if (bDropdown)
     740           0 :         nWinBits |= WB_DROPDOWN;
     741           0 :     VclPtrInstance<LineListBox> pListBox(pParent, nWinBits);
     742           0 :     if (bDropdown)
     743           0 :         pListBox->EnableAutoSize(true);
     744           0 :     rRet = pListBox;
     745           0 : }
     746             : 
     747           0 : LineListBox::~LineListBox()
     748             : {
     749           0 :     disposeOnce();
     750           0 : }
     751             : 
     752           0 : void LineListBox::dispose()
     753             : {
     754           0 :     for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
     755           0 :         if ( (*pLineList)[ i ] ) {
     756           0 :             delete (*pLineList)[ i ];
     757             :         }
     758             :     }
     759           0 :     pLineList->clear();
     760           0 :     delete pLineList;
     761           0 :     ListBox::dispose();
     762           0 : }
     763             : 
     764           0 : sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, long nWidth )
     765             : {
     766           0 :     sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
     767           0 :     if (!m_sNone.isEmpty())
     768           0 :         nListPos--;
     769             : 
     770           0 :     sal_Int32 n = 0;
     771           0 :     size_t i = 0;
     772           0 :     size_t nCount = pLineList->size();
     773           0 :     while ( nPos == LISTBOX_ENTRY_NOTFOUND && i < nCount )
     774             :     {
     775           0 :         ImpLineListData* pData = (*pLineList)[ i ];
     776           0 :         if ( pData && pData->GetMinWidth() <= nWidth )
     777             :         {
     778           0 :             if ( nListPos == n )
     779           0 :                 nPos = static_cast<sal_Int32>(i);
     780           0 :             n++;
     781             :         }
     782           0 :         i++;
     783             :     }
     784             : 
     785           0 :     return nPos;
     786             : }
     787             : 
     788           0 : void LineListBox::SelectEntry( sal_uInt16 nStyle, bool bSelect )
     789             : {
     790           0 :     sal_Int32 nPos = GetEntryPos( nStyle );
     791           0 :     if ( nPos != LISTBOX_ENTRY_NOTFOUND )
     792           0 :         ListBox::SelectEntryPos( nPos, bSelect );
     793           0 : }
     794             : 
     795           0 : void LineListBox::InsertEntry(
     796             :     const BorderWidthImpl& rWidthImpl, sal_uInt16 nStyle, long nMinWidth,
     797             :     ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn )
     798             : {
     799             :     ImpLineListData* pData = new ImpLineListData(
     800           0 :         rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn);
     801           0 :     pLineList->push_back( pData );
     802           0 : }
     803             : 
     804           0 : sal_Int32 LineListBox::GetEntryPos( sal_uInt16 nStyle ) const
     805             : {
     806           0 :     for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
     807           0 :         ImpLineListData* pData = (*pLineList)[ i ];
     808           0 :         if ( pData )
     809             :         {
     810           0 :             if ( GetEntryStyle( i ) == nStyle )
     811             :             {
     812           0 :                 size_t nPos = i;
     813           0 :                 if (!m_sNone.isEmpty())
     814           0 :                     nPos ++;
     815           0 :                 return (sal_Int32)nPos;
     816             :             }
     817             :         }
     818             :     }
     819           0 :     return LISTBOX_ENTRY_NOTFOUND;
     820             : }
     821             : 
     822           0 : sal_uInt16 LineListBox::GetEntryStyle( sal_Int32 nPos ) const
     823             : {
     824           0 :     ImpLineListData* pData = (0 <= nPos && static_cast<size_t>(nPos) < pLineList->size()) ? (*pLineList)[ nPos ] : NULL;
     825           0 :     return ( pData ) ? pData->GetStyle() : table::BorderLineStyle::NONE;
     826             : }
     827             : 
     828           0 : bool LineListBox::UpdatePaintLineColor()
     829             : {
     830           0 :     const StyleSettings&    rSettings = GetSettings().GetStyleSettings();
     831           0 :     Color                   aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
     832             : 
     833           0 :     bool bRet = aNewCol != maPaintCol;
     834             : 
     835           0 :     if( bRet )
     836           0 :         maPaintCol = aNewCol;
     837             : 
     838           0 :     return bRet;
     839             : }
     840             : 
     841           0 : void LineListBox::UpdateEntries( long nOldWidth )
     842             : {
     843           0 :     SetUpdateMode( false );
     844             : 
     845           0 :     UpdatePaintLineColor( );
     846             : 
     847           0 :     sal_Int32      nSelEntry = GetSelectEntryPos();
     848           0 :     sal_Int32       nTypePos = GetStylePos( nSelEntry, nOldWidth );
     849             : 
     850             :     // Remove the old entries
     851           0 :     while ( GetEntryCount( ) > 0 )
     852           0 :         ListBox::RemoveEntry( 0 );
     853             : 
     854             :     // Add the new entries based on the defined width
     855           0 :     if (!m_sNone.isEmpty())
     856           0 :         ListBox::InsertEntry( m_sNone, LISTBOX_APPEND );
     857             : 
     858           0 :     sal_uInt16 n = 0;
     859           0 :     sal_uInt16 nCount = pLineList->size( );
     860           0 :     while ( n < nCount )
     861             :     {
     862           0 :         ImpLineListData* pData = (*pLineList)[ n ];
     863           0 :         if ( pData && pData->GetMinWidth() <= m_nWidth )
     864             :         {
     865           0 :             Bitmap      aBmp;
     866             :             ImpGetLine( pData->GetLine1ForWidth( m_nWidth ),
     867             :                     pData->GetLine2ForWidth( m_nWidth ),
     868             :                     pData->GetDistForWidth( m_nWidth ),
     869             :                     GetColorLine1( GetEntryCount( ) ),
     870             :                     GetColorLine2( GetEntryCount( ) ),
     871             :                     GetColorDist( GetEntryCount( ) ),
     872           0 :                     pData->GetStyle(), aBmp );
     873           0 :             ListBox::InsertEntry(OUString(" "), Image(aBmp), LISTBOX_APPEND);
     874           0 :             if ( n == nTypePos )
     875           0 :                 SelectEntryPos( GetEntryCount() - 1 );
     876             :         }
     877           0 :         else if ( n == nTypePos )
     878           0 :             SetNoSelection();
     879           0 :         n++;
     880             :     }
     881             : 
     882           0 :     SetUpdateMode( true );
     883           0 :     Invalidate();
     884           0 : }
     885             : 
     886           0 : Color LineListBox::GetColorLine1( sal_Int32 nPos )
     887             : {
     888           0 :     Color rResult = GetPaintColor( );
     889             : 
     890           0 :     sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
     891           0 :     ImpLineListData* pData = (*pLineList)[ nStyle ];
     892           0 :     if ( pData )
     893           0 :         rResult = pData->GetColorLine1( GetColor( ) );
     894             : 
     895           0 :     return rResult;
     896             : }
     897             : 
     898           0 : Color LineListBox::GetColorLine2( sal_Int32 nPos )
     899             : {
     900           0 :     Color rResult = GetPaintColor( );
     901             : 
     902           0 :     sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
     903           0 :     ImpLineListData* pData = (*pLineList)[ nStyle ];
     904           0 :     if ( pData )
     905           0 :         rResult = pData->GetColorLine2( GetColor( ) );
     906             : 
     907           0 :     return rResult;
     908             : }
     909             : 
     910           0 : Color LineListBox::GetColorDist( sal_Int32 nPos )
     911             : {
     912           0 :     Color rResult = GetSettings().GetStyleSettings().GetFieldColor();
     913             : 
     914           0 :     sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
     915           0 :     ImpLineListData* pData = (*pLineList)[ nStyle ];
     916           0 :     if ( pData )
     917           0 :         rResult = pData->GetColorDist( GetColor( ), rResult );
     918             : 
     919           0 :     return rResult;
     920             : }
     921             : 
     922           0 : void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
     923             : {
     924           0 :     ListBox::DataChanged( rDCEvt );
     925             : 
     926           0 :     if( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
     927           0 :         UpdateEntries( m_nWidth );
     928           0 : }
     929             : 
     930         986 : FontNameBox::FontNameBox( vcl::Window* pParent, WinBits nWinStyle ) :
     931         986 :     ComboBox( pParent, nWinStyle )
     932             : {
     933         986 :     mpFontList = NULL;
     934         986 :     mbWYSIWYG = false;
     935         986 :     InitFontMRUEntriesFile();
     936         986 : }
     937             : 
     938           0 : VCL_BUILDER_DECL_FACTORY(FontNameBox)
     939             : {
     940           0 :     bool bDropdown = VclBuilder::extractDropdown(rMap);
     941           0 :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
     942           0 :     if (bDropdown)
     943           0 :         nWinBits |= WB_DROPDOWN;
     944           0 :     VclPtrInstance<FontNameBox> pListBox(pParent, nWinBits);
     945           0 :     if (bDropdown)
     946           0 :         pListBox->EnableAutoSize(true);
     947           0 :     rRet = pListBox;
     948           0 : }
     949             : 
     950        1972 : FontNameBox::~FontNameBox()
     951             : {
     952         986 :     disposeOnce();
     953         986 : }
     954             : 
     955         986 : void FontNameBox::dispose()
     956             : {
     957         986 :     if (mpFontList)
     958             :     {
     959         981 :         SaveMRUEntries (maFontMRUEntriesFile);
     960         981 :         ImplDestroyFontList();
     961             :     }
     962         986 :     ComboBox::dispose();
     963         986 : }
     964             : 
     965         981 : void FontNameBox::SaveMRUEntries( const OUString& aFontMRUEntriesFile, sal_Unicode cSep ) const
     966             : {
     967             :     OString aEntries(OUStringToOString(GetMRUEntries(cSep),
     968         981 :         RTL_TEXTENCODING_UTF8));
     969             : 
     970         981 :     if (aEntries.isEmpty() || aFontMRUEntriesFile.isEmpty())
     971         981 :         return;
     972             : 
     973           0 :     SvFileStream aStream;
     974           0 :     aStream.Open( aFontMRUEntriesFile, StreamMode::WRITE | StreamMode::TRUNC );
     975           0 :     if( ! (aStream.IsOpen() && aStream.IsWritable()) )
     976             :     {
     977             :         SAL_INFO("svtools.control", "FontNameBox::SaveMRUEntries: opening mru entries file " << aFontMRUEntriesFile << " failed\n");
     978           0 :         return;
     979             :     }
     980             : 
     981           0 :     aStream.SetLineDelimiter( LINEEND_LF );
     982           0 :     aStream.WriteLine( aEntries );
     983           0 :     aStream.WriteLine( OString() );
     984             : }
     985             : 
     986         981 : void FontNameBox::LoadMRUEntries( const OUString& aFontMRUEntriesFile, sal_Unicode cSep )
     987             : {
     988         981 :     if( aFontMRUEntriesFile.isEmpty() )
     989         981 :         return;
     990             : 
     991         981 :     SvFileStream aStream( aFontMRUEntriesFile, StreamMode::READ );
     992         981 :     if( ! aStream.IsOpen() )
     993             :     {
     994             :         SAL_INFO("svtools.control", "FontNameBox::LoadMRUEntries: opening mru entries file " << aFontMRUEntriesFile << " failed\n");
     995         981 :         return;
     996             :     }
     997             : 
     998           0 :     OString aLine;
     999           0 :     aStream.ReadLine( aLine );
    1000             :     OUString aEntries = OStringToOUString(aLine,
    1001           0 :         RTL_TEXTENCODING_UTF8);
    1002           0 :     SetMRUEntries( aEntries, cSep );
    1003             : }
    1004             : 
    1005         986 : void FontNameBox::InitFontMRUEntriesFile()
    1006             : {
    1007         986 :     OUString sUserConfigDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}");
    1008         986 :     rtl::Bootstrap::expandMacros(sUserConfigDir);
    1009             : 
    1010         986 :     maFontMRUEntriesFile = sUserConfigDir;
    1011         986 :     if( !maFontMRUEntriesFile.isEmpty() )
    1012             :     {
    1013         986 :         maFontMRUEntriesFile += FONTNAMEBOXMRUENTRIESFILE;
    1014         986 :     }
    1015         986 : }
    1016             : 
    1017        1962 : void FontNameBox::ImplDestroyFontList()
    1018             : {
    1019        1962 :     delete mpFontList;
    1020        1962 :     mpFontList = NULL;
    1021        1962 : }
    1022             : 
    1023         981 : void FontNameBox::Fill( const FontList* pList )
    1024             : {
    1025             :     // store old text and clear box
    1026         981 :     OUString aOldText = GetText();
    1027        1962 :     OUString rEntries = GetMRUEntries();
    1028         981 :     bool bLoadFromFile = rEntries.isEmpty();
    1029         981 :     Clear();
    1030             : 
    1031         981 :     ImplDestroyFontList();
    1032         981 :     mpFontList = new ImplFontList;
    1033             : 
    1034             :     // insert fonts
    1035         981 :     sal_uInt16 nFontCount = pList->GetFontNameCount();
    1036       85347 :     for ( sal_uInt16 i = 0; i < nFontCount; i++ )
    1037             :     {
    1038       84366 :         const vcl::FontInfo& rFontInfo = pList->GetFontName( i );
    1039       84366 :         sal_uLong nIndex = InsertEntry( rFontInfo.GetName() );
    1040       84366 :         if ( nIndex != LISTBOX_ERROR )
    1041             :         {
    1042       84366 :             if ( nIndex < mpFontList->size() ) {
    1043           0 :                 ImplFontList::iterator it = mpFontList->begin();
    1044           0 :                 ::std::advance( it, nIndex );
    1045           0 :                 mpFontList->insert( it, rFontInfo );
    1046             :             } else {
    1047       84366 :                 mpFontList->push_back( rFontInfo );
    1048             :             }
    1049             :         }
    1050             :     }
    1051             : 
    1052         981 :     if ( bLoadFromFile )
    1053         981 :         LoadMRUEntries (maFontMRUEntriesFile);
    1054             :     else
    1055           0 :         SetMRUEntries( rEntries );
    1056             : 
    1057         981 :     ImplCalcUserItemSize();
    1058             : 
    1059             :     // restore text
    1060         981 :     if (!aOldText.isEmpty())
    1061        1962 :         SetText( aOldText );
    1062         981 : }
    1063             : 
    1064         986 : void FontNameBox::EnableWYSIWYG( bool bEnable )
    1065             : {
    1066         986 :     if ( bEnable != mbWYSIWYG )
    1067             :     {
    1068         986 :         mbWYSIWYG = bEnable;
    1069         986 :         EnableUserDraw( mbWYSIWYG );
    1070         986 :         ImplCalcUserItemSize();
    1071             :     }
    1072         986 : }
    1073             : 
    1074        1967 : void FontNameBox::ImplCalcUserItemSize()
    1075             : {
    1076        1967 :     Size aUserItemSz;
    1077        1967 :     if ( mbWYSIWYG && mpFontList )
    1078             :     {
    1079         981 :         aUserItemSz = Size(MAXPREVIEWWIDTH, GetTextHeight() );
    1080         981 :         aUserItemSz.Height() *= 16;
    1081         981 :         aUserItemSz.Height() /= 10;
    1082             :     }
    1083        1967 :     SetUserItemSize( aUserItemSz );
    1084        1967 : }
    1085             : 
    1086             : namespace
    1087             : {
    1088           0 :     long shrinkFontToFit(OUString &rSampleText, long nH, vcl::Font &rFont, OutputDevice &rDevice, Rectangle &rTextRect)
    1089             :     {
    1090           0 :         long nWidth = 0;
    1091             : 
    1092           0 :         Size aSize( rFont.GetSize() );
    1093             : 
    1094             :         //Make sure it fits in the available height
    1095           0 :         while (aSize.Height() > 0)
    1096             :         {
    1097           0 :             if (!rDevice.GetTextBoundRect(rTextRect, rSampleText, 0, 0))
    1098           0 :                 break;
    1099           0 :             if (rTextRect.GetHeight() <= nH)
    1100             :             {
    1101           0 :                 nWidth = rTextRect.GetWidth();
    1102           0 :                 break;
    1103             :             }
    1104             : 
    1105           0 :             aSize.Height() -= EXTRAFONTSIZE;
    1106           0 :             rFont.SetSize(aSize);
    1107           0 :             rDevice.SetFont(rFont);
    1108             :         }
    1109             : 
    1110           0 :         return nWidth;
    1111             :     }
    1112             : }
    1113             : 
    1114           0 : void FontNameBox::UserDraw( const UserDrawEvent& rUDEvt )
    1115             : {
    1116             :     assert( mpFontList );
    1117             : 
    1118           0 :     vcl::FontInfo& rInfo = (*mpFontList)[ rUDEvt.GetItemId() ];
    1119           0 :     Point aTopLeft = rUDEvt.GetRect().TopLeft();
    1120           0 :     long nX = aTopLeft.X();
    1121           0 :     long nH = rUDEvt.GetRect().GetHeight();
    1122             : 
    1123           0 :     if ( mbWYSIWYG )
    1124             :     {
    1125           0 :         nX += IMGOUTERTEXTSPACE;
    1126             : 
    1127           0 :         const bool bSymbolFont = isSymbolFont(rInfo);
    1128             : 
    1129           0 :         Color aTextColor = rUDEvt.GetDevice()->GetTextColor();
    1130           0 :         vcl::Font aOldFont( rUDEvt.GetDevice()->GetFont() );
    1131           0 :         Size aSize( aOldFont.GetSize() );
    1132           0 :         aSize.Height() += EXTRAFONTSIZE;
    1133           0 :         vcl::Font aFont( rInfo );
    1134           0 :         aFont.SetSize( aSize );
    1135           0 :         rUDEvt.GetDevice()->SetFont( aFont );
    1136           0 :         rUDEvt.GetDevice()->SetTextColor( aTextColor );
    1137             : 
    1138           0 :         bool bUsingCorrectFont = true;
    1139           0 :         Rectangle aTextRect;
    1140             : 
    1141             :         // Preview the font name
    1142           0 :         OUString sFontName = rInfo.GetName();
    1143             : 
    1144             :         //If it shouldn't or can't draw its own name because it doesn't have the glyphs
    1145           0 :         if (!canRenderNameOfSelectedFont(*rUDEvt.GetDevice()))
    1146           0 :             bUsingCorrectFont = false;
    1147             :         else
    1148             :         {
    1149             :             //Make sure it fits in the available height, shrinking the font if necessary
    1150           0 :             bUsingCorrectFont = shrinkFontToFit(sFontName, nH, aFont, *rUDEvt.GetDevice(), aTextRect) != 0;
    1151             :         }
    1152             : 
    1153           0 :         if (!bUsingCorrectFont)
    1154             :         {
    1155           0 :             rUDEvt.GetDevice()->SetFont(aOldFont);
    1156           0 :             rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sFontName, 0, 0);
    1157             :         }
    1158             : 
    1159           0 :         long nTextHeight = aTextRect.GetHeight();
    1160           0 :         long nDesiredGap = (nH-nTextHeight)/2;
    1161           0 :         long nVertAdjust = nDesiredGap - aTextRect.Top();
    1162           0 :         Point aPos( nX, aTopLeft.Y() + nVertAdjust );
    1163           0 :         rUDEvt.GetDevice()->DrawText( aPos, sFontName );
    1164           0 :         long nTextX = aPos.X() + aTextRect.GetWidth() + GAPTOEXTRAPREVIEW;
    1165             : 
    1166           0 :         if (!bUsingCorrectFont)
    1167           0 :             rUDEvt.GetDevice()->SetFont( aFont );
    1168             : 
    1169           0 :         OUString sSampleText;
    1170             : 
    1171           0 :         if (!bSymbolFont)
    1172             :         {
    1173           0 :             const bool bNameBeginsWithLatinText = rInfo.GetName()[0] <= 'z';
    1174             : 
    1175           0 :             if (bNameBeginsWithLatinText || !bUsingCorrectFont)
    1176           0 :                 sSampleText = makeShortRepresentativeTextForSelectedFont(*rUDEvt.GetDevice());
    1177             :         }
    1178             : 
    1179             :         //If we're not a symbol font, but could neither render our own name and
    1180             :         //we can't determine what script it would like to render, then try a
    1181             :         //few well known scripts
    1182           0 :         if (sSampleText.isEmpty() && !bUsingCorrectFont)
    1183             :         {
    1184             :             static const UScriptCode aScripts[] =
    1185             :             {
    1186             :                 USCRIPT_ARABIC,
    1187             :                 USCRIPT_HEBREW,
    1188             : 
    1189             :                 USCRIPT_BENGALI,
    1190             :                 USCRIPT_GURMUKHI,
    1191             :                 USCRIPT_GUJARATI,
    1192             :                 USCRIPT_ORIYA,
    1193             :                 USCRIPT_TAMIL,
    1194             :                 USCRIPT_TELUGU,
    1195             :                 USCRIPT_KANNADA,
    1196             :                 USCRIPT_MALAYALAM,
    1197             :                 USCRIPT_SINHALA,
    1198             :                 USCRIPT_DEVANAGARI,
    1199             : 
    1200             :                 USCRIPT_THAI,
    1201             :                 USCRIPT_LAO,
    1202             :                 USCRIPT_GEORGIAN,
    1203             :                 USCRIPT_TIBETAN,
    1204             :                 USCRIPT_SYRIAC,
    1205             :                 USCRIPT_MYANMAR,
    1206             :                 USCRIPT_ETHIOPIC,
    1207             :                 USCRIPT_KHMER,
    1208             :                 USCRIPT_MONGOLIAN,
    1209             : 
    1210             :                 USCRIPT_KOREAN,
    1211             :                 USCRIPT_JAPANESE,
    1212             :                 USCRIPT_HAN,
    1213             :                 USCRIPT_SIMPLIFIED_HAN,
    1214             :                 USCRIPT_TRADITIONAL_HAN,
    1215             : 
    1216             :                 USCRIPT_GREEK
    1217             :             };
    1218             : 
    1219           0 :             for (size_t i = 0; i < SAL_N_ELEMENTS(aScripts); ++i)
    1220             :             {
    1221           0 :                 OUString sText = makeShortRepresentativeTextForScript(aScripts[i]);
    1222           0 :                 if (!sText.isEmpty())
    1223             :                 {
    1224           0 :                     bool bHasSampleTextGlyphs = (-1 == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
    1225           0 :                     if (bHasSampleTextGlyphs)
    1226             :                     {
    1227           0 :                         sSampleText = sText;
    1228           0 :                         break;
    1229             :                     }
    1230             :                 }
    1231           0 :             }
    1232             : 
    1233             :             static const UScriptCode aMinimalScripts[] =
    1234             :             {
    1235             :                 USCRIPT_HEBREW, //e.g. biblical hebrew
    1236             :                 USCRIPT_GREEK
    1237             :             };
    1238             : 
    1239           0 :             for (size_t i = 0; i < SAL_N_ELEMENTS(aMinimalScripts); ++i)
    1240             :             {
    1241           0 :                 OUString sText = makeShortMinimalTextForScript(aMinimalScripts[i]);
    1242           0 :                 if (!sText.isEmpty())
    1243             :                 {
    1244           0 :                     bool bHasSampleTextGlyphs = (-1 == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
    1245           0 :                     if (bHasSampleTextGlyphs)
    1246             :                     {
    1247           0 :                         sSampleText = sText;
    1248           0 :                         break;
    1249             :                     }
    1250             :                 }
    1251           0 :             }
    1252             :         }
    1253             : 
    1254             :         //If we're a symbol font, or for some reason the font still couldn't
    1255             :         //render something representative of what it would like to render then
    1256             :         //make up some semi-random text that it *can* display
    1257           0 :         if (bSymbolFont || (!bUsingCorrectFont && sSampleText.isEmpty()))
    1258           0 :             sSampleText = makeShortRepresentativeSymbolTextForSelectedFont(*rUDEvt.GetDevice());
    1259             : 
    1260           0 :         if (!sSampleText.isEmpty())
    1261             :         {
    1262           0 :             const Size &rItemSize = rUDEvt.GetDevice()->GetOutputSize();
    1263             :             //leave a little border at the edge
    1264           0 :             long nSpace = rItemSize.Width() - nTextX - IMGOUTERTEXTSPACE;
    1265           0 :             if (nSpace >= 0)
    1266             :             {
    1267             :                 //Make sure it fits in the available height, and get how wide that would be
    1268           0 :                 long nWidth = shrinkFontToFit(sSampleText, nH, aFont, *rUDEvt.GetDevice(), aTextRect);
    1269             :                 //Chop letters off until it fits in the available width
    1270           0 :                 while (nWidth > nSpace || nWidth > MAXPREVIEWWIDTH)
    1271             :                 {
    1272           0 :                     sSampleText = sSampleText.copy(0, sSampleText.getLength()-1);
    1273           0 :                     nWidth = rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sSampleText, 0, 0) ?
    1274           0 :                              aTextRect.GetWidth() : 0;
    1275             :                 }
    1276             : 
    1277             :                 //center the text on the line
    1278           0 :                 if (!sSampleText.isEmpty() && nWidth)
    1279             :                 {
    1280           0 :                     nTextHeight = aTextRect.GetHeight();
    1281           0 :                     nDesiredGap = (nH-nTextHeight)/2;
    1282           0 :                     nVertAdjust = nDesiredGap - aTextRect.Top();
    1283           0 :                     aPos = Point(nTextX + nSpace - nWidth, aTopLeft.Y() + nVertAdjust);
    1284           0 :                     rUDEvt.GetDevice()->DrawText( aPos, sSampleText );
    1285             :                 }
    1286             :             }
    1287             :         }
    1288             : 
    1289           0 :         rUDEvt.GetDevice()->SetFont( aOldFont );
    1290           0 :         DrawEntry( rUDEvt, false, false);   // draw separator
    1291             :     }
    1292             :     else
    1293             :     {
    1294           0 :         DrawEntry( rUDEvt, true, true );
    1295             :     }
    1296           0 : }
    1297             : 
    1298           0 : FontStyleBox::FontStyleBox(vcl::Window* pParent, WinBits nBits)
    1299           0 :     : ComboBox(pParent, nBits)
    1300             : {
    1301             :     //Use the standard texts to get an optimal size and stick to that size.
    1302             :     //That should stop the character dialog dancing around.
    1303           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT));
    1304           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT_ITALIC));
    1305           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL));
    1306           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL_ITALIC));
    1307           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD));
    1308           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD_ITALIC));
    1309           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK));
    1310           0 :     InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK_ITALIC));
    1311           0 :     aOptimalSize = GetOptimalSize();
    1312           0 :     Clear();
    1313           0 : }
    1314             : 
    1315           0 : Size FontStyleBox::GetOptimalSize() const
    1316             : {
    1317           0 :     if (aOptimalSize.Width() || aOptimalSize.Height())
    1318           0 :         return aOptimalSize;
    1319           0 :     return ComboBox::GetOptimalSize();
    1320             : }
    1321             : 
    1322           0 : VCL_BUILDER_DECL_FACTORY(FontStyleBox)
    1323             : {
    1324           0 :     bool bDropdown = VclBuilder::extractDropdown(rMap);
    1325           0 :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
    1326           0 :     if (bDropdown)
    1327           0 :         nWinBits |= WB_DROPDOWN;
    1328           0 :     VclPtrInstance<FontStyleBox> pListBox(pParent, nWinBits);
    1329           0 :     if (bDropdown)
    1330           0 :         pListBox->EnableAutoSize(true);
    1331           0 :     rRet = pListBox;
    1332           0 : }
    1333             : 
    1334           0 : void FontStyleBox::Select()
    1335             : {
    1336             :     // keep text over fill operation
    1337           0 :     aLastStyle = GetText();
    1338           0 :     ComboBox::Select();
    1339           0 : }
    1340             : 
    1341           0 : void FontStyleBox::LoseFocus()
    1342             : {
    1343             :     // keep text over fill operation
    1344           0 :     aLastStyle = GetText();
    1345           0 :     ComboBox::LoseFocus();
    1346           0 : }
    1347             : 
    1348           0 : void FontStyleBox::Modify()
    1349             : {
    1350             :     CharClass   aChrCls( ::comphelper::getProcessComponentContext(),
    1351           0 :                         GetSettings().GetLanguageTag() );
    1352           0 :     OUString   aStr = GetText();
    1353           0 :     sal_Int32      nEntryCount = GetEntryCount();
    1354             : 
    1355           0 :     if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
    1356             :     {
    1357           0 :         aStr = aChrCls.uppercase(aStr);
    1358           0 :         for ( sal_Int32 i = 0; i < nEntryCount; i++ )
    1359             :         {
    1360           0 :             OUString aEntryText = aChrCls.uppercase(GetEntry(i));
    1361             : 
    1362           0 :             if ( aStr == aEntryText )
    1363             :             {
    1364           0 :                 SetText( GetEntry( i ) );
    1365           0 :                 break;
    1366             :             }
    1367           0 :         }
    1368             :     }
    1369             : 
    1370           0 :     ComboBox::Modify();
    1371           0 : }
    1372             : 
    1373           0 : void FontStyleBox::Fill( const OUString& rName, const FontList* pList )
    1374             : {
    1375             :     // note: this method must call ComboBox::SetText(),
    1376             :     //   else aLastStyle will overwritten
    1377             :     // store prior selection position and clear box
    1378           0 :     OUString aOldText = GetText();
    1379           0 :     sal_Int32 nPos = GetEntryPos( aOldText );
    1380           0 :     Clear();
    1381             : 
    1382             :     // does a font with this name already exist?
    1383           0 :     sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
    1384           0 :     if ( hFontInfo )
    1385             :     {
    1386           0 :         OUString aStyleText;
    1387           0 :         FontWeight  eLastWeight = WEIGHT_DONTKNOW;
    1388           0 :         FontItalic  eLastItalic = ITALIC_NONE;
    1389           0 :         FontWidth   eLastWidth = WIDTH_DONTKNOW;
    1390           0 :         bool        bNormal = false;
    1391           0 :         bool        bItalic = false;
    1392           0 :         bool        bBold = false;
    1393           0 :         bool        bBoldItalic = false;
    1394           0 :         bool        bInsert = false;
    1395           0 :         vcl::FontInfo    aInfo;
    1396           0 :         while ( hFontInfo )
    1397             :         {
    1398           0 :             aInfo = FontList::GetFontInfo( hFontInfo );
    1399             : 
    1400           0 :             FontWeight  eWeight = aInfo.GetWeight();
    1401           0 :             FontItalic  eItalic = aInfo.GetItalic();
    1402           0 :             FontWidth   eWidth = aInfo.GetWidthType();
    1403             :             // Only if the attributes are different, we insert the
    1404             :             // Font to avoid double Entries in different languages
    1405           0 :             if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
    1406             :                  (eWidth != eLastWidth) )
    1407             :             {
    1408           0 :                 if ( bInsert )
    1409           0 :                     InsertEntry( aStyleText );
    1410             : 
    1411           0 :                 if ( eWeight <= WEIGHT_NORMAL )
    1412             :                 {
    1413           0 :                     if ( eItalic != ITALIC_NONE )
    1414           0 :                         bItalic = true;
    1415             :                     else
    1416           0 :                         bNormal = true;
    1417             :                 }
    1418             :                 else
    1419             :                 {
    1420           0 :                     if ( eItalic != ITALIC_NONE )
    1421           0 :                         bBoldItalic = true;
    1422             :                     else
    1423           0 :                         bBold = true;
    1424             :                 }
    1425             : 
    1426             :                 // For wrong StyleNames we replace this with the correct once
    1427           0 :                 aStyleText = pList->GetStyleName( aInfo );
    1428           0 :                 bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
    1429           0 :                 if ( !bInsert )
    1430             :                 {
    1431           0 :                     aStyleText = pList->GetStyleName( eWeight, eItalic );
    1432           0 :                     bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
    1433             :                 }
    1434             : 
    1435           0 :                 eLastWeight = eWeight;
    1436           0 :                 eLastItalic = eItalic;
    1437           0 :                 eLastWidth = eWidth;
    1438             :             }
    1439             :             else
    1440             :             {
    1441           0 :                 if ( bInsert )
    1442             :                 {
    1443             :                     // If we have two names for the same attributes
    1444             :                     // we prefer the translated standard names
    1445           0 :                     const OUString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
    1446           0 :                     if (rAttrStyleText != aStyleText)
    1447             :                     {
    1448           0 :                         OUString aTempStyleText = pList->GetStyleName( aInfo );
    1449           0 :                         if (rAttrStyleText == aTempStyleText)
    1450           0 :                             aStyleText = rAttrStyleText;
    1451           0 :                         bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
    1452             :                     }
    1453             :                 }
    1454             :             }
    1455             : 
    1456           0 :             if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
    1457           0 :                 bItalic = true;
    1458           0 :             else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
    1459           0 :                 bBold = true;
    1460           0 :             else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
    1461           0 :                 bBoldItalic = true;
    1462             : 
    1463           0 :             hFontInfo = FontList::GetNextFontInfo( hFontInfo );
    1464             :         }
    1465             : 
    1466           0 :         if ( bInsert )
    1467           0 :             InsertEntry( aStyleText );
    1468             : 
    1469             :         // certain style as copy
    1470           0 :         if ( bNormal )
    1471             :         {
    1472           0 :             if ( !bItalic )
    1473           0 :                 InsertEntry( pList->GetItalicStr() );
    1474           0 :             if ( !bBold )
    1475           0 :                 InsertEntry( pList->GetBoldStr() );
    1476             :         }
    1477           0 :         if ( !bBoldItalic )
    1478             :         {
    1479           0 :             if ( bNormal || bItalic || bBold )
    1480           0 :                 InsertEntry( pList->GetBoldItalicStr() );
    1481             :         }
    1482           0 :         if (!aOldText.isEmpty())
    1483             :         {
    1484           0 :             if ( GetEntryPos( aLastStyle ) != LISTBOX_ENTRY_NOTFOUND )
    1485           0 :                 ComboBox::SetText( aLastStyle );
    1486             :             else
    1487             :             {
    1488           0 :                 if ( nPos >= GetEntryCount() )
    1489           0 :                     ComboBox::SetText( GetEntry( 0 ) );
    1490             :                 else
    1491           0 :                     ComboBox::SetText( GetEntry( nPos ) );
    1492             :             }
    1493           0 :         }
    1494             :     }
    1495             :     else
    1496             :     {
    1497             :         // insert standard styles if no font
    1498           0 :         InsertEntry( pList->GetNormalStr() );
    1499           0 :         InsertEntry( pList->GetItalicStr() );
    1500           0 :         InsertEntry( pList->GetBoldStr() );
    1501           0 :         InsertEntry( pList->GetBoldItalicStr() );
    1502           0 :         if (!aOldText.isEmpty())
    1503             :         {
    1504           0 :             if ( nPos > GetEntryCount() )
    1505           0 :                 ComboBox::SetText( GetEntry( 0 ) );
    1506             :             else
    1507           0 :                 ComboBox::SetText( GetEntry( nPos ) );
    1508             :         }
    1509           0 :     }
    1510           0 : }
    1511             : 
    1512         986 : FontSizeBox::FontSizeBox( vcl::Window* pParent, WinBits nWinSize ) :
    1513         986 :     MetricBox( pParent, nWinSize )
    1514             : {
    1515         986 :     ImplInit();
    1516         986 : }
    1517             : 
    1518           0 : VCL_BUILDER_DECL_FACTORY(FontSizeBox)
    1519             : {
    1520           0 :     bool bDropdown = VclBuilder::extractDropdown(rMap);
    1521           0 :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
    1522           0 :     if (bDropdown)
    1523           0 :         nWinBits |= WB_DROPDOWN;
    1524           0 :     VclPtrInstance<FontSizeBox> pListBox(pParent, nWinBits);
    1525           0 :     if (bDropdown)
    1526           0 :         pListBox->EnableAutoSize(true);
    1527           0 :     rRet = pListBox;
    1528           0 : }
    1529             : 
    1530         986 : void FontSizeBox::ImplInit()
    1531             : {
    1532         986 :     EnableAutocomplete( false );
    1533             : 
    1534         986 :     bRelativeMode   = false;
    1535         986 :     bPtRelative     = false;
    1536         986 :     bRelative       = false;
    1537         986 :     bStdSize        = false;
    1538         986 :     pFontList       = NULL;
    1539             : 
    1540         986 :     SetShowTrailingZeros( false );
    1541         986 :     SetDecimalDigits( 1 );
    1542         986 :     SetMin( 20 );
    1543         986 :     SetMax( 9999 );
    1544         986 :     SetProminentEntryType( ProminentEntry::MIDDLE );
    1545         986 : }
    1546             : 
    1547           0 : void FontSizeBox::Reformat()
    1548             : {
    1549           0 :     FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
    1550           0 :     if ( !bRelativeMode || !aFontSizeNames.IsEmpty() )
    1551             :     {
    1552           0 :         long nNewValue = aFontSizeNames.Name2Size( GetText() );
    1553           0 :         if ( nNewValue)
    1554             :         {
    1555           0 :             mnLastValue = nNewValue;
    1556           0 :             return;
    1557             :         }
    1558             :     }
    1559             : 
    1560           0 :     MetricBox::Reformat();
    1561             : }
    1562             : 
    1563           0 : void FontSizeBox::Modify()
    1564             : {
    1565           0 :     MetricBox::Modify();
    1566             : 
    1567           0 :     if ( bRelativeMode )
    1568             :     {
    1569           0 :         OUString aStr = comphelper::string::stripStart(GetText(), ' ');
    1570             : 
    1571           0 :         bool bNewMode = bRelative;
    1572           0 :         bool bOldPtRelMode = bPtRelative;
    1573             : 
    1574           0 :         if ( bRelative )
    1575             :         {
    1576           0 :             bPtRelative = false;
    1577           0 :             const sal_Unicode* pStr = aStr.getStr();
    1578           0 :             while ( *pStr )
    1579             :             {
    1580           0 :                 if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') && !unicode::isSpace(*pStr) )
    1581             :                 {
    1582           0 :                     if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
    1583           0 :                         bPtRelative = true;
    1584           0 :                     else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
    1585             :                         ;
    1586             :                     else
    1587             :                     {
    1588           0 :                         bNewMode = false;
    1589           0 :                         break;
    1590             :                     }
    1591             :                 }
    1592           0 :                 pStr++;
    1593             :             }
    1594             :         }
    1595             :         else
    1596             :         {
    1597           0 :             if ( -1 != aStr.indexOf('%') )
    1598             :             {
    1599           0 :                 bNewMode = true;
    1600           0 :                 bPtRelative = false;
    1601             :             }
    1602             : 
    1603           0 :             if ( '-' == aStr[0] || '+' == aStr[0] )
    1604             :             {
    1605           0 :                 bNewMode = true;
    1606           0 :                 bPtRelative = true;
    1607             :             }
    1608             :         }
    1609             : 
    1610           0 :         if ( bNewMode != bRelative || bPtRelative != bOldPtRelMode )
    1611           0 :             SetRelative( bNewMode );
    1612             :     }
    1613           0 : }
    1614             : 
    1615        2659 : void FontSizeBox::Fill( const vcl::FontInfo* pInfo, const FontList* pList )
    1616             : {
    1617             :     // remember for relative mode
    1618        2659 :     pFontList = pList;
    1619             : 
    1620             :     // no font sizes need to be set for relative mode
    1621        2659 :     if ( bRelative )
    1622        1673 :         return;
    1623             : 
    1624             :     // query font sizes
    1625             :     const sal_IntPtr* pTempAry;
    1626        2659 :     const sal_IntPtr* pAry = 0;
    1627             : 
    1628        2659 :     if( pInfo )
    1629             :     {
    1630        1673 :         aFontInfo = *pInfo;
    1631        1673 :         pAry = pList->GetSizeAry( *pInfo );
    1632             :     }
    1633             :     else
    1634             :     {
    1635         986 :         pAry = FontList::GetStdSizeAry();
    1636             :     }
    1637             : 
    1638             :     // first insert font size names (for simplified/traditional chinese)
    1639        2659 :     FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
    1640        2659 :     if ( pAry == FontList::GetStdSizeAry() )
    1641             :     {
    1642             :         // for standard sizes we don't need to bother
    1643        2659 :         if ( bStdSize && GetEntryCount() && aFontSizeNames.IsEmpty() )
    1644        1673 :             return;
    1645         986 :         bStdSize = true;
    1646             :     }
    1647             :     else
    1648           0 :         bStdSize = false;
    1649             : 
    1650         986 :     Selection aSelection = GetSelection();
    1651         986 :     OUString aStr = GetText();
    1652             : 
    1653         986 :     Clear();
    1654         986 :     sal_Int32 nPos = 0;
    1655             : 
    1656         986 :     if ( !aFontSizeNames.IsEmpty() )
    1657             :     {
    1658           0 :         if ( pAry == FontList::GetStdSizeAry() )
    1659             :         {
    1660             :             // for scalable fonts all font size names
    1661           0 :             sal_uLong nCount = aFontSizeNames.Count();
    1662           0 :             for( sal_uLong i = 0; i < nCount; i++ )
    1663             :             {
    1664           0 :                 OUString    aSizeName = aFontSizeNames.GetIndexName( i );
    1665           0 :                 sal_IntPtr  nSize = aFontSizeNames.GetIndexSize( i );
    1666           0 :                 ComboBox::InsertEntry( aSizeName, nPos );
    1667           0 :                 ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(-nSize) ); // mark as special
    1668           0 :                 nPos++;
    1669           0 :             }
    1670             :         }
    1671             :         else
    1672             :         {
    1673             :             // for fixed size fonts only selectable font size names
    1674           0 :             pTempAry = pAry;
    1675           0 :             while ( *pTempAry )
    1676             :             {
    1677           0 :                 OUString aSizeName = aFontSizeNames.Size2Name( *pTempAry );
    1678           0 :                 if ( !aSizeName.isEmpty() )
    1679             :                 {
    1680           0 :                     ComboBox::InsertEntry( aSizeName, nPos );
    1681           0 :                     ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(-(*pTempAry)) ); // mark as special
    1682           0 :                     nPos++;
    1683             :                 }
    1684           0 :                 pTempAry++;
    1685           0 :             }
    1686             :         }
    1687             :     }
    1688             : 
    1689             :     // then insert numerical font size values
    1690         986 :     pTempAry = pAry;
    1691       31552 :     while ( *pTempAry )
    1692             :     {
    1693       29580 :         InsertValue( *pTempAry, FUNIT_NONE, nPos );
    1694       29580 :         ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(*pTempAry) );
    1695       29580 :         nPos++;
    1696       29580 :         pTempAry++;
    1697             :     }
    1698             : 
    1699         986 :     SetText( aStr );
    1700         986 :     SetSelection( aSelection );
    1701             : }
    1702             : 
    1703           0 : void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax, sal_uInt16 nStep )
    1704             : {
    1705           0 :     bRelativeMode = true;
    1706           0 :     nRelMin       = nMin;
    1707           0 :     nRelMax       = nMax;
    1708           0 :     nRelStep      = nStep;
    1709           0 :     SetUnit( FUNIT_POINT );
    1710           0 : }
    1711             : 
    1712           0 : void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
    1713             : {
    1714           0 :     bRelativeMode = true;
    1715           0 :     nPtRelMin     = nMin;
    1716           0 :     nPtRelMax     = nMax;
    1717           0 :     nPtRelStep    = nStep;
    1718           0 :     SetUnit( FUNIT_POINT );
    1719           0 : }
    1720             : 
    1721           0 : void FontSizeBox::SetRelative( bool bNewRelative )
    1722             : {
    1723           0 :     if ( bRelativeMode )
    1724             :     {
    1725           0 :         Selection aSelection = GetSelection();
    1726           0 :         OUString aStr = comphelper::string::stripStart(GetText(), ' ');
    1727             : 
    1728           0 :         if ( bNewRelative )
    1729             :         {
    1730           0 :             bRelative = true;
    1731           0 :             bStdSize = false;
    1732             : 
    1733           0 :             if ( bPtRelative )
    1734             :             {
    1735           0 :                 Clear(); //clear early because SetDecimalDigits is a slow recalc
    1736             : 
    1737           0 :                 SetDecimalDigits( 1 );
    1738           0 :                 SetMin( nPtRelMin );
    1739           0 :                 SetMax( nPtRelMax );
    1740           0 :                 SetUnit( FUNIT_POINT );
    1741             : 
    1742           0 :                 short i = nPtRelMin, n = 0;
    1743             :                 // JP 30.06.98: more than 100 values are not useful
    1744           0 :                 while ( i <= nPtRelMax && n++ < 100 )
    1745             :                 {
    1746           0 :                     InsertValue( i );
    1747           0 :                     i = i + nPtRelStep;
    1748             :                 }
    1749             :             }
    1750             :             else
    1751             :             {
    1752           0 :                 Clear(); //clear early because SetDecimalDigits is a slow recalc
    1753             : 
    1754           0 :                 SetDecimalDigits( 0 );
    1755           0 :                 SetMin( nRelMin );
    1756           0 :                 SetMax( nRelMax );
    1757           0 :                 SetUnit( FUNIT_PERCENT );
    1758             : 
    1759           0 :                 sal_uInt16 i = nRelMin;
    1760           0 :                 while ( i <= nRelMax )
    1761             :                 {
    1762           0 :                     InsertValue( i );
    1763           0 :                     i = i + nRelStep;
    1764             :                 }
    1765             :             }
    1766             :         }
    1767             :         else
    1768             :         {
    1769           0 :             if (pFontList)
    1770           0 :                 Clear(); //clear early because SetDecimalDigits is a slow recalc
    1771           0 :             bRelative = bPtRelative = false;
    1772           0 :             SetDecimalDigits( 1 );
    1773           0 :             SetMin( 20 );
    1774           0 :             SetMax( 9999 );
    1775           0 :             SetUnit( FUNIT_POINT );
    1776           0 :             if ( pFontList )
    1777           0 :                 Fill( &aFontInfo, pFontList );
    1778             :         }
    1779             : 
    1780           0 :         SetText( aStr );
    1781           0 :         SetSelection( aSelection );
    1782             :     }
    1783           0 : }
    1784             : 
    1785       40132 : OUString FontSizeBox::CreateFieldText( sal_Int64 nValue ) const
    1786             : {
    1787       40132 :     OUString sRet( MetricBox::CreateFieldText( nValue ) );
    1788       40132 :     if ( bRelativeMode && bPtRelative && (0 <= nValue) && !sRet.isEmpty() )
    1789           0 :         sRet = "+" + sRet;
    1790       40132 :     return sRet;
    1791             : }
    1792             : 
    1793        4636 : void FontSizeBox::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
    1794             : {
    1795        4636 :     if ( !bRelative )
    1796             :     {
    1797        4636 :         sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
    1798        4636 :         FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
    1799             :         // conversion loses precision; however font sizes should
    1800             :         // never have a problem with that
    1801        4636 :         OUString aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
    1802        4636 :         if ( !aName.isEmpty() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
    1803             :         {
    1804           0 :             mnLastValue = nTempValue;
    1805           0 :             SetText( aName );
    1806           0 :             mnFieldValue = mnLastValue;
    1807           0 :             SetEmptyFieldValueData( false );
    1808        4636 :             return;
    1809        4636 :         }
    1810             :     }
    1811             : 
    1812        4636 :     MetricBox::SetValue( nNewValue, eInUnit );
    1813             : }
    1814             : 
    1815        4636 : void FontSizeBox::SetValue( sal_Int64 nNewValue )
    1816             : {
    1817        4636 :     SetValue( nNewValue, FUNIT_NONE );
    1818        4636 : }
    1819             : 
    1820        4338 : sal_Int64 FontSizeBox::GetValue( FieldUnit eOutUnit ) const
    1821             : {
    1822        4338 :     if ( !bRelative )
    1823             :     {
    1824        4338 :         FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
    1825        4338 :         sal_Int64 nValue = aFontSizeNames.Name2Size( GetText() );
    1826        4338 :         if ( nValue)
    1827           0 :             return MetricField::ConvertValue( nValue, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit );
    1828             :     }
    1829             : 
    1830        4338 :     return MetricBox::GetValue( eOutUnit );
    1831             : }
    1832             : 
    1833        4338 : sal_Int64 FontSizeBox::GetValue() const
    1834             : {
    1835             :     // implementation not inline, because it is a virtual function
    1836        4338 :     return GetValue( FUNIT_NONE );
    1837         798 : }
    1838             : 
    1839             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11