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 <unotools/charclass.hxx> 33 #include <editsh.hxx> 34 #include <fldbas.hxx> 35 #include <ndtxt.hxx> // GetCurFld 36 #include <doc.hxx> 37 #include <docary.hxx> 38 #include <fmtfld.hxx> 39 #include <txtfld.hxx> 40 #include <edimp.hxx> 41 #include <dbfld.hxx> 42 #include <expfld.hxx> 43 #include <flddat.hxx> 44 #include <swundo.hxx> 45 #include <dbmgr.hxx> 46 #include <swddetbl.hxx> 47 #include <hints.hxx> 48 #include <switerator.hxx> 49 #include <fieldhint.hxx> 50 51 /*-------------------------------------------------------------------- 52 Beschreibung: Feldtypen zu einer ResId zaehlen 53 wenn 0 alle zaehlen 54 --------------------------------------------------------------------*/ 55 56 sal_uInt16 SwEditShell::GetFldTypeCount(sal_uInt16 nResId, sal_Bool bUsed ) const 57 { 58 const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes(); 59 const sal_uInt16 nSize = pFldTypes->Count(); 60 61 if(nResId == USHRT_MAX) 62 { 63 if(!bUsed) 64 return nSize; 65 else 66 { 67 sal_uInt16 nUsed = 0; 68 for ( sal_uInt16 i = 0; i < nSize; i++ ) 69 { 70 if(IsUsed(*(*pFldTypes)[i])) 71 nUsed++; 72 } 73 return nUsed; 74 } 75 } 76 77 // Alle Typen mit gleicher ResId 78 sal_uInt16 nIdx = 0; 79 for(sal_uInt16 i = 0; i < nSize; ++i) 80 { // Gleiche ResId -> Index erhoehen 81 SwFieldType& rFldType = *((*pFldTypes)[i]); 82 if(rFldType.Which() == nResId) 83 nIdx++; 84 } 85 return nIdx; 86 } 87 88 /*-------------------------------------------------------------------- 89 Beschreibung: Feldtypen zu einer ResId finden 90 wenn 0 alle finden 91 --------------------------------------------------------------------*/ 92 SwFieldType* SwEditShell::GetFldType(sal_uInt16 nFld, sal_uInt16 nResId, sal_Bool bUsed ) const 93 { 94 const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes(); 95 const sal_uInt16 nSize = pFldTypes->Count(); 96 97 if(nResId == USHRT_MAX && nFld < nSize) 98 { 99 if(!bUsed) 100 return (*pFldTypes)[nFld]; 101 else 102 { 103 sal_uInt16 i, nUsed = 0; 104 for ( i = 0; i < nSize; i++ ) 105 { 106 if(IsUsed(*(*pFldTypes)[i])) 107 { 108 if(nUsed == nFld) 109 break; 110 nUsed++; 111 } 112 } 113 return i < nSize ? (*pFldTypes)[i] : 0; 114 } 115 } 116 117 sal_uInt16 nIdx = 0; 118 for(sal_uInt16 i = 0; i < nSize; ++i) 119 { // Gleiche ResId -> Index erhoehen 120 SwFieldType* pFldType = (*pFldTypes)[i]; 121 if(pFldType->Which() == nResId) 122 { 123 if (!bUsed || IsUsed(*pFldType)) 124 { 125 if(nIdx == nFld) 126 return pFldType; 127 nIdx++; 128 } 129 } 130 } 131 return 0; 132 } 133 134 /*-------------------------------------------------------------------- 135 Beschreibung: Den ersten Typen mit ResId und Namen finden 136 --------------------------------------------------------------------*/ 137 SwFieldType* SwEditShell::GetFldType(sal_uInt16 nResId, const String& rName) const 138 { 139 return GetDoc()->GetFldType( nResId, rName, false ); 140 } 141 142 /*-------------------------------------------------------------------- 143 Beschreibung: Feldtypen loeschen 144 --------------------------------------------------------------------*/ 145 void SwEditShell::RemoveFldType(sal_uInt16 nFld, sal_uInt16 nResId) 146 { 147 if( USHRT_MAX == nResId ) 148 { 149 GetDoc()->RemoveFldType(nFld); 150 return; 151 } 152 153 const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes(); 154 const sal_uInt16 nSize = pFldTypes->Count(); 155 sal_uInt16 nIdx = 0; 156 for( sal_uInt16 i = 0; i < nSize; ++i ) 157 // Gleiche ResId -> Index erhoehen 158 if( (*pFldTypes)[i]->Which() == nResId && 159 nIdx++ == nFld ) 160 { 161 GetDoc()->RemoveFldType( i ); 162 return; 163 } 164 } 165 166 /*-------------------------------------------------------------------- 167 Beschreibung: FieldType ueber Name loeschen 168 --------------------------------------------------------------------*/ 169 void SwEditShell::RemoveFldType(sal_uInt16 nResId, const String& rStr) 170 { 171 const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes(); 172 const sal_uInt16 nSize = pFldTypes->Count(); 173 const CharClass& rCC = GetAppCharClass(); 174 175 String aTmp( rCC.lower( rStr )); 176 177 for(sal_uInt16 i = 0; i < nSize; ++i) 178 { 179 // Gleiche ResId -> Index erhoehen 180 SwFieldType* pFldType = (*pFldTypes)[i]; 181 if( pFldType->Which() == nResId ) 182 { 183 if( aTmp.Equals( rCC.lower( pFldType->GetName() ) )) 184 { 185 GetDoc()->RemoveFldType(i); 186 return; 187 } 188 } 189 } 190 } 191 192 193 void SwEditShell::FieldToText( SwFieldType* pType ) 194 { 195 if( !pType->GetDepends() ) 196 return; 197 198 SET_CURR_SHELL( this ); 199 StartAllAction(); 200 StartUndo( UNDO_DELETE ); 201 Push(); 202 SwPaM* pPaM = GetCrsr(); 203 204 SwFieldHint aHint( pPaM ); 205 SwClientIter aIter( *pType ); 206 for ( SwClient* pClient = aIter.GoStart(); pClient; pClient = ++aIter ) 207 { 208 pPaM->DeleteMark(); 209 pClient->SwClientNotifyCall( *pType, aHint ); 210 } 211 212 Pop( sal_False ); 213 EndAllAction(); 214 EndUndo( UNDO_DELETE ); 215 } 216 217 /************************************************************************* 218 |* 219 |* SwEditShell::Insert( SwField ) 220 |* 221 |* Beschreibung an der Cursorposition ein Feld einfuegen 222 |* Quelle: vgl. SwEditShell::Insert( String ) 223 |* 224 *************************************************************************/ 225 void SwEditShell::Insert2(SwField& rFld, const bool bForceExpandHints) 226 { 227 SET_CURR_SHELL( this ); 228 StartAllAction(); 229 SwFmtFld aFld( rFld ); 230 231 const SetAttrMode nInsertFlags = (bForceExpandHints) 232 ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND 233 : nsSetAttrMode::SETATTR_DEFAULT; 234 235 FOREACHPAM_START(this) // fuer jeden PaM 236 bool bSuccess(GetDoc()->InsertPoolItem(*PCURCRSR, aFld, nInsertFlags)); 237 ASSERT( bSuccess, "Doc->Insert(Field) failed"); 238 (void) bSuccess; 239 FOREACHPAM_END() // fuer jeden PaM 240 241 EndAllAction(); 242 } 243 244 /************************************************************************* 245 |* 246 |* SwEditShell::GetCurFld() 247 |* 248 |* Beschreibung Stehen die PaMs auf Feldern ? 249 |* Quelle: edtfrm.cxx: 250 |* 251 *************************************************************************/ 252 253 inline SwTxtFld *GetDocTxtFld( const SwPosition* pPos ) 254 { 255 SwTxtNode * const pNode = pPos->nNode.GetNode().GetTxtNode(); 256 return (pNode) 257 ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt( 258 pPos->nContent.GetIndex(), RES_TXTATR_FIELD )) 259 : 0; 260 } 261 262 SwField* SwEditShell::GetCurFld() const 263 { 264 // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen 265 // Cursor-Position. 266 267 SwPaM* pCrsr = GetCrsr(); 268 SwTxtFld *pTxtFld = GetDocTxtFld( pCrsr->Start() ); 269 SwField *pCurFld = NULL; 270 271 /* #108536# Field was only recognized if no selection was 272 present. Now it is recognized if either the cursor is in the 273 field or the selection spans exactly over the field. */ 274 if( pTxtFld && 275 pCrsr->GetNext() == pCrsr && 276 pCrsr->Start()->nNode == pCrsr->End()->nNode && 277 (pCrsr->End()->nContent.GetIndex() - 278 pCrsr->Start()->nContent.GetIndex()) <= 1) 279 { 280 pCurFld = (SwField*)pTxtFld->GetFld().GetFld(); 281 // TabellenFormel ? wandel internen in externen Namen um 282 if( RES_TABLEFLD == pCurFld->GetTyp()->Which() ) 283 { 284 const SwTableNode* pTblNd = IsCrsrInTbl(); 285 ((SwTblField*)pCurFld)->PtrToBoxNm( pTblNd ? &pTblNd->GetTable() : 0 ); 286 } 287 288 } 289 290 /* #108536# removed handling of multi-selections */ 291 292 return pCurFld; 293 } 294 295 296 /************************************************************************* 297 |* 298 |* SwEditShell::UpdateFlds() 299 |* 300 |* Beschreibung Stehen die PaMs auf Feldern ? 301 |* BP 12.05.92 302 |* 303 *************************************************************************/ 304 SwTxtFld* lcl_FindInputFld( SwDoc* pDoc, SwField& rFld ) 305 { 306 // suche das Feld ueber seine Addresse. Muss fuer InputFelder in 307 // geschuetzten Feldern erfolgen 308 SwTxtFld* pTFld = 0; 309 if( RES_INPUTFLD == rFld.Which() || ( RES_SETEXPFLD == rFld.Which() && 310 ((SwSetExpField&)rFld).GetInputFlag() ) ) 311 { 312 const SfxPoolItem* pItem; 313 sal_uInt32 n, nMaxItems = 314 pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); 315 for( n = 0; n < nMaxItems; ++n ) 316 if( 0 != (pItem = 317 pDoc->GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ) 318 && ((SwFmtFld*)pItem)->GetFld() == &rFld ) 319 { 320 pTFld = ((SwFmtFld*)pItem)->GetTxtFld(); 321 break; 322 } 323 } 324 return pTFld; 325 } 326 327 void SwEditShell::UpdateFlds( SwField &rFld ) 328 { 329 SET_CURR_SHELL( this ); 330 StartAllAction(); 331 { 332 SwField *pCurFld = 0; 333 334 // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen 335 // Cursor-Position. 336 SwMsgPoolItem* pMsgHnt = 0; 337 SwRefMarkFldUpdate aRefMkHt( GetOut() ); 338 sal_uInt16 nFldWhich = rFld.GetTyp()->Which(); 339 if( RES_GETREFFLD == nFldWhich ) 340 pMsgHnt = &aRefMkHt; 341 342 SwPaM* pCrsr = GetCrsr(); 343 SwTxtFld *pTxtFld; 344 SwFmtFld *pFmtFld; 345 346 // if( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark() && 347 // ( 0 != ( pTxtFld = GetDocTxtFld( pCrsr->Start() ) ) || 348 // 0 != ( pTxtFld = lcl_FindInputFld( GetDoc(), rFld ) ) ) && 349 // ( pFmtFld = (SwFmtFld*)&pTxtFld->GetFld())->GetFld() 350 // ->GetTyp()->Which() == rFld.GetTyp()->Which() ) 351 if ( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark()) 352 { 353 pTxtFld = GetDocTxtFld(pCrsr->Start()); 354 355 if (!pTxtFld) // #i30221# 356 pTxtFld = lcl_FindInputFld( GetDoc(), rFld); 357 358 if (pTxtFld != 0) 359 GetDoc()->UpdateFld(pTxtFld, rFld, pMsgHnt, sal_True); // #111840# 360 } 361 362 // bOkay (statt return wg. EndAllAction) wird sal_False, 363 // 1) wenn nur ein Pam mehr als ein Feld enthaelt oder 364 // 2) bei gemischten Feldtypen 365 sal_Bool bOkay = sal_True; 366 sal_Bool bTblSelBreak = sal_False; 367 368 SwMsgPoolItem aHint( RES_TXTATR_FIELD ); // Such-Hint 369 FOREACHPAM_START(this) // fuer jeden PaM 370 if( PCURCRSR->HasMark() && bOkay ) // ... mit Selektion 371 { 372 // Kopie des PaM 373 SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() ); 374 SwPaM aPam( *PCURCRSR->GetPoint() ); 375 376 SwPosition *pCurStt = aCurPam.Start(), *pCurEnd = 377 aCurPam.End(); 378 /* 379 * Fuer den Fall, dass zwei aneinanderliegende Felder in einem 380 * PaM liegen, hangelt sich aPam portionsweise bis zum Ende. 381 * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt. 382 * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End 383 * und die Schleife terminiert. 384 */ 385 386 // Suche nach SwTxtFld ... 387 while( bOkay 388 && pCurStt->nContent != pCurEnd->nContent 389 && aPam.Find( aHint, sal_False, fnMoveForward, &aCurPam ) ) 390 { 391 // wenn nur ein Pam mehr als ein Feld enthaelt ... 392 if( aPam.Start()->nContent != pCurStt->nContent ) 393 bOkay = sal_False; 394 395 if( 0 != (pTxtFld = GetDocTxtFld( pCurStt )) ) 396 { 397 pFmtFld = (SwFmtFld*)&pTxtFld->GetFld(); 398 pCurFld = pFmtFld->GetFld(); 399 400 // bei gemischten Feldtypen 401 if( pCurFld->GetTyp()->Which() != 402 rFld.GetTyp()->Which() ) 403 bOkay = sal_False; 404 405 bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld, 406 pMsgHnt, sal_False); // #111840# 407 } 408 // Der Suchbereich wird um den gefundenen Bereich 409 // verkuerzt. 410 pCurStt->nContent++; 411 } 412 } 413 414 if( bTblSelBreak ) // wenn Tabellen Selektion und Tabellen- 415 break; // Formel aktualisiert wurde -> beenden 416 417 FOREACHPAM_END() // fuer jeden PaM 418 } 419 GetDoc()->SetModified(); 420 EndAllAction(); 421 } 422 423 /*-----------------13.05.92 10:54------------------- 424 Liefert den logischen fuer die Datenbank zurueck 425 --------------------------------------------------*/ 426 427 SwDBData SwEditShell::GetDBData() const 428 { 429 return GetDoc()->GetDBData(); 430 } 431 432 const SwDBData& SwEditShell::GetDBDesc() const 433 { 434 return GetDoc()->GetDBDesc(); 435 } 436 437 void SwEditShell::ChgDBData(const SwDBData& rNewData) 438 { 439 GetDoc()->ChgDBData(rNewData); 440 } 441 442 void SwEditShell::GetAllUsedDB( SvStringsDtor& rDBNameList, 443 SvStringsDtor* pAllDBNames ) 444 { 445 GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames ); 446 } 447 448 void SwEditShell::ChangeDBFields( const SvStringsDtor& rOldNames, 449 const String& rNewName ) 450 { 451 GetDoc()->ChangeDBFields( rOldNames, rNewName ); 452 } 453 454 /*-------------------------------------------------------------------- 455 Beschreibung: Alle Expression-Felder erneuern 456 --------------------------------------------------------------------*/ 457 void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB) 458 { 459 SET_CURR_SHELL( this ); 460 StartAllAction(); 461 GetDoc()->UpdateExpFlds(NULL, true); 462 if (bCloseDB) 463 GetDoc()->GetNewDBMgr()->CloseAll(); // Alle Datenbankverbindungen dichtmachen 464 EndAllAction(); 465 } 466 467 SwNewDBMgr* SwEditShell::GetNewDBMgr() const 468 { 469 return GetDoc()->GetNewDBMgr(); 470 } 471 472 /*-------------------------------------------------------------------- 473 Beschreibung: Feldtypen einfuegen 474 --------------------------------------------------------------------*/ 475 SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType) 476 { 477 return GetDoc()->InsertFldType(rFldType); 478 } 479 480 void SwEditShell::LockExpFlds() 481 { 482 GetDoc()->LockExpFlds(); 483 } 484 485 void SwEditShell::UnlockExpFlds() 486 { 487 GetDoc()->UnlockExpFlds(); 488 } 489 490 491 void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags ) 492 { 493 getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags ); 494 } 495 496 SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const 497 { 498 return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings ); 499 } 500 501 void SwEditShell::SetFixFields( sal_Bool bOnlyTimeDate, 502 const DateTime* pNewDateTime ) 503 { 504 SET_CURR_SHELL( this ); 505 sal_Bool bUnLockView = !IsViewLocked(); 506 LockView( sal_True ); 507 StartAllAction(); 508 GetDoc()->SetFixFields( bOnlyTimeDate, pNewDateTime ); 509 EndAllAction(); 510 if( bUnLockView ) 511 LockView( sal_False ); 512 } 513 514 void SwEditShell::SetLabelDoc( sal_Bool bFlag ) 515 { 516 GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag ); 517 } 518 519 sal_Bool SwEditShell::IsLabelDoc() const 520 { 521 return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT); 522 } 523 /* -----------------------------21.12.99 12:53-------------------------------- 524 525 ---------------------------------------------------------------------------*/ 526 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData) 527 { 528 GetDoc()->ChangeAuthorityData(pNewData); 529 } 530 /* -----------------------------03.08.2001 12:04------------------------------ 531 532 ---------------------------------------------------------------------------*/ 533 sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const 534 { 535 const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes(); 536 const sal_uInt16 nSize = pFldTypes->Count(); 537 for(sal_uInt16 i = 0; i < nSize; ++i) 538 { 539 SwFieldType& rFldType = *((*pFldTypes)[i]); 540 sal_uInt16 nWhich = rFldType.Which(); 541 if(IsUsed(rFldType)) 542 { 543 switch(nWhich) 544 { 545 case RES_DBFLD: 546 case RES_DBNEXTSETFLD: 547 case RES_DBNUMSETFLD: 548 case RES_DBSETNUMBERFLD: 549 { 550 SwIterator<SwFmtFld,SwFieldType> aIter( rFldType ); 551 SwFmtFld* pFld = aIter.First(); 552 while(pFld) 553 { 554 if(pFld->IsFldInDoc()) 555 return sal_True; 556 pFld = aIter.Next(); 557 } 558 } 559 break; 560 } 561 } 562 } 563 return sal_False; 564 } 565