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 #include <com/sun/star/chart2/XChartDocument.hpp> 28 #include <hintids.hxx> 29 #include <hints.hxx> 30 31 #define _SVSTDARR_ULONGS 32 #include <svl/svstdarr.hxx> 33 34 #include <vcl/svapp.hxx> 35 #include <vcl/window.hxx> 36 #include <editeng/boxitem.hxx> 37 #include <swwait.hxx> 38 #include <fmtfsize.hxx> 39 #include <frmatr.hxx> 40 #include <editsh.hxx> 41 #include <doc.hxx> 42 #include <IDocumentUndoRedo.hxx> 43 #include <cntfrm.hxx> 44 #include <pam.hxx> 45 #include <ndtxt.hxx> 46 #include <fldbas.hxx> 47 #include <swtable.hxx> 48 #include <swundo.hxx> 49 #include <tblsel.hxx> 50 #include <edimp.hxx> 51 #include <tabfrm.hxx> 52 #include <cellfrm.hxx> 53 #include <cellatr.hxx> 54 #include <swtblfmt.hxx> 55 #include <swddetbl.hxx> 56 #include <mdiexp.hxx> 57 #include <unochart.hxx> 58 59 using namespace ::com::sun::star; 60 using namespace ::com::sun::star::uno; 61 62 extern void ClearFEShellTabCols(); 63 64 const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts, 65 sal_uInt16 nRows, sal_uInt16 nCols, 66 sal_Int16 eAdj, 67 const SwTableAutoFmt* pTAFmt ) 68 { 69 StartAllAction(); 70 SwPosition* pPos = GetCrsr()->GetPoint(); 71 72 sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex(); 73 if( bEndUndo ) 74 { 75 StartUndo( UNDO_START ); 76 GetDoc()->SplitNode( *pPos, false ); 77 } 78 79 /* #109161# If called from a shell the adjust item is propagated 80 from pPos to the new content nodes in the table. 81 */ 82 const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos, 83 nRows, nCols, 84 eAdj, pTAFmt, 85 0, sal_True ); 86 if( bEndUndo ) 87 EndUndo( UNDO_END ); 88 89 EndAllAction(); 90 return *pTable; 91 } 92 93 sal_Bool SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts, 94 sal_Unicode cCh, 95 sal_Int16 eAdj, 96 const SwTableAutoFmt* pTAFmt ) 97 { 98 SwWait aWait( *GetDoc()->GetDocShell(), sal_True ); 99 sal_Bool bRet = sal_False; 100 StartAllAction(); 101 FOREACHPAM_START(this) 102 if( PCURCRSR->HasMark() ) 103 bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh, 104 eAdj, pTAFmt ); 105 FOREACHPAM_END() 106 EndAllAction(); 107 return bRet; 108 } 109 110 sal_Bool SwEditShell::TableToText( sal_Unicode cCh ) 111 { 112 SwWait aWait( *GetDoc()->GetDocShell(), sal_True ); 113 sal_Bool bRet = sal_False; 114 SwPaM* pCrsr = GetCrsr(); 115 const SwTableNode* pTblNd = 116 GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode ); 117 if( IsTableMode() ) 118 { 119 ClearMark(); 120 pCrsr = GetCrsr(); 121 } 122 else if( !pTblNd || pCrsr->GetNext() != pCrsr ) 123 return bRet; 124 125 // TL_CHART2: 126 // tell the charts about the table to be deleted and have them use their own data 127 GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() ); 128 129 StartAllAction(); 130 131 // verschiebe den akt. Cursor aus dem Tabellen Bereich 132 // angemeldet ist 133 SwNodeIndex aTabIdx( *pTblNd ); 134 pCrsr->DeleteMark(); 135 pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); 136 pCrsr->GetPoint()->nContent.Assign( 0, 0 ); 137 // SPoint und Mark aus dem Bereich verschieben !!! 138 pCrsr->SetMark(); 139 pCrsr->DeleteMark(); 140 141 bRet = GetDoc()->TableToText( pTblNd, cCh ); 142 pCrsr->GetPoint()->nNode = aTabIdx; 143 144 SwCntntNode* pCNd = pCrsr->GetCntntNode(); 145 if( !pCNd ) 146 pCrsr->Move( fnMoveForward, fnGoCntnt ); 147 else 148 pCrsr->GetPoint()->nContent.Assign( pCNd, 0 ); 149 150 EndAllAction(); 151 return bRet; 152 } 153 154 sal_Bool SwEditShell::IsTextToTableAvailable() const 155 { 156 sal_Bool bOnlyText = sal_False; 157 FOREACHPAM_START(this) 158 if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ) 159 { 160 bOnlyText = sal_True; 161 162 // pruefe ob in der Selection eine Tabelle liegt 163 sal_uLong nStt = PCURCRSR->GetMark()->nNode.GetIndex(), 164 nEnd = PCURCRSR->GetPoint()->nNode.GetIndex(); 165 if( nStt > nEnd ) { sal_uLong n = nStt; nStt = nEnd; nEnd = n; } 166 167 for( ; nStt <= nEnd; ++nStt ) 168 if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() ) 169 { 170 bOnlyText = sal_False; 171 break; 172 } 173 174 if( !bOnlyText ) 175 break; 176 } 177 FOREACHPAM_END() 178 179 return bOnlyText; 180 } 181 182 void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts, 183 SwDDEFieldType* pDDEType, 184 sal_uInt16 nRows, sal_uInt16 nCols, 185 sal_Int16 eAdj ) 186 { 187 SwPosition* pPos = GetCrsr()->GetPoint(); 188 189 StartAllAction(); 190 191 sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex(); 192 if( bEndUndo ) 193 { 194 StartUndo( UNDO_START ); 195 GetDoc()->SplitNode( *pPos, false ); 196 } 197 198 const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER, 199 rInsTblOpts.mnRowsToRepeat ); 200 SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos, 201 nRows, nCols, eAdj ); 202 203 SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]-> 204 GetSttNd()->FindTableNode(); 205 SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType ); 206 pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle 207 208 if( bEndUndo ) 209 EndUndo( UNDO_END ); 210 211 EndAllAction(); 212 } 213 214 /*-------------------------------------------------------------------- 215 Beschreibung: Tabellenfelder einer Tabelle updaten 216 --------------------------------------------------------------------*/ 217 void SwEditShell::UpdateTable() 218 { 219 const SwTableNode* pTblNd = IsCrsrInTbl(); 220 221 // Keine Arme keine Kekse 222 if( pTblNd ) 223 { 224 StartAllAction(); 225 if( DoesUndo() ) 226 StartUndo(); 227 EndAllTblBoxEdit(); 228 SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() ); 229 GetDoc()->UpdateTblFlds( &aTblUpdate ); 230 if( DoesUndo() ) 231 EndUndo(); 232 EndAllAction(); 233 } 234 } 235 236 // Change Modus erfragen/setzen 237 TblChgMode SwEditShell::GetTblChgMode() const 238 { 239 TblChgMode eMode; 240 const SwTableNode* pTblNd = IsCrsrInTbl(); 241 if( pTblNd ) 242 eMode = pTblNd->GetTable().GetTblChgMode(); 243 else 244 eMode = GetTblChgDefaultMode(); 245 return eMode; 246 } 247 248 void SwEditShell::SetTblChgMode( TblChgMode eMode ) 249 { 250 const SwTableNode* pTblNd = IsCrsrInTbl(); 251 252 // Keine Arme keine Kekse 253 if( pTblNd ) 254 { 255 ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode ); 256 if( !GetDoc()->IsModified() ) // Bug 57028 257 { 258 GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified(); 259 } 260 GetDoc()->SetModified(); 261 } 262 } 263 264 sal_Bool SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const 265 { 266 SwSelBoxes aBoxes; 267 if( IsTableMode() ) 268 ::GetTblSelCrs( *this, aBoxes ); 269 else 270 { 271 do { 272 SwFrm *pFrm = GetCurrFrm(); 273 do { 274 pFrm = pFrm->GetUpper(); 275 } while ( pFrm && !pFrm->IsCellFrm() ); 276 if ( pFrm ) 277 { 278 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); 279 aBoxes.Insert( pBox ); 280 } 281 } while( sal_False ); 282 } 283 284 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) 285 { 286 const SwTableBox* pSelBox = aBoxes[ n ]; 287 const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); 288 if( !n ) 289 { 290 // Formeln in die externe Darstellung bringen! 291 const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable(); 292 293 SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl ); 294 aTblUpdate.eFlags = TBL_BOXNAME; 295 ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate ); 296 297 rSet.Put( pTblFmt->GetAttrSet() ); 298 } 299 else 300 rSet.MergeValues( pTblFmt->GetAttrSet() ); 301 } 302 return 0 != rSet.Count(); 303 } 304 305 void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet ) 306 { 307 SET_CURR_SHELL( this ); 308 SwSelBoxes aBoxes; 309 if( IsTableMode() ) 310 ::GetTblSelCrs( *this, aBoxes ); 311 else 312 { 313 do { 314 SwFrm *pFrm = GetCurrFrm(); 315 do { 316 pFrm = pFrm->GetUpper(); 317 } while ( pFrm && !pFrm->IsCellFrm() ); 318 if ( pFrm ) 319 { 320 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); 321 aBoxes.Insert( pBox ); 322 } 323 } while( sal_False ); 324 } 325 326 // beim setzen einer Formel keine Ueberpruefung mehr vornehmen! 327 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA )) 328 ClearTblBoxCntnt(); 329 330 StartAllAction(); 331 GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 332 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) 333 GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet ); 334 GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); 335 EndAllAction(); 336 } 337 338 sal_Bool SwEditShell::IsTableBoxTextFormat() const 339 { 340 if( IsTableMode() ) 341 return sal_False; 342 343 SwTableBox *pBox = 0; 344 { 345 SwFrm *pFrm = GetCurrFrm(); 346 do { 347 pFrm = pFrm->GetUpper(); 348 } while ( pFrm && !pFrm->IsCellFrm() ); 349 if ( pFrm ) 350 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); 351 } 352 353 if( !pBox ) 354 return sal_False; 355 356 sal_uInt32 nFmt; 357 const SfxPoolItem* pItem; 358 if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState( 359 RES_BOXATR_FORMAT, sal_True, &pItem )) 360 { 361 nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue(); 362 return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) || 363 NUMBERFORMAT_TEXT == nFmt; 364 } 365 366 sal_uLong nNd = pBox->IsValidNumTxtNd(); 367 if( ULONG_MAX == nNd ) 368 return sal_True; 369 370 const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt(); 371 if( !rTxt.Len() ) 372 return sal_False; 373 374 double fVal; 375 return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal ); 376 } 377 378 String SwEditShell::GetTableBoxText() const 379 { 380 String sRet; 381 if( !IsTableMode() ) 382 { 383 SwTableBox *pBox = 0; 384 { 385 SwFrm *pFrm = GetCurrFrm(); 386 do { 387 pFrm = pFrm->GetUpper(); 388 } while ( pFrm && !pFrm->IsCellFrm() ); 389 if ( pFrm ) 390 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); 391 } 392 393 sal_uLong nNd; 394 if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) ) 395 sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt(); 396 } 397 return sRet; 398 } 399 400 sal_Bool SwEditShell::SplitTable( sal_uInt16 eMode ) 401 { 402 sal_Bool bRet = sal_False; 403 SwPaM *pCrsr = GetCrsr(); 404 if( pCrsr->GetNode()->FindTableNode() ) 405 { 406 StartAllAction(); 407 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); 408 409 bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, sal_True ); 410 411 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); 412 ClearFEShellTabCols(); 413 EndAllAction(); 414 } 415 return bRet; 416 } 417 418 sal_Bool SwEditShell::MergeTable( sal_Bool bWithPrev, sal_uInt16 nMode ) 419 { 420 sal_Bool bRet = sal_False; 421 SwPaM *pCrsr = GetCrsr(); 422 if( pCrsr->GetNode()->FindTableNode() ) 423 { 424 StartAllAction(); 425 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); 426 427 bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode ); 428 429 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); 430 ClearFEShellTabCols(); 431 EndAllAction(); 432 } 433 return bRet; 434 } 435 436 sal_Bool SwEditShell::CanMergeTable( sal_Bool bWithPrev, sal_Bool* pChkNxtPrv ) const 437 { 438 sal_Bool bRet = sal_False; 439 const SwPaM *pCrsr = GetCrsr(); 440 const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode(); 441 if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable )) 442 { 443 sal_Bool bNew = pTblNd->GetTable().IsNewModel(); 444 const SwNodes& rNds = GetDoc()->GetNodes(); 445 if( pChkNxtPrv ) 446 { 447 const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode(); 448 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) && 449 bNew == pChkNd->GetTable().IsNewModel() && 450 // --> FME 2004-09-17 #117418# Consider table in table case 451 pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 ) 452 // <-- 453 *pChkNxtPrv = sal_True, bRet = sal_True; // mit Prev ist moeglich 454 else 455 { 456 pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode(); 457 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) && 458 bNew == pChkNd->GetTable().IsNewModel() ) 459 *pChkNxtPrv = sal_False, bRet = sal_True; // mit Next ist moeglich 460 } 461 } 462 else 463 { 464 const SwTableNode* pTmpTblNd = 0; 465 466 if( bWithPrev ) 467 { 468 pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode(); 469 // --> FME 2004-09-17 #117418# Consider table in table case 470 if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 ) 471 pTmpTblNd = 0; 472 // <-- 473 } 474 else 475 pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode(); 476 477 bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) && 478 bNew == pTmpTblNd->GetTable().IsNewModel(); 479 } 480 } 481 return bRet; 482 } 483 484 // setze das InsertDB als Tabelle Undo auf: 485 void SwEditShell::AppendUndoForInsertFromDB( sal_Bool bIsTable ) 486 { 487 GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable ); 488 } 489 490