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 aInputFldHint( RES_TXTATR_INPUTFIELD ); 320 FOREACHPAM_START(this) // fuer jeden PaM 321 if( PCURCRSR->HasMark() && bOkay ) // ... mit Selektion 322 { 323 // Kopie des PaM 324 SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() ); 325 SwPaM aPam( *PCURCRSR->GetPoint() ); 326 327 SwPosition *pCurStt = aCurPam.Start(), *pCurEnd = 328 aCurPam.End(); 329 /* 330 * Fuer den Fall, dass zwei aneinanderliegende Felder in einem 331 * PaM liegen, hangelt sich aPam portionsweise bis zum Ende. 332 * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt. 333 * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End 334 * und die Schleife terminiert. 335 */ 336 337 // Suche nach SwTxtFld ... 338 while( bOkay 339 && pCurStt->nContent != pCurEnd->nContent 340 && ( aPam.Find( aFldHint, sal_False, fnMoveForward, &aCurPam ) 341 || aPam.Find( aInputFldHint, sal_False, fnMoveForward, &aCurPam ) ) ) 342 { 343 // wenn nur ein Pam mehr als ein Feld enthaelt ... 344 if( aPam.Start()->nContent != pCurStt->nContent ) 345 bOkay = sal_False; 346 347 if( 0 != (pTxtFld = GetTxtFldAtPos( pCurStt, true )) ) 348 { 349 pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld(); 350 pCurFld = pFmtFld->GetField(); 351 352 // bei gemischten Feldtypen 353 if( pCurFld->GetTyp()->Which() != 354 rFld.GetTyp()->Which() ) 355 bOkay = sal_False; 356 357 bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld, 358 pMsgHnt, sal_False); // #111840# 359 } 360 // Der Suchbereich wird um den gefundenen Bereich 361 // verkuerzt. 362 pCurStt->nContent++; 363 } 364 } 365 366 if( bTblSelBreak ) // wenn Tabellen Selektion und Tabellen- 367 break; // Formel aktualisiert wurde -> beenden 368 369 FOREACHPAM_END() // fuer jeden PaM 370 } 371 GetDoc()->SetModified(); 372 EndAllAction(); 373 } 374 375 /*-----------------13.05.92 10:54------------------- 376 Liefert den logischen fuer die Datenbank zurueck 377 --------------------------------------------------*/ 378 379 SwDBData SwEditShell::GetDBData() const 380 { 381 return GetDoc()->GetDBData(); 382 } 383 384 const SwDBData& SwEditShell::GetDBDesc() const 385 { 386 return GetDoc()->GetDBDesc(); 387 } 388 389 void SwEditShell::ChgDBData(const SwDBData& rNewData) 390 { 391 GetDoc()->ChgDBData(rNewData); 392 } 393 394 void SwEditShell::GetAllUsedDB( SvStringsDtor& rDBNameList, 395 SvStringsDtor* pAllDBNames ) 396 { 397 GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames ); 398 } 399 400 void SwEditShell::ChangeDBFields( const SvStringsDtor& rOldNames, 401 const String& rNewName ) 402 { 403 GetDoc()->ChangeDBFields( rOldNames, rNewName ); 404 } 405 406 /*-------------------------------------------------------------------- 407 Beschreibung: Alle Expression-Felder erneuern 408 --------------------------------------------------------------------*/ 409 void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB) 410 { 411 SET_CURR_SHELL( this ); 412 StartAllAction(); 413 GetDoc()->UpdateExpFlds(NULL, true); 414 if (bCloseDB) 415 GetDoc()->GetNewDBMgr()->CloseAll(); // Alle Datenbankverbindungen dichtmachen 416 EndAllAction(); 417 } 418 419 SwNewDBMgr* SwEditShell::GetNewDBMgr() const 420 { 421 return GetDoc()->GetNewDBMgr(); 422 } 423 424 /*-------------------------------------------------------------------- 425 Beschreibung: Feldtypen einfuegen 426 --------------------------------------------------------------------*/ 427 SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType) 428 { 429 return GetDoc()->InsertFldType(rFldType); 430 } 431 432 void SwEditShell::LockExpFlds() 433 { 434 GetDoc()->LockExpFlds(); 435 } 436 437 void SwEditShell::UnlockExpFlds() 438 { 439 GetDoc()->UnlockExpFlds(); 440 } 441 442 443 void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags ) 444 { 445 getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags ); 446 } 447 448 SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const 449 { 450 return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings ); 451 } 452 453 void SwEditShell::SetFixFields( sal_Bool bOnlyTimeDate, 454 const DateTime* pNewDateTime ) 455 { 456 SET_CURR_SHELL( this ); 457 sal_Bool bUnLockView = !IsViewLocked(); 458 LockView( sal_True ); 459 StartAllAction(); 460 GetDoc()->SetFixFields( bOnlyTimeDate, pNewDateTime ); 461 EndAllAction(); 462 if( bUnLockView ) 463 LockView( sal_False ); 464 } 465 466 void SwEditShell::SetLabelDoc( sal_Bool bFlag ) 467 { 468 GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag ); 469 } 470 471 sal_Bool SwEditShell::IsLabelDoc() const 472 { 473 return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT); 474 } 475 /* -----------------------------21.12.99 12:53-------------------------------- 476 477 ---------------------------------------------------------------------------*/ 478 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData) 479 { 480 GetDoc()->ChangeAuthorityData(pNewData); 481 } 482 /* -----------------------------03.08.2001 12:04------------------------------ 483 484 ---------------------------------------------------------------------------*/ 485 sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const 486 { 487 const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes(); 488 const sal_uInt16 nSize = pFldTypes->Count(); 489 for(sal_uInt16 i = 0; i < nSize; ++i) 490 { 491 SwFieldType& rFldType = *((*pFldTypes)[i]); 492 sal_uInt16 nWhich = rFldType.Which(); 493 if(IsUsed(rFldType)) 494 { 495 switch(nWhich) 496 { 497 case RES_DBFLD: 498 case RES_DBNEXTSETFLD: 499 case RES_DBNUMSETFLD: 500 case RES_DBSETNUMBERFLD: 501 { 502 SwIterator<SwFmtFld,SwFieldType> aIter( rFldType ); 503 SwFmtFld* pFld = aIter.First(); 504 while(pFld) 505 { 506 if(pFld->IsFldInDoc()) 507 return sal_True; 508 pFld = aIter.Next(); 509 } 510 } 511 break; 512 } 513 } 514 } 515 return sal_False; 516 } 517