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