1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edfld.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <unotools/charclass.hxx>
38 #include <ndtxt.hxx> // GetCurFld
51 #include <swddetbl.hxx>
55 /*--------------------------------------------------------------------
56 Beschreibung: Feldtypen zu einer ResId zaehlen
58 --------------------------------------------------------------------*/
60 USHORT
SwEditShell::GetFldTypeCount(USHORT nResId
, BOOL bUsed
) const
62 const SwFldTypes
* pFldTypes
= GetDoc()->GetFldTypes();
63 const USHORT nSize
= pFldTypes
->Count();
65 if(nResId
== USHRT_MAX
)
72 for ( USHORT i
= 0; i
< nSize
; i
++ )
74 if(IsUsed(*(*pFldTypes
)[i
]))
81 // Alle Typen mit gleicher ResId
83 for(USHORT i
= 0; i
< nSize
; ++i
)
84 { // Gleiche ResId -> Index erhoehen
85 SwFieldType
& rFldType
= *((*pFldTypes
)[i
]);
86 if(rFldType
.Which() == nResId
)
92 /*--------------------------------------------------------------------
93 Beschreibung: Feldtypen zu einer ResId finden
95 --------------------------------------------------------------------*/
96 SwFieldType
* SwEditShell::GetFldType(USHORT nFld
, USHORT nResId
, BOOL bUsed
) const
98 const SwFldTypes
* pFldTypes
= GetDoc()->GetFldTypes();
99 const USHORT nSize
= pFldTypes
->Count();
101 if(nResId
== USHRT_MAX
&& nFld
< nSize
)
104 return (*pFldTypes
)[nFld
];
108 for ( i
= 0; i
< nSize
; i
++ )
110 if(IsUsed(*(*pFldTypes
)[i
]))
117 return i
< nSize
? (*pFldTypes
)[i
] : 0;
122 for(USHORT i
= 0; i
< nSize
; ++i
)
123 { // Gleiche ResId -> Index erhoehen
124 SwFieldType
* pFldType
= (*pFldTypes
)[i
];
125 if(pFldType
->Which() == nResId
)
127 if (!bUsed
|| IsUsed(*pFldType
))
138 /*--------------------------------------------------------------------
139 Beschreibung: Den ersten Typen mit ResId und Namen finden
140 --------------------------------------------------------------------*/
141 SwFieldType
* SwEditShell::GetFldType(USHORT nResId
, const String
& rName
) const
143 return GetDoc()->GetFldType( nResId
, rName
, false );
146 /*--------------------------------------------------------------------
147 Beschreibung: Feldtypen loeschen
148 --------------------------------------------------------------------*/
149 void SwEditShell::RemoveFldType(USHORT nFld
, USHORT nResId
)
151 if( USHRT_MAX
== nResId
)
153 GetDoc()->RemoveFldType(nFld
);
157 const SwFldTypes
* pFldTypes
= GetDoc()->GetFldTypes();
158 const USHORT nSize
= pFldTypes
->Count();
160 for( USHORT i
= 0; i
< nSize
; ++i
)
161 // Gleiche ResId -> Index erhoehen
162 if( (*pFldTypes
)[i
]->Which() == nResId
&&
165 GetDoc()->RemoveFldType( i
);
170 /*--------------------------------------------------------------------
171 Beschreibung: FieldType ueber Name loeschen
172 --------------------------------------------------------------------*/
173 void SwEditShell::RemoveFldType(USHORT nResId
, const String
& rStr
)
175 const SwFldTypes
* pFldTypes
= GetDoc()->GetFldTypes();
176 const USHORT nSize
= pFldTypes
->Count();
177 const CharClass
& rCC
= GetAppCharClass();
179 String
aTmp( rCC
.lower( rStr
));
181 for(USHORT i
= 0; i
< nSize
; ++i
)
183 // Gleiche ResId -> Index erhoehen
184 SwFieldType
* pFldType
= (*pFldTypes
)[i
];
185 if( pFldType
->Which() == nResId
)
187 if( aTmp
.Equals( rCC
.lower( pFldType
->GetName() ) ))
189 GetDoc()->RemoveFldType(i
);
197 void SwEditShell::FieldToText( SwFieldType
* pType
)
199 if( !pType
->GetDepends() )
202 SET_CURR_SHELL( this );
204 StartUndo( UNDO_DELETE
);
206 SwPaM
* pPaM
= GetCrsr();
208 BOOL bDDEFld
= RES_DDEFLD
== pType
->Which();
209 // Modify-Object gefunden, trage alle Felder ins Array ein
210 SwClientIter
aIter( *pType
);
211 SwClient
* pLast
= aIter
.GoStart();
213 if( pLast
) // konnte zum Anfang gesprungen werden ??
216 const SwFmtFld
* pFmtFld
= bDDEFld
217 ? PTR_CAST( SwFmtFld
, pLast
)
222 if( !pFmtFld
->GetTxtFld() )
225 // kann keine DDETabelle sein
226 const SwTxtNode
& rTxtNode
= pFmtFld
->GetTxtFld()->GetTxtNode();
227 pPaM
->GetPoint()->nNode
= rTxtNode
;
228 pPaM
->GetPoint()->nContent
.Assign( (SwTxtNode
*)&rTxtNode
,
229 *pFmtFld
->GetTxtFld()->GetStart() );
231 // Feldinhalt durch Text ersetzen
232 String
aEntry( pFmtFld
->GetFld()->Expand() );
234 pPaM
->Move( fnMoveForward
);
235 GetDoc()->DeleteRange( *pPaM
);
236 GetDoc()->InsertString( *pPaM
, aEntry
);
241 SwDepend
* pDep
= (SwDepend
*)pLast
;
242 SwDDETable
* pDDETbl
= (SwDDETable
*)pDep
->GetToTell();
243 pDDETbl
->NoDDETable();
246 } while( 0 != ( pLast
= aIter
++ ));
250 EndUndo( UNDO_DELETE
);
253 /*************************************************************************
255 |* SwEditShell::Insert( SwField )
257 |* Beschreibung an der Cursorposition ein Feld einfuegen
258 |* Quelle: vgl. SwEditShell::Insert( String )
260 *************************************************************************/
261 void SwEditShell::Insert2(SwField
& rFld
, const bool bForceExpandHints
)
263 SET_CURR_SHELL( this );
265 SwFmtFld
aFld( rFld
);
267 const SetAttrMode nInsertFlags
= (bForceExpandHints
)
268 ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
269 : nsSetAttrMode::SETATTR_DEFAULT
;
271 FOREACHPAM_START(this) // fuer jeden PaM
272 bool bSuccess(GetDoc()->InsertPoolItem(*PCURCRSR
, aFld
, nInsertFlags
));
273 ASSERT( bSuccess
, "Doc->Insert(Field) failed");
275 FOREACHPAM_END() // fuer jeden PaM
280 /*************************************************************************
282 |* SwEditShell::GetCurFld()
284 |* Beschreibung Stehen die PaMs auf Feldern ?
285 |* Quelle: edtfrm.cxx:
287 *************************************************************************/
289 inline SwTxtFld
*GetDocTxtFld( const SwPosition
* pPos
)
291 SwTxtNode
* const pNode
= pPos
->nNode
.GetNode().GetTxtNode();
293 ? static_cast<SwTxtFld
*>( pNode
->GetTxtAttrForCharAt(
294 pPos
->nContent
.GetIndex(), RES_TXTATR_FIELD
))
298 SwField
* SwEditShell::GetCurFld() const
300 // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
303 SwPaM
* pCrsr
= GetCrsr();
304 SwTxtFld
*pTxtFld
= GetDocTxtFld( pCrsr
->Start() );
305 SwField
*pCurFld
= NULL
;
307 /* #108536# Field was only recognized if no selection was
308 present. Now it is recognized if either the cursor is in the
309 field or the selection spans exactly over the field. */
311 pCrsr
->GetNext() == pCrsr
&&
312 pCrsr
->Start()->nNode
== pCrsr
->End()->nNode
&&
313 (pCrsr
->End()->nContent
.GetIndex() -
314 pCrsr
->Start()->nContent
.GetIndex()) <= 1)
316 pCurFld
= (SwField
*)pTxtFld
->GetFld().GetFld();
317 // TabellenFormel ? wandel internen in externen Namen um
318 if( RES_TABLEFLD
== pCurFld
->GetTyp()->Which() )
320 const SwTableNode
* pTblNd
= IsCrsrInTbl();
321 ((SwTblField
*)pCurFld
)->PtrToBoxNm( pTblNd
? &pTblNd
->GetTable() : 0 );
326 /* #108536# removed handling of multi-selections */
332 /*************************************************************************
334 |* SwEditShell::UpdateFlds()
336 |* Beschreibung Stehen die PaMs auf Feldern ?
339 *************************************************************************/
340 SwTxtFld
* lcl_FindInputFld( SwDoc
* pDoc
, SwField
& rFld
)
342 // suche das Feld ueber seine Addresse. Muss fuer InputFelder in
343 // geschuetzten Feldern erfolgen
345 if( RES_INPUTFLD
== rFld
.Which() || ( RES_SETEXPFLD
== rFld
.Which() &&
346 ((SwSetExpField
&)rFld
).GetInputFlag() ) )
348 const SfxPoolItem
* pItem
;
349 USHORT n
, nMaxItems
=
350 pDoc
->GetAttrPool().GetItemCount( RES_TXTATR_FIELD
);
351 for( n
= 0; n
< nMaxItems
; ++n
)
353 pDoc
->GetAttrPool().GetItem( RES_TXTATR_FIELD
, n
) )
354 && ((SwFmtFld
*)pItem
)->GetFld() == &rFld
)
356 pTFld
= ((SwFmtFld
*)pItem
)->GetTxtFld();
363 void SwEditShell::UpdateFlds( SwField
&rFld
)
365 SET_CURR_SHELL( this );
368 SwField
*pCurFld
= 0;
370 // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
372 SwMsgPoolItem
* pMsgHnt
= 0;
373 SwRefMarkFldUpdate
aRefMkHt( GetOut() );
374 USHORT nFldWhich
= rFld
.GetTyp()->Which();
375 if( RES_GETREFFLD
== nFldWhich
)
378 SwPaM
* pCrsr
= GetCrsr();
382 // if( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark() &&
383 // ( 0 != ( pTxtFld = GetDocTxtFld( pCrsr->Start() ) ) ||
384 // 0 != ( pTxtFld = lcl_FindInputFld( GetDoc(), rFld ) ) ) &&
385 // ( pFmtFld = (SwFmtFld*)&pTxtFld->GetFld())->GetFld()
386 // ->GetTyp()->Which() == rFld.GetTyp()->Which() )
387 if ( pCrsr
->GetNext() == pCrsr
&& !pCrsr
->HasMark())
389 pTxtFld
= GetDocTxtFld(pCrsr
->Start());
391 if (!pTxtFld
) // #i30221#
392 pTxtFld
= lcl_FindInputFld( GetDoc(), rFld
);
395 GetDoc()->UpdateFld(pTxtFld
, rFld
, pMsgHnt
, TRUE
); // #111840#
398 // bOkay (statt return wg. EndAllAction) wird FALSE,
399 // 1) wenn nur ein Pam mehr als ein Feld enthaelt oder
400 // 2) bei gemischten Feldtypen
402 BOOL bTblSelBreak
= FALSE
;
404 SwMsgPoolItem
aHint( RES_TXTATR_FIELD
); // Such-Hint
405 FOREACHPAM_START(this) // fuer jeden PaM
406 if( PCURCRSR
->HasMark() && bOkay
) // ... mit Selektion
409 SwPaM
aCurPam( *PCURCRSR
->GetMark(), *PCURCRSR
->GetPoint() );
410 SwPaM
aPam( *PCURCRSR
->GetPoint() );
412 SwPosition
*pCurStt
= aCurPam
.Start(), *pCurEnd
=
415 * Fuer den Fall, dass zwei aneinanderliegende Felder in einem
416 * PaM liegen, hangelt sich aPam portionsweise bis zum Ende.
417 * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt.
418 * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End
419 * und die Schleife terminiert.
422 // Suche nach SwTxtFld ...
424 && pCurStt
->nContent
!= pCurEnd
->nContent
425 && aPam
.Find( aHint
, FALSE
, fnMoveForward
, &aCurPam
) )
427 // wenn nur ein Pam mehr als ein Feld enthaelt ...
428 if( aPam
.Start()->nContent
!= pCurStt
->nContent
)
431 if( 0 != (pTxtFld
= GetDocTxtFld( pCurStt
)) )
433 pFmtFld
= (SwFmtFld
*)&pTxtFld
->GetFld();
434 pCurFld
= pFmtFld
->GetFld();
436 // bei gemischten Feldtypen
437 if( pCurFld
->GetTyp()->Which() !=
438 rFld
.GetTyp()->Which() )
441 bTblSelBreak
= GetDoc()->UpdateFld(pTxtFld
, rFld
,
442 pMsgHnt
, FALSE
); // #111840#
444 // Der Suchbereich wird um den gefundenen Bereich
450 if( bTblSelBreak
) // wenn Tabellen Selektion und Tabellen-
451 break; // Formel aktualisiert wurde -> beenden
453 FOREACHPAM_END() // fuer jeden PaM
455 GetDoc()->SetModified();
459 /*-----------------13.05.92 10:54-------------------
460 Liefert den logischen fuer die Datenbank zurueck
461 --------------------------------------------------*/
463 SwDBData
SwEditShell::GetDBData() const
465 return GetDoc()->GetDBData();
468 const SwDBData
& SwEditShell::GetDBDesc() const
470 return GetDoc()->GetDBDesc();
473 void SwEditShell::ChgDBData(const SwDBData
& rNewData
)
475 GetDoc()->ChgDBData(rNewData
);
478 void SwEditShell::GetAllUsedDB( SvStringsDtor
& rDBNameList
,
479 SvStringsDtor
* pAllDBNames
)
481 GetDoc()->GetAllUsedDB( rDBNameList
, pAllDBNames
);
484 void SwEditShell::ChangeDBFields( const SvStringsDtor
& rOldNames
,
485 const String
& rNewName
)
487 GetDoc()->ChangeDBFields( rOldNames
, rNewName
);
490 /*--------------------------------------------------------------------
491 Beschreibung: Alle Expression-Felder erneuern
492 --------------------------------------------------------------------*/
493 void SwEditShell::UpdateExpFlds(BOOL bCloseDB
)
495 SET_CURR_SHELL( this );
497 GetDoc()->UpdateExpFlds(NULL
, true);
499 GetDoc()->GetNewDBMgr()->CloseAll(); // Alle Datenbankverbindungen dichtmachen
503 SwNewDBMgr
* SwEditShell::GetNewDBMgr() const
505 return GetDoc()->GetNewDBMgr();
508 /*--------------------------------------------------------------------
509 Beschreibung: Feldtypen einfuegen
510 --------------------------------------------------------------------*/
511 SwFieldType
* SwEditShell::InsertFldType(const SwFieldType
& rFldType
)
513 return GetDoc()->InsertFldType(rFldType
);
516 void SwEditShell::LockExpFlds()
518 GetDoc()->LockExpFlds();
521 void SwEditShell::UnlockExpFlds()
523 GetDoc()->UnlockExpFlds();
527 void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags
)
529 getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags
);
532 SwFldUpdateFlags
SwEditShell::GetFldUpdateFlags(BOOL bDocSettings
) const
534 return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings
);
537 void SwEditShell::SetFixFields( BOOL bOnlyTimeDate
,
538 const DateTime
* pNewDateTime
)
540 SET_CURR_SHELL( this );
541 BOOL bUnLockView
= !IsViewLocked();
544 GetDoc()->SetFixFields( bOnlyTimeDate
, pNewDateTime
);
550 void SwEditShell::SetLabelDoc( BOOL bFlag
)
552 GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT
, bFlag
);
555 BOOL
SwEditShell::IsLabelDoc() const
557 return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT
);
559 /* -----------------------------21.12.99 12:53--------------------------------
561 ---------------------------------------------------------------------------*/
562 void SwEditShell::ChangeAuthorityData(const SwAuthEntry
* pNewData
)
564 GetDoc()->ChangeAuthorityData(pNewData
);
566 /* -----------------------------03.08.2001 12:04------------------------------
568 ---------------------------------------------------------------------------*/
569 BOOL
SwEditShell::IsAnyDatabaseFieldInDoc()const
571 const SwFldTypes
* pFldTypes
= GetDoc()->GetFldTypes();
572 const USHORT nSize
= pFldTypes
->Count();
573 for(USHORT i
= 0; i
< nSize
; ++i
)
575 SwFieldType
& rFldType
= *((*pFldTypes
)[i
]);
576 USHORT nWhich
= rFldType
.Which();
582 case RES_DBNEXTSETFLD
:
583 case RES_DBNUMSETFLD
:
584 case RES_DBSETNUMBERFLD
:
586 SwClientIter
aIter( rFldType
);
587 SwFmtFld
* pFld
= (SwFmtFld
*)aIter
.First( TYPE( SwFmtFld
));
590 if(pFld
->IsFldInDoc())
592 pFld
= (SwFmtFld
*)aIter
.Next();