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