LCOV - code coverage report
Current view: top level - sc/source/core/tool - ddelink.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 71 115 61.7 %
Date: 2015-06-13 12:38:46 Functions: 12 18 66.7 %
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 <comphelper/string.hxx>
      21             : #include <osl/thread.h>
      22             : #include <sfx2/linkmgr.hxx>
      23             : #include <sfx2/bindings.hxx>
      24             : #include <svl/zforlist.hxx>
      25             : #include <svl/sharedstringpool.hxx>
      26             : 
      27             : #include "ddelink.hxx"
      28             : #include "brdcst.hxx"
      29             : #include "document.hxx"
      30             : #include "scmatrix.hxx"
      31             : #include "patattr.hxx"
      32             : #include "rechead.hxx"
      33             : #include "rangeseq.hxx"
      34             : #include "sc.hrc"
      35             : #include "hints.hxx"
      36             : 
      37          88 : TYPEINIT2(ScDdeLink,::sfx2::SvBaseLink,SfxBroadcaster);
      38             : 
      39             : #define DDE_TXT_ENCODING    osl_getThreadTextEncoding()
      40             : 
      41             : bool ScDdeLink::bIsInUpdate = false;
      42             : 
      43           3 : ScDdeLink::ScDdeLink( ScDocument* pD, const OUString& rA, const OUString& rT, const OUString& rI,
      44             :                         sal_uInt8 nM ) :
      45             :     ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS,SotClipboardFormatId::STRING),
      46             :     pDoc( pD ),
      47             :     aAppl( rA ),
      48             :     aTopic( rT ),
      49             :     aItem( rI ),
      50             :     nMode( nM ),
      51             :     bNeedUpdate( false ),
      52           3 :     pResult( NULL )
      53             : {
      54           3 : }
      55             : 
      56           6 : ScDdeLink::~ScDdeLink()
      57             : {
      58             :     // Verbindung aufheben
      59             : 
      60             :     // pResult is refcounted
      61           6 : }
      62             : 
      63           0 : ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
      64             :     ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS,SotClipboardFormatId::STRING),
      65             :     pDoc    ( pD ),
      66             :     aAppl   ( rOther.aAppl ),
      67             :     aTopic  ( rOther.aTopic ),
      68             :     aItem   ( rOther.aItem ),
      69             :     nMode   ( rOther.nMode ),
      70             :     bNeedUpdate( false ),
      71           0 :     pResult ( NULL )
      72             : {
      73           0 :     if (rOther.pResult)
      74           0 :         pResult = rOther.pResult->Clone();
      75           0 : }
      76             : 
      77           0 : ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
      78             :     ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS,SotClipboardFormatId::STRING),
      79             :     pDoc( pD ),
      80             :     bNeedUpdate( false ),
      81           0 :     pResult( NULL )
      82             : {
      83           0 :     rHdr.StartEntry();
      84             : 
      85           0 :     rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
      86           0 :     aAppl = rStream.ReadUniOrByteString( eCharSet );
      87           0 :     aTopic = rStream.ReadUniOrByteString( eCharSet );
      88           0 :     aItem = rStream.ReadUniOrByteString( eCharSet );
      89             : 
      90             :     bool bHasValue;
      91           0 :     rStream.ReadCharAsBool( bHasValue );
      92           0 :     if ( bHasValue )
      93           0 :         pResult = new ScMatrix(0, 0);
      94             : 
      95           0 :     if (rHdr.BytesLeft())       // neu in 388b und der 364w (RealTime-Client) Version
      96           0 :         rStream.ReadUChar( nMode );
      97             :     else
      98           0 :         nMode = SC_DDE_DEFAULT;
      99             : 
     100           0 :     rHdr.EndEntry();
     101           0 : }
     102             : 
     103           0 : void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
     104             : {
     105           0 :     rHdr.StartEntry();
     106             : 
     107           0 :     rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
     108           0 :     rStream.WriteUniOrByteString( aAppl, eCharSet );
     109           0 :     rStream.WriteUniOrByteString( aTopic, eCharSet );
     110           0 :     rStream.WriteUniOrByteString( aItem, eCharSet );
     111             : 
     112           0 :     bool bHasValue = ( pResult != 0 );
     113           0 :     rStream.WriteBool( bHasValue );
     114             : 
     115           0 :     if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )      // nicht bei 4.0 Export
     116           0 :         rStream.WriteUChar( nMode );                                   // seit 388b
     117             : 
     118             :     //  Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
     119             :     //  (aus ScDocument::SaveDdeLinks)
     120             : 
     121           0 :     rHdr.EndEntry();
     122           0 : }
     123             : 
     124           5 : sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged(
     125             :     const OUString& rMimeType, const ::com::sun::star::uno::Any & rValue )
     126             : {
     127             :     //  wir koennen nur Strings...
     128           5 :     if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
     129           0 :         return SUCCESS;
     130             : 
     131           5 :     OUString aLinkStr;
     132           5 :     ScByteSequenceToString::GetString( aLinkStr, rValue, DDE_TXT_ENCODING );
     133           5 :     aLinkStr = convertLineEnd(aLinkStr, LINEEND_LF);
     134             : 
     135             :     //  wenn String mit Zeilenende aufhoert, streichen:
     136             : 
     137           5 :     sal_Int32 nLen = aLinkStr.getLength();
     138           5 :     if (nLen && aLinkStr[nLen-1] == '\n')
     139           5 :         aLinkStr = aLinkStr.copy(0, nLen-1);
     140             : 
     141          10 :     OUString aLine;
     142           5 :     SCSIZE nCols = 1;       // Leerstring -> eine leere Zelle
     143           5 :     SCSIZE nRows = 1;
     144           5 :     if (!aLinkStr.isEmpty())
     145             :     {
     146           5 :         nRows = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLinkStr, '\n'));
     147           5 :         aLine = aLinkStr.getToken( 0, '\n' );
     148           5 :         if (!aLine.isEmpty())
     149           5 :             nCols = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLine, '\t'));
     150             :     }
     151             : 
     152           5 :     if (!nRows || !nCols)               // keine Daten
     153             :     {
     154           0 :         pResult.reset();
     155             :     }
     156             :     else                                // Daten aufteilen
     157             :     {
     158             :         //  Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
     159           5 :         pResult = new ScMatrix(nCols, nRows, 0.0);
     160             : 
     161           5 :         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
     162           5 :         svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
     163             : 
     164             :         //  nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
     165             :         //  SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
     166             :         //  SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
     167             :         //  SC_DDE_TEXT    - ohne NumberFormatter direkt als String
     168           5 :         sal_uLong nStdFormat = 0;
     169           5 :         if ( nMode == SC_DDE_DEFAULT )
     170             :         {
     171           5 :             ScPatternAttr* pDefPattern = pDoc->GetDefPattern();     // enthaelt Standard-Vorlage
     172           5 :             if ( pDefPattern )
     173           5 :                 nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
     174             :         }
     175           0 :         else if ( nMode == SC_DDE_ENGLISH )
     176           0 :             nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
     177             : 
     178           5 :         OUString aEntry;
     179          10 :         for (SCSIZE nR=0; nR<nRows; nR++)
     180             :         {
     181           5 :             aLine = aLinkStr.getToken( (sal_Int32) nR, '\n' );
     182          10 :             for (SCSIZE nC=0; nC<nCols; nC++)
     183             :             {
     184           5 :                 aEntry = aLine.getToken( (sal_Int32) nC, '\t' );
     185           5 :                 sal_uInt32 nIndex = nStdFormat;
     186           5 :                 double fVal = double();
     187           5 :                 if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
     188           5 :                     pResult->PutDouble( fVal, nC, nR );
     189           0 :                 else if (aEntry.isEmpty())
     190             :                     // empty cell
     191           0 :                     pResult->PutEmpty(nC, nR);
     192             :                 else
     193           0 :                     pResult->PutString(rPool.intern(aEntry), nC, nR);
     194             :             }
     195           5 :         }
     196             :     }
     197             : 
     198             :     //  Es hat sich was getan...
     199             : 
     200           5 :     if (HasListeners())
     201             :     {
     202           2 :         Broadcast(ScHint(SC_HINT_DATACHANGED, ScAddress()));
     203           2 :         pDoc->TrackFormulas();      // muss sofort passieren
     204           2 :         pDoc->StartTrackTimer();
     205             : 
     206             :         //  StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
     207             :         //  ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
     208             :         //  TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
     209             :         //  eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)
     210             : 
     211             :         //  notify Uno objects (for XRefreshListener)
     212             :         //  must be after TrackFormulas
     213             :         //TODO: do this asynchronously?
     214           2 :         ScLinkRefreshedHint aHint;
     215           2 :         aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
     216           2 :         pDoc->BroadcastUno( aHint );
     217             :     }
     218             : 
     219          10 :     return SUCCESS;
     220             : }
     221             : 
     222           3 : void ScDdeLink::ListenersGone()
     223             : {
     224           3 :     bool bWas = bIsInUpdate;
     225           3 :     bIsInUpdate = true;             // Remove() kann Reschedule ausloesen??!?
     226             : 
     227           3 :     ScDocument* pStackDoc = pDoc;   // member pDoc can't be used after removing the link
     228             : 
     229           3 :     sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager();
     230           3 :     pLinkMgr->Remove( this);        // deletes this
     231             : 
     232           3 :     if ( pLinkMgr->GetLinks().empty() )            // letzten geloescht ?
     233             :     {
     234           3 :         SfxBindings* pBindings = pStackDoc->GetViewBindings();      // don't use member pDoc!
     235           3 :         if (pBindings)
     236           0 :             pBindings->Invalidate( SID_LINKS );
     237             :     }
     238             : 
     239           3 :     bIsInUpdate = bWas;
     240           3 : }
     241             : 
     242          12 : const ScMatrix* ScDdeLink::GetResult() const
     243             : {
     244          12 :     return pResult.get();
     245             : }
     246             : 
     247           0 : void ScDdeLink::SetResult( const ScMatrixRef& pRes )
     248             : {
     249           0 :     pResult = pRes;
     250           0 : }
     251             : 
     252           5 : void ScDdeLink::TryUpdate()
     253             : {
     254           5 :     if (bIsInUpdate)
     255           0 :         bNeedUpdate = true;         // kann jetzt nicht ausgefuehrt werden
     256             :     else
     257             :     {
     258           5 :         bIsInUpdate = true;
     259           5 :         pDoc->IncInDdeLinkUpdate();
     260           5 :         Update();
     261           5 :         pDoc->DecInDdeLinkUpdate();
     262           5 :         bIsInUpdate = false;
     263           5 :         bNeedUpdate = false;
     264             :     }
     265         161 : }
     266             : 
     267             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11