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