xref: /trunk/main/sw/source/core/fields/ddefld.cxx (revision 2f121198d67f2a83c79aa413d785f6f49842f605)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <sfx2/linkmgr.hxx>
33 #include <doc.hxx>
34 #include <editsh.hxx>
35 #include <errhdl.hxx>
36 #include <ndtxt.hxx>
37 #include <fmtfld.hxx>
38 #include <txtfld.hxx>
39 #include <ddefld.hxx>
40 #include <swtable.hxx>
41 #include <swbaslnk.hxx>
42 #include <swddetbl.hxx>
43 #include <unofldmid.h>
44 #include <hints.hxx>
45 
46 using rtl::OUString;
47 using namespace ::com::sun::star;
48 
49 #define DDE_TXT_ENCODING    gsl_getSystemTextEncoding()
50 
51 /*--------------------------------------------------------------------
52     Beschreibung: Globale Variablen
53  --------------------------------------------------------------------*/
54 
55 class SwIntrnlRefLink : public SwBaseLink
56 {
57     SwDDEFieldType& rFldType;
58 public:
59     SwIntrnlRefLink( SwDDEFieldType& rType, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
60         : SwBaseLink( nUpdateType, nFmt ),
61         rFldType( rType )
62     {}
63 
64     virtual void Closed();
65     virtual void DataChanged( const String& rMimeType,
66                                 const uno::Any & rValue );
67 
68     virtual const SwNode* GetAnchor() const;
69     virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0,
70                             xub_StrLen nEnd = STRING_NOTFOUND ) const;
71 };
72 
73 
74 void SwIntrnlRefLink::DataChanged( const String& rMimeType,
75                                 const uno::Any & rValue )
76 {
77     switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
78     {
79     case FORMAT_STRING:
80         if( !IsNoDataFlag() )
81         {
82             uno::Sequence< sal_Int8 > aSeq;
83             rValue >>= aSeq;
84             String sStr( (sal_Char*)aSeq.getConstArray(), static_cast<xub_StrLen>(aSeq.getLength()),
85                                DDE_TXT_ENCODING  );
86 
87             // CR-LF am Ende entfernen, ist ueberfluessig!
88             xub_StrLen n = sStr.Len();
89             while( n && 0 == sStr.GetChar( n-1 ) )
90                 --n;
91             if( n && 0x0a == sStr.GetChar( n-1 ) )
92                 --n;
93             if( n && 0x0d == sStr.GetChar( n-1 ) )
94                 --n;
95 
96             sal_Bool bDel = n != sStr.Len();
97             if( bDel )
98                 sStr.Erase( n );
99 
100             rFldType.SetExpansion( sStr );
101             // erst Expansion setzen! (sonst wird das Flag geloescht!)
102             rFldType.SetCRLFDelFlag( bDel );
103         }
104         break;
105 
106     // weitere Formate ...
107     default:
108         return;
109     }
110 
111     ASSERT( rFldType.GetDoc(), "Kein pDoc" );
112 
113     // keine Abhaengigen mehr?
114     if( rFldType.GetDepends() && !rFldType.IsModifyLocked() && !ChkNoDataFlag() )
115     {
116         ViewShell* pSh;
117         SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh );
118 
119         // dann suchen wir uns mal alle Felder. Wird kein gueltiges
120         // gefunden, dann Disconnecten wir uns!
121         SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
122         int bCallModify = sal_False;
123         rFldType.LockModify();
124 
125         SwClientIter aIter( rFldType );     // TODO
126         SwClient * pLast = aIter.GoStart();
127         if( pLast )     // konnte zum Anfang gesprungen werden ??
128             do {
129                 // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
130                 if( !pLast->IsA( TYPE( SwFmtFld ) ) ||
131                     ((SwFmtFld*)pLast)->GetTxtFld() )
132                 {
133                     if( !bCallModify )
134                     {
135                         if( pESh )
136                             pESh->StartAllAction();
137                         else if( pSh )
138                             pSh->StartAction();
139                     }
140                     pLast->ModifyNotification( 0, &aUpdateDDE );
141                     bCallModify = sal_True;
142                 }
143             } while( 0 != ( pLast = ++aIter ));
144 
145         rFldType.UnlockModify();
146 
147         if( bCallModify )
148         {
149             if( pESh )
150                 pESh->EndAllAction();
151             else if( pSh )
152                 pSh->EndAction();
153 
154             if( pSh )
155                 pSh->GetDoc()->SetModified();
156         }
157     }
158 }
159 
160 void SwIntrnlRefLink::Closed()
161 {
162     if( rFldType.GetDoc() && !rFldType.GetDoc()->IsInDtor() )
163     {
164         // Advise verabschiedet sich, alle Felder in Text umwandeln ?
165         ViewShell* pSh;
166         SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh );
167         if( pESh )
168         {
169             pESh->StartAllAction();
170             pESh->FieldToText( &rFldType );
171             pESh->EndAllAction();
172         }
173         else
174         {
175             pSh->StartAction();
176             // am Doc aufrufen ??
177             pSh->EndAction();
178         }
179     }
180     SvBaseLink::Closed();
181 }
182 
183 const SwNode* SwIntrnlRefLink::GetAnchor() const
184 {
185     // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen
186     const SwNode* pNd = 0;
187     SwClientIter aIter( rFldType );     // TODO
188     SwClient * pLast = aIter.GoStart();
189     if( pLast )     // konnte zum Anfang gesprungen werden ??
190         do {
191             // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
192             if( !pLast->IsA( TYPE( SwFmtFld ) ))
193             {
194                 SwDepend* pDep = (SwDepend*)pLast;
195                 SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
196                 pNd = pDDETbl->GetTabSortBoxes()[0]->GetSttNd();
197             }
198             else if( ((SwFmtFld*)pLast)->GetTxtFld() )
199                 pNd = ((SwFmtFld*)pLast)->GetTxtFld()->GetpTxtNode();
200 
201             if( pNd && &rFldType.GetDoc()->GetNodes() == &pNd->GetNodes() )
202                 break;
203             pNd = 0;
204         } while( 0 != ( pLast = ++aIter ));
205 
206     return pNd;
207 }
208 
209 sal_Bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
210                                 xub_StrLen nStt, xub_StrLen nEnd ) const
211 {
212     // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen
213     SwNodes* pNds = &rFldType.GetDoc()->GetNodes();
214     SwClientIter aIter( rFldType );         // TODO
215     SwClient * pLast = aIter.GoStart();
216     if( pLast )     // konnte zum Anfang gesprungen werden ??
217         do {
218             // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
219             if( !pLast->IsA( TYPE( SwFmtFld ) ))
220             {
221                 SwDepend* pDep = (SwDepend*)pLast;
222                 SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
223                 const SwTableNode* pTblNd = pDDETbl->GetTabSortBoxes()[0]->
224                                 GetSttNd()->FindTableNode();
225                 if( pTblNd->GetNodes().IsDocNodes() &&
226                     nSttNd < pTblNd->EndOfSectionIndex() &&
227                     nEndNd > pTblNd->GetIndex() )
228                     return sal_True;
229             }
230             else if( ((SwFmtFld*)pLast)->GetTxtFld() )
231             {
232                 const SwTxtFld* pTFld = ((SwFmtFld*)pLast)->GetTxtFld();
233                 const SwTxtNode* pNd = pTFld->GetpTxtNode();
234                 if( pNd && pNds == &pNd->GetNodes() )
235                 {
236                     sal_uLong nNdPos = pNd->GetIndex();
237                     if( nSttNd <= nNdPos && nNdPos <= nEndNd &&
238                         ( nNdPos != nSttNd || *pTFld->GetStart() >= nStt ) &&
239                         ( nNdPos != nEndNd || *pTFld->GetStart() < nEnd ))
240                         return sal_True;
241                 }
242             }
243         } while( 0 != ( pLast = ++aIter ));
244 
245     return sal_False;
246 }
247 
248 SwDDEFieldType::SwDDEFieldType(const String& rName,
249                                 const String& rCmd, sal_uInt16 nUpdateType )
250     : SwFieldType( RES_DDEFLD ),
251     aName( rName ), pDoc( 0 ), nRefCnt( 0 )
252 {
253     bCRLFFlag = bDeleted = sal_False;
254     refLink = new SwIntrnlRefLink( *this, nUpdateType, FORMAT_STRING );
255     SetCmd( rCmd );
256 }
257 
258 SwDDEFieldType::~SwDDEFieldType()
259 {
260     if( pDoc && !pDoc->IsInDtor() )
261         pDoc->GetLinkManager().Remove( refLink );
262     refLink->Disconnect();
263 }
264 
265 SwFieldType* SwDDEFieldType::Copy() const
266 {
267     SwDDEFieldType* pType = new SwDDEFieldType( aName, GetCmd(), GetType() );
268     pType->aExpansion = aExpansion;
269     pType->bCRLFFlag = bCRLFFlag;
270     pType->bDeleted = bDeleted;
271     pType->SetDoc( pDoc );
272     return pType;
273 }
274 
275 const String& SwDDEFieldType::GetName() const
276 {
277     return aName;
278 }
279 
280 void SwDDEFieldType::SetCmd( const String& rStr )
281 {
282     String sCmd( rStr );
283     xub_StrLen nPos;
284     while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( "  " )) )
285         sCmd.Erase( nPos, 1 );
286     refLink->SetLinkSourceName( sCmd );
287 }
288 
289 String SwDDEFieldType::GetCmd() const
290 {
291     return refLink->GetLinkSourceName();
292 }
293 
294 void SwDDEFieldType::SetDoc( SwDoc* pNewDoc )
295 {
296     if( pNewDoc == pDoc )
297         return;
298 
299     if( pDoc && refLink.Is() )
300     {
301         ASSERT( !nRefCnt, "wie kommen die Referenzen rueber?" );
302         pDoc->GetLinkManager().Remove( refLink );
303     }
304 
305     pDoc = pNewDoc;
306     if( pDoc && nRefCnt )
307     {
308         refLink->SetVisible( pDoc->IsVisibleLinks() );
309         pDoc->GetLinkManager().InsertDDELink( refLink );
310     }
311 }
312 
313 
314 void SwDDEFieldType::_RefCntChgd()
315 {
316     if( nRefCnt )
317     {
318         refLink->SetVisible( pDoc->IsVisibleLinks() );
319         pDoc->GetLinkManager().InsertDDELink( refLink );
320         if( pDoc->GetCurrentViewShell() )   //swmod 071108//swmod 071225
321             UpdateNow();
322     }
323     else
324     {
325         Disconnect();
326         pDoc->GetLinkManager().Remove( refLink );
327     }
328 }
329 /* -----------------------------28.08.00 16:23--------------------------------
330 
331  ---------------------------------------------------------------------------*/
332 sal_Bool SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
333 {
334     sal_uInt8 nPart = 0;
335     switch( nWhichId )
336     {
337     case FIELD_PROP_PAR2:      nPart = 3; break;
338     case FIELD_PROP_PAR4:      nPart = 2; break;
339     case FIELD_PROP_SUBTYPE:   nPart = 1; break;
340     case FIELD_PROP_BOOL1:
341         {
342             sal_Bool bSet = GetType() == sfx2::LINKUPDATE_ALWAYS ? sal_True : sal_False;
343             rVal.setValue(&bSet, ::getBooleanCppuType());
344         }
345         break;
346     case FIELD_PROP_PAR5:
347         rVal <<= ::rtl::OUString(aExpansion);
348     break;
349     default:
350         DBG_ERROR("illegal property");
351     }
352     if( nPart )
353         rVal <<= OUString(GetCmd().GetToken(nPart-1, sfx2::cTokenSeperator));
354     return sal_True;
355 }
356 /* -----------------------------28.08.00 16:23--------------------------------
357 
358  ---------------------------------------------------------------------------*/
359 sal_Bool SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
360 {
361     sal_uInt8 nPart = 0;
362     switch( nWhichId )
363     {
364     case FIELD_PROP_PAR2:      nPart = 3; break;
365     case FIELD_PROP_PAR4:      nPart = 2; break;
366     case FIELD_PROP_SUBTYPE:   nPart = 1; break;
367     case FIELD_PROP_BOOL1:
368         SetType( static_cast<sal_uInt16>(*(sal_Bool*)rVal.getValue() ?
369                                      sfx2::LINKUPDATE_ALWAYS :
370                                      sfx2::LINKUPDATE_ONCALL ) );
371         break;
372     case FIELD_PROP_PAR5:
373     {
374         ::rtl::OUString sTemp;
375         rVal >>= sTemp;
376         aExpansion = sTemp;
377     }
378     break;
379     default:
380         DBG_ERROR("illegal property");
381     }
382     if( nPart )
383     {
384         String sTmp, sCmd( GetCmd() );
385         while(3 > sCmd.GetTokenCount(sfx2::cTokenSeperator))
386             sCmd += sfx2::cTokenSeperator;
387         sCmd.SetToken( nPart-1, sfx2::cTokenSeperator, ::GetString( rVal, sTmp ) );
388         SetCmd( sCmd );
389     }
390     return sal_True;
391 }
392 /* ---------------------------------------------------------------------------
393 
394  ---------------------------------------------------------------------------*/
395 SwDDEField::SwDDEField( SwDDEFieldType* pInitType )
396     : SwField(pInitType)
397 {
398 }
399 
400 SwDDEField::~SwDDEField()
401 {
402     if( GetTyp()->IsLastDepend() )
403         ((SwDDEFieldType*)GetTyp())->Disconnect();
404 }
405 
406 String SwDDEField::Expand() const
407 {
408     xub_StrLen nPos;
409     String aStr( ((SwDDEFieldType*)GetTyp())->GetExpansion() );
410 
411     aStr.EraseAllChars( '\r' );
412     while( (nPos = aStr.Search( '\t' )) != STRING_NOTFOUND )
413         aStr.SetChar( nPos, ' ' );
414     while( (nPos = aStr.Search( '\n' )) != STRING_NOTFOUND )
415         aStr.SetChar( nPos, '|' );
416     if( aStr.Len() && ( aStr.GetChar( aStr.Len()-1 ) == '|') )
417         aStr.Erase( aStr.Len()-1, 1 );
418     return aStr;
419 }
420 
421 SwField* SwDDEField::Copy() const
422 {
423     return new SwDDEField((SwDDEFieldType*)GetTyp());
424 }
425 
426 /*--------------------------------------------------------------------
427     Beschreibung: Parameter des Typen erfragen
428                   Name
429  --------------------------------------------------------------------*/
430 const String& SwDDEField::GetPar1() const
431 {
432     return ((SwDDEFieldType*)GetTyp())->GetName();
433 }
434 
435 /*--------------------------------------------------------------------
436     Beschreibung: Parameter des Typen erfragen
437                   Commando
438  --------------------------------------------------------------------*/
439 String SwDDEField::GetPar2() const
440 {
441     return ((SwDDEFieldType*)GetTyp())->GetCmd();
442 }
443 
444 void SwDDEField::SetPar2(const String& rStr)
445 {
446     ((SwDDEFieldType*)GetTyp())->SetCmd(rStr);
447 }
448 
449