LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/filter/html - htmldraw.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 389 0.3 %
Date: 2013-07-09 Functions: 2 11 18.2 %
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 "hintids.hxx"
      21             : #include <vcl/svapp.hxx>
      22             : #include <vcl/wrkwin.hxx>
      23             : #include <svx/svdmodel.hxx>
      24             : #include <svx/svdpage.hxx>
      25             : #include <svx/svdobj.hxx>
      26             : #include <svx/svdotext.hxx>
      27             : #include <editeng/eeitem.hxx>
      28             : #include <editeng/outliner.hxx>
      29             : #include <svx/xfillit.hxx>
      30             : #include <editeng/colritem.hxx>
      31             : #include <editeng/brushitem.hxx>
      32             : #include <editeng/lrspitem.hxx>
      33             : #include <editeng/ulspitem.hxx>
      34             : #include <svl/itemiter.hxx>
      35             : #include <svl/whiter.hxx>
      36             : #include <svtools/htmlout.hxx>
      37             : #include <svtools/htmltokn.h>
      38             : #include <svtools/htmlkywd.hxx>
      39             : #include <svx/svdpool.hxx>
      40             : 
      41             : 
      42             : #include "charatr.hxx"
      43             : #include <frmfmt.hxx>
      44             : #include <fmtanchr.hxx>
      45             : #include <fmtsrnd.hxx>
      46             : #include "ndtxt.hxx"
      47             : #include "doc.hxx"
      48             : #include "dcontact.hxx"
      49             : #include "poolfmt.hxx"
      50             : #include "swcss1.hxx"
      51             : #include "swhtml.hxx"
      52             : #include "wrthtml.hxx"
      53             : #include <rtl/strbuf.hxx>
      54             : 
      55             : using namespace ::com::sun::star;
      56             : 
      57             : 
      58             : const sal_uInt32 HTML_FRMOPTS_MARQUEE   =
      59             :     HTML_FRMOPT_ALIGN |
      60             :     HTML_FRMOPT_SPACE;
      61             : 
      62             : const sal_uInt32 HTML_FRMOPTS_MARQUEE_CSS1  =
      63             :     HTML_FRMOPT_S_ALIGN |
      64             :     HTML_FRMOPT_S_SPACE;
      65             : 
      66             : static HTMLOptionEnum aHTMLMarqBehaviorTable[] =
      67             : {
      68             :     { OOO_STRING_SVTOOLS_HTML_BEHAV_scroll,     SDRTEXTANI_SCROLL       },
      69             :     { OOO_STRING_SVTOOLS_HTML_BEHAV_alternate,  SDRTEXTANI_ALTERNATE    },
      70             :     { OOO_STRING_SVTOOLS_HTML_BEHAV_slide,      SDRTEXTANI_SLIDE        },
      71             :     { 0,                        0                       }
      72             : };
      73             : 
      74             : static HTMLOptionEnum aHTMLMarqDirectionTable[] =
      75             : {
      76             :     { OOO_STRING_SVTOOLS_HTML_AL_left,          SDRTEXTANI_LEFT         },
      77             :     { OOO_STRING_SVTOOLS_HTML_AL_right,         SDRTEXTANI_RIGHT        },
      78             :     { 0,                        0                       }
      79             : };
      80             : 
      81           0 : void SwHTMLParser::InsertDrawObject( SdrObject* pNewDrawObj,
      82             :                                      const Size& rPixSpace,
      83             :                                      sal_Int16 eVertOri,
      84             :                                      sal_Int16 eHoriOri,
      85             :                                      SfxItemSet& rCSS1ItemSet,
      86             :                                      SvxCSS1PropertyInfo& rCSS1PropInfo,
      87             :                                      sal_Bool bHidden )
      88             : {
      89             :     // always on top of text.
      90             :     // but in invisible layer. <ConnectToLayout> will move the object
      91             :     // to the visible layer.
      92           0 :     pNewDrawObj->SetLayer( pDoc->GetInvisibleHeavenId() );
      93             : 
      94           0 :     SfxItemSet aFrmSet( pDoc->GetAttrPool(),
      95           0 :                         RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
      96           0 :     if( !IsNewDoc() )
      97           0 :         Reader::ResetFrmFmtAttrs( aFrmSet );
      98             : 
      99           0 :     sal_uInt16 nLeftSpace = 0, nRightSpace = 0, nUpperSpace = 0, nLowerSpace = 0;
     100           0 :     if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() )
     101             :     {
     102           0 :         Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() );
     103             :         aTwipSpc =
     104             :             Application::GetDefaultDevice()->PixelToLogic( aTwipSpc,
     105           0 :                                                 MapMode(MAP_TWIP) );
     106           0 :         nLeftSpace = nRightSpace = (sal_uInt16)aTwipSpc.Width();
     107           0 :         nUpperSpace = nLowerSpace = (sal_uInt16)aTwipSpc.Height();
     108             :     }
     109             : 
     110             :     // linken/rechten Rand setzen
     111             :     const SfxPoolItem *pItem;
     112           0 :     if( SFX_ITEM_SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, sal_True, &pItem ) )
     113             :     {
     114             :         // Ggf. den Erstzeilen-Einzug noch plaetten
     115           0 :         const SvxLRSpaceItem *pLRItem = (const SvxLRSpaceItem *)pItem;
     116           0 :         SvxLRSpaceItem aLRItem( *pLRItem );
     117           0 :         aLRItem.SetTxtFirstLineOfst( 0 );
     118           0 :         if( rCSS1PropInfo.bLeftMargin )
     119             :         {
     120           0 :             nLeftSpace = static_cast< sal_uInt16 >(aLRItem.GetLeft());
     121           0 :             rCSS1PropInfo.bLeftMargin = sal_False;
     122             :         }
     123           0 :         if( rCSS1PropInfo.bRightMargin )
     124             :         {
     125           0 :             nRightSpace = static_cast< sal_uInt16 >(aLRItem.GetRight());
     126           0 :             rCSS1PropInfo.bRightMargin = sal_False;
     127             :         }
     128           0 :         rCSS1ItemSet.ClearItem( RES_LR_SPACE );
     129             :     }
     130           0 :     if( nLeftSpace || nRightSpace )
     131             :     {
     132           0 :         SvxLRSpaceItem aLRItem( RES_LR_SPACE );
     133           0 :         aLRItem.SetLeft( nLeftSpace );
     134           0 :         aLRItem.SetRight( nRightSpace );
     135           0 :         aFrmSet.Put( aLRItem );
     136             :     }
     137             : 
     138             :     // oberen/unteren Rand setzen
     139           0 :     if( SFX_ITEM_SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, sal_True, &pItem ) )
     140             :     {
     141             :         // Ggf. den Erstzeilen-Einzug noch plaetten
     142           0 :         const SvxULSpaceItem *pULItem = (const SvxULSpaceItem *)pItem;
     143           0 :         if( rCSS1PropInfo.bTopMargin )
     144             :         {
     145           0 :             nUpperSpace = pULItem->GetUpper();
     146           0 :             rCSS1PropInfo.bTopMargin = sal_False;
     147             :         }
     148           0 :         if( rCSS1PropInfo.bBottomMargin )
     149             :         {
     150           0 :             nLowerSpace = pULItem->GetLower();
     151           0 :             rCSS1PropInfo.bBottomMargin = sal_False;
     152             :         }
     153             : 
     154           0 :         rCSS1ItemSet.ClearItem( RES_UL_SPACE );
     155             :     }
     156           0 :     if( nUpperSpace || nLowerSpace )
     157             :     {
     158           0 :         SvxULSpaceItem aULItem( RES_UL_SPACE );
     159           0 :         aULItem.SetUpper( nUpperSpace );
     160           0 :         aULItem.SetLower( nLowerSpace );
     161           0 :         aFrmSet.Put( aULItem );
     162             :     }
     163             : 
     164           0 :     SwFmtAnchor aAnchor( FLY_AS_CHAR );
     165           0 :     if( SVX_CSS1_POS_ABSOLUTE == rCSS1PropInfo.ePosition &&
     166           0 :         SVX_CSS1_LTYPE_TWIP == rCSS1PropInfo.eLeftType &&
     167           0 :         SVX_CSS1_LTYPE_TWIP == rCSS1PropInfo.eTopType )
     168             :     {
     169             :         const SwStartNode *pFlySttNd =
     170           0 :             pPam->GetPoint()->nNode.GetNode().FindFlyStartNode();
     171             : 
     172           0 :         if( pFlySttNd )
     173             :         {
     174           0 :             aAnchor.SetType( FLY_AT_FLY );
     175           0 :             SwPosition aPos( *pFlySttNd );
     176           0 :             aAnchor.SetAnchor( &aPos );
     177             :         }
     178             :         else
     179             :         {
     180           0 :             aAnchor.SetType( FLY_AT_PAGE );
     181             :         }
     182             :         // #i26791# - direct positioning for <SwDoc::Insert(..)>
     183             :         pNewDrawObj->SetRelativePos( Point(rCSS1PropInfo.nLeft + nLeftSpace,
     184           0 :                                            rCSS1PropInfo.nTop + nUpperSpace) );
     185           0 :         aFrmSet.Put( SwFmtSurround(SURROUND_THROUGHT) );
     186             :     }
     187           0 :     else if( SVX_ADJUST_LEFT == rCSS1PropInfo.eFloat ||
     188             :              text::HoriOrientation::LEFT == eHoriOri )
     189             :     {
     190           0 :         aAnchor.SetType( FLY_AT_PARA );
     191             :         aFrmSet.Put( SwFmtSurround(bHidden ? SURROUND_THROUGHT
     192           0 :                                              : SURROUND_RIGHT) );
     193             :         // #i26791# - direct positioning for <SwDoc::Insert(..)>
     194           0 :         pNewDrawObj->SetRelativePos( Point(nLeftSpace, nUpperSpace) );
     195             :     }
     196           0 :     else if( text::VertOrientation::NONE != eVertOri )
     197             :     {
     198           0 :         aFrmSet.Put( SwFmtVertOrient( 0, eVertOri ) );
     199             :     }
     200             : 
     201           0 :     if (FLY_AT_PAGE == aAnchor.GetAnchorId())
     202             :     {
     203           0 :         aAnchor.SetPageNum( 1 );
     204             :     }
     205           0 :     else if( FLY_AT_FLY != aAnchor.GetAnchorId() )
     206             :     {
     207           0 :         aAnchor.SetAnchor( pPam->GetPoint() );
     208             :     }
     209           0 :     aFrmSet.Put( aAnchor );
     210             : 
     211           0 :     pDoc->Insert( *pPam, *pNewDrawObj, &aFrmSet, NULL );
     212           0 : }
     213             : 
     214             : 
     215           0 : static void PutEEPoolItem( SfxItemSet &rEEItemSet,
     216             :                            const SfxPoolItem& rSwItem )
     217             : {
     218             : 
     219           0 :     sal_uInt16 nEEWhich = 0;
     220             : 
     221           0 :     switch( rSwItem.Which() )
     222             :     {
     223           0 :     case RES_CHRATR_COLOR:          nEEWhich = EE_CHAR_COLOR; break;
     224           0 :     case RES_CHRATR_CROSSEDOUT:     nEEWhich = EE_CHAR_STRIKEOUT; break;
     225           0 :     case RES_CHRATR_ESCAPEMENT:     nEEWhich = EE_CHAR_ESCAPEMENT; break;
     226           0 :     case RES_CHRATR_FONT:           nEEWhich = EE_CHAR_FONTINFO; break;
     227           0 :     case RES_CHRATR_CJK_FONT:       nEEWhich = EE_CHAR_FONTINFO_CJK; break;
     228           0 :     case RES_CHRATR_CTL_FONT:       nEEWhich = EE_CHAR_FONTINFO_CTL; break;
     229           0 :     case RES_CHRATR_FONTSIZE:       nEEWhich = EE_CHAR_FONTHEIGHT; break;
     230           0 :     case RES_CHRATR_CJK_FONTSIZE:   nEEWhich = EE_CHAR_FONTHEIGHT_CJK; break;
     231           0 :     case RES_CHRATR_CTL_FONTSIZE:   nEEWhich = EE_CHAR_FONTHEIGHT_CTL; break;
     232           0 :     case RES_CHRATR_KERNING:        nEEWhich = EE_CHAR_KERNING; break;
     233           0 :     case RES_CHRATR_POSTURE:        nEEWhich = EE_CHAR_ITALIC; break;
     234           0 :     case RES_CHRATR_CJK_POSTURE:    nEEWhich = EE_CHAR_ITALIC_CJK; break;
     235           0 :     case RES_CHRATR_CTL_POSTURE:    nEEWhich = EE_CHAR_ITALIC_CTL; break;
     236           0 :     case RES_CHRATR_UNDERLINE:      nEEWhich = EE_CHAR_UNDERLINE; break;
     237           0 :     case RES_CHRATR_WEIGHT:         nEEWhich = EE_CHAR_WEIGHT; break;
     238           0 :     case RES_CHRATR_CJK_WEIGHT:     nEEWhich = EE_CHAR_WEIGHT_CJK; break;
     239           0 :     case RES_CHRATR_CTL_WEIGHT:     nEEWhich = EE_CHAR_WEIGHT_CTL; break;
     240             :     case RES_BACKGROUND:
     241             :     case RES_CHRATR_BACKGROUND:
     242             :         {
     243           0 :             const SvxBrushItem& rBrushItem = (const SvxBrushItem&)rSwItem;
     244           0 :             rEEItemSet.Put( XFillStyleItem(XFILL_SOLID) );
     245             :             rEEItemSet.Put( XFillColorItem(aEmptyStr,
     246           0 :                             rBrushItem.GetColor()) );
     247             :         }
     248           0 :         break;
     249             :     }
     250             : 
     251           0 :     if( nEEWhich )
     252             :     {
     253           0 :         SfxPoolItem *pEEItem = rSwItem.Clone();
     254           0 :         pEEItem->SetWhich( nEEWhich );
     255           0 :         rEEItemSet.Put( *pEEItem );
     256           0 :         delete pEEItem;
     257             :     }
     258           0 : }
     259             : 
     260           0 : void SwHTMLParser::NewMarquee( HTMLTable *pCurTable )
     261             : {
     262             : 
     263             :     OSL_ENSURE( !pMarquee, "Marquee in Marquee???" );
     264           0 :     aContents.Erase();
     265             : 
     266           0 :     String aId, aStyle, aClass;
     267             : 
     268           0 :     long nWidth=0, nHeight=0;
     269           0 :     sal_Bool bPrcWidth = sal_False, bDirection = sal_False, bBGColor = sal_False;
     270           0 :     Size aSpace( 0, 0 );
     271           0 :     sal_Int16 eVertOri = text::VertOrientation::TOP;
     272           0 :     sal_Int16 eHoriOri = text::HoriOrientation::NONE;
     273           0 :     SdrTextAniKind eAniKind = SDRTEXTANI_SCROLL;
     274           0 :     SdrTextAniDirection eAniDir = SDRTEXTANI_LEFT;
     275           0 :     sal_uInt16 nCount = 0, nDelay = 60;
     276           0 :     sal_Int16 nAmount = -6;
     277           0 :     Color aBGColor;
     278             : 
     279           0 :     const HTMLOptions& rHTMLOptions = GetOptions();
     280           0 :     for (size_t i = 0, n = rHTMLOptions.size(); i < n; ++i)
     281             :     {
     282           0 :         const HTMLOption& rOption = rHTMLOptions[i];
     283           0 :         switch( rOption.GetToken() )
     284             :         {
     285             :             case HTML_O_ID:
     286           0 :                 aId = rOption.GetString();
     287           0 :                 break;
     288             :             case HTML_O_STYLE:
     289           0 :                 aStyle = rOption.GetString();
     290           0 :                 break;
     291             :             case HTML_O_CLASS:
     292           0 :                 aClass = rOption.GetString();
     293           0 :                 break;
     294             : 
     295             :             case HTML_O_BEHAVIOR:
     296             :                 eAniKind =
     297             :                     (SdrTextAniKind)rOption.GetEnum( aHTMLMarqBehaviorTable,
     298           0 :                                                       static_cast< sal_uInt16 >(eAniKind) );
     299           0 :                 break;
     300             : 
     301             :             case HTML_O_BGCOLOR:
     302           0 :                 rOption.GetColor( aBGColor );
     303           0 :                 bBGColor = sal_True;
     304           0 :                 break;
     305             : 
     306             :             case HTML_O_DIRECTION:
     307             :                 eAniDir =
     308             :                     (SdrTextAniDirection)rOption.GetEnum( aHTMLMarqDirectionTable,
     309           0 :                                                       static_cast< sal_uInt16 >(eAniDir) );
     310           0 :                 bDirection = sal_True;
     311           0 :                 break;
     312             : 
     313             :             case HTML_O_LOOP:
     314           0 :                 if( rOption.GetString().
     315           0 :                         EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_LOOP_infinite) )
     316             :                 {
     317           0 :                     nCount = 0;
     318             :                 }
     319             :                 else
     320             :                 {
     321           0 :                     sal_uInt32 nLoop = rOption.GetSNumber();
     322           0 :                     nCount = (sal_uInt16)(nLoop>0 ? nLoop : 0 );
     323             :                 }
     324           0 :                 break;
     325             : 
     326             :             case HTML_O_SCROLLAMOUNT:
     327           0 :                 nAmount = -((sal_Int16)rOption.GetNumber());
     328           0 :                 break;
     329             : 
     330             :             case HTML_O_SCROLLDELAY:
     331           0 :                 nDelay = (sal_uInt16)rOption.GetNumber();
     332           0 :                 break;
     333             : 
     334             :             case HTML_O_WIDTH:
     335             :                 // erstmal nur als Pixelwerte merken!
     336           0 :                 nWidth = rOption.GetNumber();
     337           0 :                 bPrcWidth = rOption.GetString().Search('%') != STRING_NOTFOUND;
     338           0 :                 if( bPrcWidth && nWidth>100 )
     339           0 :                     nWidth = 100;
     340           0 :                 break;
     341             : 
     342             :             case HTML_O_HEIGHT:
     343             :                 // erstmal nur als Pixelwerte merken!
     344           0 :                 nHeight = rOption.GetNumber();
     345           0 :                 if( rOption.GetString().Search('%') != STRING_NOTFOUND )
     346           0 :                     nHeight = 0;
     347           0 :                 break;
     348             : 
     349             :             case HTML_O_HSPACE:
     350             :                 // erstmal nur als Pixelwerte merken!
     351           0 :                 aSpace.Height() = rOption.GetNumber();
     352           0 :                 break;
     353             : 
     354             :             case HTML_O_VSPACE:
     355             :                 // erstmal nur als Pixelwerte merken!
     356           0 :                 aSpace.Width() = rOption.GetNumber();
     357           0 :                 break;
     358             : 
     359             :             case HTML_O_ALIGN:
     360             :                 eVertOri =
     361             :                     rOption.GetEnum( aHTMLImgVAlignTable,
     362           0 :                                                     text::VertOrientation::TOP );
     363             :                 eHoriOri =
     364             :                     rOption.GetEnum( aHTMLImgHAlignTable,
     365           0 :                                                     text::HoriOrientation::NONE );
     366           0 :                 break;
     367             :         }
     368             :     }
     369             : 
     370             :     // Ein DrawTxtobj anlegen
     371             :     // #i52858# - method name changed
     372           0 :     SdrModel* pModel = pDoc->GetOrCreateDrawModel();
     373             : 
     374           0 :     SdrPage* pPg = pModel->GetPage( 0 );
     375             :     pMarquee = SdrObjFactory::MakeNewObject( SdrInventor,
     376           0 :                                              OBJ_TEXT, pPg, pModel );
     377           0 :     if( !pMarquee )
     378           0 :         return;
     379             : 
     380           0 :     pPg->InsertObject( pMarquee );
     381             : 
     382           0 :     if( aId.Len() )
     383           0 :         InsertBookmark( aId );
     384             : 
     385             :     // (Nur) Alternate leueft per Default von links nach rechts
     386           0 :     if( SDRTEXTANI_ALTERNATE==eAniKind && !bDirection )
     387           0 :         eAniDir = SDRTEXTANI_RIGHT;
     388             : 
     389             :     // die fuer das Scrollen benoetigten Attribute umsetzen
     390             :     sal_uInt16 aWhichMap[7] =   { XATTR_FILL_FIRST,   XATTR_FILL_LAST,
     391             :                               SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
     392             :                               EE_CHAR_START,      EE_CHAR_END,
     393           0 :                               0 };
     394           0 :     SfxItemSet aItemSet( pModel->GetItemPool(), aWhichMap );
     395           0 :     aItemSet.Put( SdrTextAutoGrowWidthItem( sal_False ) );
     396           0 :     aItemSet.Put( SdrTextAutoGrowHeightItem( sal_True ) );
     397           0 :     aItemSet.Put( SdrTextAniKindItem( eAniKind ) );
     398           0 :     aItemSet.Put( SdrTextAniDirectionItem( eAniDir ) );
     399           0 :     aItemSet.Put( SdrTextAniCountItem( nCount ) );
     400           0 :     aItemSet.Put( SdrTextAniDelayItem( nDelay ) );
     401           0 :     aItemSet.Put( SdrTextAniAmountItem( nAmount ) );
     402           0 :     if( SDRTEXTANI_ALTERNATE==eAniKind )
     403             :     {
     404             :         // (Nur) Alternate startet und stoppt per default Inside
     405           0 :         aItemSet.Put( SdrTextAniStartInsideItem(sal_True) );
     406           0 :         aItemSet.Put( SdrTextAniStopInsideItem(sal_True) );
     407           0 :         if( SDRTEXTANI_LEFT==eAniDir )
     408           0 :             aItemSet.Put( SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT) );
     409             :     }
     410             : 
     411             :     // die Default-Farbe (aus der Standard-Vorlage) setzen, damit ueberhaupt
     412             :     // eine sinnvolle Farbe gesetzt ist.
     413             :     const Color& rDfltColor =
     414           0 :         pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD )
     415           0 :             ->GetColor().GetValue();
     416           0 :     aItemSet.Put( SvxColorItem( rDfltColor, EE_CHAR_COLOR ) );
     417             : 
     418             :     // Die Attribute der aktuellen Absatzvorlage setzen
     419             :     sal_uInt16 nWhichIds[] =
     420             :     {
     421             :         RES_CHRATR_COLOR,   RES_CHRATR_CROSSEDOUT, RES_CHRATR_ESCAPEMENT,
     422             :         RES_CHRATR_FONT,    RES_CHRATR_FONTSIZE,   RES_CHRATR_KERNING,
     423             :         RES_CHRATR_POSTURE, RES_CHRATR_UNDERLINE,  RES_CHRATR_WEIGHT,
     424             :         RES_CHRATR_BACKGROUND,
     425             :         RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
     426             :         RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT,
     427             :         RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE,
     428             :         RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT,
     429             :         0
     430           0 :     };
     431             :     SwTxtNode const*const pTxtNd =
     432           0 :         pPam->GetPoint()->nNode.GetNode().GetTxtNode();
     433           0 :     if( pTxtNd )
     434             :     {
     435           0 :         const SfxItemSet& rItemSet = pTxtNd->GetAnyFmtColl().GetAttrSet();
     436             :         const SfxPoolItem *pItem;
     437           0 :         for( sal_uInt16 i=0; nWhichIds[i]; i++ )
     438             :         {
     439           0 :             if( SFX_ITEM_SET == rItemSet.GetItemState( nWhichIds[i], sal_True, &pItem ) )
     440           0 :                 PutEEPoolItem( aItemSet, *pItem );
     441             :         }
     442             :     }
     443             : 
     444             :     // die Attribute der Umgebung am Draw-Objekt setzen
     445           0 :     _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
     446           0 :     for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
     447             :          nCnt--; ++pTbl )
     448             :     {
     449           0 :         _HTMLAttr *pAttr = *pTbl;
     450           0 :         if( pAttr )
     451           0 :             PutEEPoolItem( aItemSet, pAttr->GetItem() );
     452             :     }
     453             : 
     454           0 :     if( bBGColor )
     455             :     {
     456           0 :         aItemSet.Put( XFillStyleItem(XFILL_SOLID) );
     457           0 :         aItemSet.Put( XFillColorItem(aEmptyStr, aBGColor) );
     458             :     }
     459             : 
     460             :     // Styles parsen (funktioniert hier nur fuer Attribute, die auch
     461             :     // am Zeichen-Objekt gesetzt werden koennen)
     462           0 :     SfxItemSet aStyleItemSet( pDoc->GetAttrPool(),
     463           0 :                               pCSS1Parser->GetWhichMap() );
     464           0 :     SvxCSS1PropertyInfo aPropInfo;
     465           0 :     if( HasStyleOptions( aStyle, aId, aClass )  &&
     466           0 :         ParseStyleOptions( aStyle, aId, aClass, aStyleItemSet, aPropInfo ) )
     467             :     {
     468           0 :         SfxItemIter aIter( aStyleItemSet );
     469             : 
     470           0 :         const SfxPoolItem *pItem = aIter.FirstItem();
     471           0 :         while( pItem )
     472             :         {
     473           0 :             PutEEPoolItem( aItemSet, *pItem );
     474           0 :             pItem = aIter.NextItem();
     475           0 :         }
     476             :     }
     477             : 
     478             :     // jetzt noch die Groesse setzen
     479           0 :     Size aTwipSz( bPrcWidth ? 0 : nWidth, nHeight );
     480           0 :     if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() )
     481             :     {
     482             :         aTwipSz = Application::GetDefaultDevice()
     483           0 :                     ->PixelToLogic( aTwipSz, MapMode( MAP_TWIP ) );
     484             :     }
     485             : 
     486           0 :     if( SVX_CSS1_LTYPE_TWIP== aPropInfo.eWidthType )
     487             :     {
     488           0 :         aTwipSz.Width() = aPropInfo.nWidth;
     489           0 :         nWidth = 1; // != 0;
     490           0 :         bPrcWidth = sal_False;
     491             :     }
     492           0 :     if( SVX_CSS1_LTYPE_TWIP== aPropInfo.eHeightType )
     493           0 :         aTwipSz.Height() = aPropInfo.nHeight;
     494             : 
     495           0 :     bFixMarqueeWidth = sal_False;
     496           0 :     if( !nWidth || bPrcWidth )
     497             :     {
     498           0 :         if( pTable )
     499             :         {
     500           0 :             if( !pCurTable )
     501             :             {
     502             :                 // Die Laufschrift steht in einer Tabelle, aber nicht
     503             :                 // in einer Zelle. Da jetzt keine vernuenftige Zuordung
     504             :                 // zu einer Zelle moeglich ist, passen wir hir die
     505             :                 // Breite dem Inhalt der Laufschrift an.
     506           0 :                 bFixMarqueeWidth = sal_True;
     507             :             }
     508           0 :             else if( !nWidth )
     509             :             {
     510             :                 // Da wir wissen, in welcher Zelle die Laufschrift ist,
     511             :                 // koennen wir die Breite auch anpassen. Keine Breitenangabe
     512             :                 // wird wie 100% behandelt.
     513           0 :                 nWidth = 100;
     514           0 :                 bPrcWidth = sal_True;
     515             :             }
     516           0 :             aTwipSz.Width() = MINLAY;
     517             :         }
     518             :         else
     519             :         {
     520           0 :             long nBrowseWidth = GetCurrentBrowseWidth();
     521           0 :             aTwipSz.Width() = !nWidth ? nBrowseWidth
     522           0 :                                       : (nWidth*nBrowseWidth) / 100;
     523             :         }
     524             :     }
     525             : 
     526             :     // Die Hoehe ist nur eine Mindest-Hoehe
     527           0 :     if( aTwipSz.Height() < MINFLY )
     528           0 :         aTwipSz.Height() = MINFLY;
     529           0 :     aItemSet.Put( SdrTextMinFrameHeightItem( aTwipSz.Height() ) );
     530             : 
     531           0 :     pMarquee->SetMergedItemSetAndBroadcast(aItemSet);
     532             : 
     533           0 :     if( aTwipSz.Width() < MINFLY )
     534           0 :         aTwipSz.Width() = MINFLY;
     535           0 :     pMarquee->SetLogicRect( Rectangle( 0, 0, aTwipSz.Width(), aTwipSz.Height() ) );
     536             : 
     537             :     // und das Objekt in das Dok einfuegen
     538             :     InsertDrawObject( pMarquee, aSpace, eVertOri, eHoriOri, aStyleItemSet,
     539           0 :                       aPropInfo );
     540             : 
     541             :     // Das Zeichen-Objekt der Tabelle bekanntmachen. Ist ein bisserl
     542             :     // umstaendlich, weil noch ueber den Parser gegangen wird, obwohl die
     543             :     // Tabelle bekannt ist, aber anderenfalls muesste man die Tabelle
     544             :     // oeffentlich machen, und das ist auch nicht schoen. Das globale
     545             :     // pTable kann uebrigens auch nicht verwendet werden, denn die
     546             :     // Laufschrift kann sich auch mal in einer Sub-Tabelle befinden.
     547           0 :     if( pCurTable && bPrcWidth)
     548           0 :         RegisterDrawObjectToTable( pCurTable, pMarquee, (sal_uInt8)nWidth );
     549             : }
     550             : 
     551           0 : void SwHTMLParser::EndMarquee()
     552             : {
     553             :     OSL_ENSURE( pMarquee && OBJ_TEXT==pMarquee->GetObjIdentifier(),
     554             :             "kein Marquee oder falscher Typ" );
     555             : 
     556           0 :     if( bFixMarqueeWidth )
     557             :     {
     558             :         // Da es keine fixe Hoehe gibt, das Text-Objekt erstmal breiter
     559             :         // als den Text machen, damit nicht umgebrochen wird.
     560           0 :         const Rectangle& rOldRect = pMarquee->GetLogicRect();
     561             :         pMarquee->SetLogicRect( Rectangle( rOldRect.TopLeft(),
     562           0 :                                            Size( USHRT_MAX, 240 ) ) );
     563             :     }
     564             : 
     565             :     // den gesammelten Text einfuegen
     566           0 :     ((SdrTextObj*)pMarquee)->SetText( aContents );
     567           0 :     pMarquee->SetMergedItemSetAndBroadcast( pMarquee->GetMergedItemSet() );
     568             : 
     569           0 :     if( bFixMarqueeWidth )
     570             :     {
     571             :         // die Groesse dem Text anpassen.
     572           0 :         ((SdrTextObj*)pMarquee)->FitFrameToTextSize();
     573             :     }
     574             : 
     575           0 :     aContents.Erase();
     576           0 :     pMarquee = 0;
     577           0 : }
     578             : 
     579           0 : void SwHTMLParser::InsertMarqueeText()
     580             : {
     581             :     OSL_ENSURE( pMarquee && OBJ_TEXT==pMarquee->GetObjIdentifier(),
     582             :             "kein Marquee oder falscher Typ" );
     583             : 
     584             :     // das akteulle Textstueck an den Text anhaengen
     585           0 :     aContents += aToken;
     586           0 : }
     587             : 
     588           0 : void SwHTMLParser::ResizeDrawObject( SdrObject* pObj, SwTwips nWidth )
     589             : {
     590             :     OSL_ENSURE( OBJ_TEXT==pObj->GetObjIdentifier(),
     591             :             "kein Marquee oder falscher Typ" );
     592             : 
     593           0 :     if( OBJ_TEXT!=pObj->GetObjIdentifier() )
     594           0 :         return;
     595             : 
     596             :     // die alte Groesse
     597           0 :     const Rectangle& rOldRect = pObj->GetLogicRect();
     598           0 :     Size aNewSz( nWidth, rOldRect.GetSize().Height() );
     599           0 :     pObj->SetLogicRect( Rectangle( rOldRect.TopLeft(), aNewSz ) );
     600             : }
     601             : 
     602             : 
     603           0 : const SdrObject *SwHTMLWriter::GetMarqueeTextObj( const SwDrawFrmFmt& rFmt )
     604             : {
     605           0 :     const SdrObject* pObj = rFmt.FindSdrObject();
     606           0 :     return (pObj && ::IsMarqueeTextObj( *pObj )) ? pObj : 0;
     607             : }
     608             : 
     609           0 : void SwHTMLWriter::GetEEAttrsFromDrwObj( SfxItemSet& rItemSet,
     610             :                                          const SdrObject *pObj,
     611             :                                          sal_Bool bSetDefaults )
     612             : {
     613             :     // die Edit script::Engine-Attribute aus dem Objekt holen
     614           0 :     SfxItemSet rObjItemSet = pObj->GetMergedItemSet();
     615             : 
     616             :     // ueber die Edit script::Engine-Attribute iterieren und die Attribute
     617             :     // in SW-Attrs wandeln bzw. default setzen
     618           0 :     SfxWhichIter aIter( rObjItemSet );
     619           0 :     sal_uInt16 nEEWhich = aIter.FirstWhich();
     620           0 :     while( nEEWhich )
     621             :     {
     622             :         const SfxPoolItem *pEEItem;
     623           0 :         sal_Bool bSet = SFX_ITEM_SET == rObjItemSet.GetItemState( nEEWhich, sal_False,
     624           0 :                                                               &pEEItem );
     625             : 
     626           0 :         if( bSet || bSetDefaults )
     627             :         {
     628           0 :             sal_uInt16 nSwWhich = 0;
     629           0 :             switch( nEEWhich )
     630             :             {
     631           0 :             case EE_CHAR_COLOR:         nSwWhich = RES_CHRATR_COLOR;        break;
     632           0 :             case EE_CHAR_STRIKEOUT:     nSwWhich = RES_CHRATR_CROSSEDOUT;   break;
     633           0 :             case EE_CHAR_ESCAPEMENT:    nSwWhich = RES_CHRATR_ESCAPEMENT;   break;
     634           0 :             case EE_CHAR_FONTINFO:      nSwWhich = RES_CHRATR_FONT;         break;
     635           0 :             case EE_CHAR_FONTINFO_CJK:  nSwWhich = RES_CHRATR_CJK_FONT;     break;
     636           0 :             case EE_CHAR_FONTINFO_CTL:  nSwWhich = RES_CHRATR_CTL_FONT;     break;
     637           0 :             case EE_CHAR_FONTHEIGHT:    nSwWhich = RES_CHRATR_FONTSIZE;     break;
     638           0 :             case EE_CHAR_FONTHEIGHT_CJK:nSwWhich = RES_CHRATR_CJK_FONTSIZE; break;
     639           0 :             case EE_CHAR_FONTHEIGHT_CTL:nSwWhich = RES_CHRATR_CTL_FONTSIZE; break;
     640           0 :             case EE_CHAR_KERNING:       nSwWhich = RES_CHRATR_KERNING;      break;
     641           0 :             case EE_CHAR_ITALIC:        nSwWhich = RES_CHRATR_POSTURE;      break;
     642           0 :             case EE_CHAR_ITALIC_CJK:    nSwWhich = RES_CHRATR_CJK_POSTURE;  break;
     643           0 :             case EE_CHAR_ITALIC_CTL:    nSwWhich = RES_CHRATR_CTL_POSTURE;  break;
     644           0 :             case EE_CHAR_UNDERLINE:     nSwWhich = RES_CHRATR_UNDERLINE;    break;
     645           0 :             case EE_CHAR_WEIGHT:        nSwWhich = RES_CHRATR_WEIGHT;       break;
     646           0 :             case EE_CHAR_WEIGHT_CJK:    nSwWhich = RES_CHRATR_CJK_WEIGHT;   break;
     647           0 :             case EE_CHAR_WEIGHT_CTL:    nSwWhich = RES_CHRATR_CTL_WEIGHT;   break;
     648             :             }
     649             : 
     650           0 :             if( nSwWhich )
     651             :             {
     652             :                 // wenn das Item nicht gesetzt ist nehmen wir ggf. das
     653             :                 // Default-Item
     654           0 :                 if( !bSet )
     655           0 :                     pEEItem = &rObjItemSet.GetPool()->GetDefaultItem(nEEWhich);
     656             : 
     657             :                 // jetzt Clonen wir das Item mit der Which-Id des Writers
     658           0 :                 SfxPoolItem *pSwItem = pEEItem->Clone();
     659           0 :                 pSwItem->SetWhich( nSwWhich );
     660           0 :                 rItemSet.Put( *pSwItem );
     661           0 :                 delete pSwItem;
     662             :             }
     663             :         }
     664             : 
     665           0 :         nEEWhich = aIter.NextWhich();
     666           0 :     }
     667           0 : }
     668             : 
     669             : 
     670           0 : Writer& OutHTML_DrawFrmFmtAsMarquee( Writer& rWrt,
     671             :                                      const SwDrawFrmFmt& rFmt,
     672             :                                      const SdrObject& rSdrObject )
     673             : {
     674           0 :     SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
     675             : 
     676             :     OSL_ENSURE( rWrt.pDoc->GetDrawModel(), "Da gibt's ein Draw-Obj ohne ein Draw-Model zu haben?" );
     677           0 :     const SdrTextObj *pTextObj = (const SdrTextObj *)&rSdrObject;
     678             : 
     679             :     // Gibt es ueberhaupt auszugebenden Text
     680             :     const OutlinerParaObject *pOutlinerParaObj =
     681           0 :         pTextObj->GetOutlinerParaObject();
     682           0 :     if( !pOutlinerParaObj )
     683           0 :         return rWrt;
     684             : 
     685           0 :     OStringBuffer sOut;
     686           0 :     sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_marquee);
     687             : 
     688             :     // Die Attribute des Objektd holen
     689           0 :     const SfxItemSet& rItemSet = pTextObj->GetMergedItemSet();
     690             : 
     691             :     // BEHAVIOUR
     692           0 :     SdrTextAniKind eAniKind = pTextObj->GetTextAniKind();
     693             :     OSL_ENSURE( SDRTEXTANI_SCROLL==eAniKind ||
     694             :             SDRTEXTANI_ALTERNATE==eAniKind ||
     695             :             SDRTEXTANI_SLIDE==eAniKind,
     696             :             "Text-Draw-Objekt nicht fuer Marquee geeignet" );
     697             : 
     698           0 :     const sal_Char *pStr = 0;
     699           0 :     switch( eAniKind )
     700             :     {
     701           0 :     case SDRTEXTANI_SCROLL:     pStr = OOO_STRING_SVTOOLS_HTML_BEHAV_scroll;        break;
     702           0 :     case SDRTEXTANI_SLIDE:      pStr = OOO_STRING_SVTOOLS_HTML_BEHAV_slide;     break;
     703           0 :     case SDRTEXTANI_ALTERNATE:  pStr = OOO_STRING_SVTOOLS_HTML_BEHAV_alternate; break;
     704             :     default:
     705             :         ;
     706             :     }
     707             : 
     708           0 :     if( pStr )
     709             :     {
     710           0 :         sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_behavior).
     711           0 :             append('=').append(pStr);
     712             :     }
     713             : 
     714             :     // DIRECTION
     715           0 :     pStr = 0;
     716           0 :     SdrTextAniDirection eAniDir = pTextObj->GetTextAniDirection();
     717           0 :     switch( eAniDir )
     718             :     {
     719           0 :     case SDRTEXTANI_LEFT:       pStr = OOO_STRING_SVTOOLS_HTML_AL_left;     break;
     720           0 :     case SDRTEXTANI_RIGHT:      pStr = OOO_STRING_SVTOOLS_HTML_AL_right;        break;
     721             :     default:
     722             :         ;
     723             :     }
     724             : 
     725           0 :     if( pStr )
     726             :     {
     727           0 :         sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_direction).
     728           0 :             append('=').append(pStr);
     729             :     }
     730             : 
     731             :     // LOOP
     732             :     sal_Int32 nCount =
     733           0 :         ((const SdrTextAniCountItem&)rItemSet.Get( SDRATTR_TEXT_ANICOUNT ))
     734           0 :                                              .GetValue();
     735           0 :     if( 0==nCount )
     736           0 :         nCount = SDRTEXTANI_SLIDE==eAniKind ? 1 : -1;
     737           0 :     sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_loop).append('=').
     738           0 :         append(nCount);
     739             : 
     740             :     // SCROLLDELAY
     741             :     sal_uInt16 nDelay =
     742           0 :         ((const SdrTextAniDelayItem&)rItemSet.Get( SDRATTR_TEXT_ANIDELAY ))
     743           0 :                                             .GetValue();
     744           0 :     sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_scrolldelay).
     745           0 :         append('=').append(static_cast<sal_Int32>(nDelay));
     746             : 
     747             :     // SCROLLAMOUNT
     748             :     sal_Int16 nAmount =
     749           0 :         ((const SdrTextAniAmountItem&)rItemSet.Get( SDRATTR_TEXT_ANIAMOUNT ))
     750           0 :                                              .GetValue();
     751           0 :     if( nAmount < 0 )
     752             :     {
     753           0 :         nAmount = -nAmount;
     754             :     }
     755           0 :     else if( nAmount && Application::GetDefaultDevice() )
     756             :     {
     757             :         nAmount = (sal_uInt16)(Application::GetDefaultDevice()
     758             :                             ->LogicToPixel( Size(nAmount,0),
     759           0 :                                             MapMode(MAP_TWIP) ).Width());
     760             :     }
     761           0 :     if( nAmount )
     762             :     {
     763           0 :         sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_scrollamount).
     764           0 :             append('=').append(static_cast<sal_Int32>(nAmount));
     765             :     }
     766             : 
     767           0 :     Size aTwipSz( pTextObj->GetLogicRect().GetSize() );
     768           0 :     if( pTextObj->IsAutoGrowWidth() )
     769           0 :         aTwipSz.Width() = 0;
     770             :     // Die Hoehe ist bei MS eine Mindesthoehe, also geben wir auch die
     771             :     // Mindestheoehe aus, wenn es sie gibt. Da eine Mindesthoehe MINFLY
     772             :     // mit hoher Wahrscheinlichkeit vom Import kommt, wird sie nicht mit
     773             :     // ausgegeben. Falsch machen kann man da nichst, denn jeder Font ist
     774             :     // hoeher.
     775           0 :     if( pTextObj->IsAutoGrowHeight() )
     776             :     {
     777           0 :         aTwipSz.Height() = pTextObj->GetMinTextFrameHeight();
     778           0 :         if( MINFLY==aTwipSz.Height() )
     779           0 :             aTwipSz.Height() = 0;
     780             :     }
     781             : 
     782           0 :     if( (aTwipSz.Width() || aTwipSz.Height()) &&
     783           0 :         Application::GetDefaultDevice() )
     784             :     {
     785             :         Size aPixelSz =
     786             :             Application::GetDefaultDevice()->LogicToPixel( aTwipSz,
     787           0 :                                                 MapMode(MAP_TWIP) );
     788           0 :         if( !aPixelSz.Width() && aTwipSz.Width() )
     789           0 :             aPixelSz.Width() = 1;
     790           0 :         if( !aPixelSz.Height() && aTwipSz.Height() )
     791           0 :             aPixelSz.Height() = 1;
     792             : 
     793           0 :         if( aPixelSz.Width() )
     794             :         {
     795           0 :             sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_width).
     796           0 :                 append('=').append(static_cast<sal_Int32>(aPixelSz.Width()));
     797             :         }
     798             : 
     799           0 :         if( aPixelSz.Height() )
     800             :         {
     801           0 :             sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height).
     802           0 :                 append('=').append(static_cast<sal_Int32>(aPixelSz.Height()));
     803             :         }
     804             :     }
     805             : 
     806             :     // BGCOLOR
     807             :     XFillStyle eFillStyle =
     808           0 :         ((const XFillStyleItem&)rItemSet.Get(XATTR_FILLSTYLE)).GetValue();
     809           0 :     if( XFILL_SOLID==eFillStyle )
     810             :     {
     811             :         const Color& rFillColor =
     812           0 :             ((const XFillColorItem&)rItemSet.Get(XATTR_FILLCOLOR)).GetColorValue();
     813             : 
     814           0 :         sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor).append('=');
     815           0 :         rWrt.Strm() << sOut.makeStringAndClear().getStr();
     816           0 :         HTMLOutFuncs::Out_Color( rWrt.Strm(), rFillColor, rHTMLWrt.eDestEnc );
     817             :     }
     818             : 
     819           0 :     if (!sOut.isEmpty())
     820           0 :         rWrt.Strm() << sOut.makeStringAndClear().getStr();
     821             : 
     822             :     // und nun noch ALIGN, HSPACE und VSPACE
     823           0 :     sal_uInt32 nFrmFlags = HTML_FRMOPTS_MARQUEE;
     824           0 :     if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) )
     825           0 :         nFrmFlags |= HTML_FRMOPTS_MARQUEE_CSS1;
     826           0 :     OString aEndTags = rHTMLWrt.OutFrmFmtOptions( rFmt, aEmptyStr, nFrmFlags );
     827           0 :     if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) )
     828           0 :         rHTMLWrt.OutCSS1_FrmFmtOptions( rFmt, nFrmFlags, &rSdrObject );
     829             : 
     830             : 
     831           0 :     rWrt.Strm() << '>';
     832             : 
     833             :     // Was jetzt kommt ist das Gegenstueck zu SdrTextObjectt::SetText()
     834           0 :     Outliner aOutliner(0, OUTLINERMODE_TEXTOBJECT);
     835           0 :     aOutliner.SetUpdateMode( sal_False );
     836           0 :     aOutliner.SetText( *pOutlinerParaObj );
     837             :     String aText( aOutliner.GetText( aOutliner.GetParagraph(0),
     838           0 :                                      aOutliner.GetParagraphCount() ) );
     839           0 :     HTMLOutFuncs::Out_String( rWrt.Strm(), aText,
     840           0 :                                 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
     841             : 
     842           0 :     HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_marquee, sal_False );
     843             : 
     844           0 :     if( !aEndTags.isEmpty() )
     845           0 :         rWrt.Strm() << aEndTags.getStr();
     846             : 
     847           0 :     return rWrt;
     848          99 : }
     849             : 
     850             : 
     851             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10