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 #if STLPORT_VERSION>=321 29 #include <cstdarg> 30 #endif 31 32 33 #include <hintids.hxx> 34 35 #include <sfx2/request.hxx> 36 #include <svx/svxids.hrc> 37 38 #include <svtools/svmedit.hxx> 39 #include <vcl/svapp.hxx> 40 #include <vcl/wrkwin.hxx> 41 #include <sfx2/app.hxx> 42 #include <sfx2/docfac.hxx> 43 #include <sfx2/printer.hxx> 44 #include <vcl/msgbox.hxx> 45 #include <sfx2/dispatch.hxx> 46 #include <editeng/boxitem.hxx> 47 #include <editeng/lrspitem.hxx> 48 #include <editeng/ulspitem.hxx> 49 #include <editeng/pbinitem.hxx> 50 #include <editeng/paperinf.hxx> 51 #include <editeng/brkitem.hxx> 52 #include <fmthdft.hxx> 53 #include <swwait.hxx> 54 #include <paratr.hxx> 55 #include <swmodule.hxx> 56 #include <wrtsh.hxx> 57 #include <view.hxx> 58 #include <docsh.hxx> 59 #include <frmatr.hxx> 60 #include <fldbas.hxx> 61 #include <swundo.hxx> 62 #include <IDocumentDeviceAccess.hxx> 63 #include <dbmgr.hxx> 64 #include <fmtcol.hxx> 65 #include <frmmgr.hxx> 66 #include <fldmgr.hxx> 67 #include <pagedesc.hxx> 68 #include <poolfmt.hxx> 69 #include <expfld.hxx> 70 #include <SwStyleNameMapper.hxx> 71 #include <crsskip.hxx> 72 73 #include <cmdid.h> 74 #ifndef _GLOBALS_HRC 75 #include <globals.hrc> 76 #endif 77 #ifndef _APP_HRC 78 #include <app.hrc> 79 #endif 80 #ifndef _POOLFMT_HRC 81 #include <poolfmt.hrc> 82 #endif 83 #include "swabstdlg.hxx" 84 #include "envelp.hrc" 85 #include "envimg.hxx" 86 87 #define ENV_NEWDOC RET_OK 88 #define ENV_INSERT RET_USER 89 #define ENV_CANCEL SHRT_MAX 90 91 92 // -------------------------------------------------------------------------- 93 94 95 // Funktion wird fuer Etiketten und Briefumschlaege benutzt! 96 // im applab.cxx und appenv.cxx 97 String InsertLabEnvText( SwWrtShell& rSh, SwFldMgr& rFldMgr, const String& rText ) 98 { 99 String sRet; 100 String aText(rText); 101 aText.EraseAllChars( '\r' ); 102 103 104 sal_uInt16 nTokenPos = 0; 105 while( STRING_NOTFOUND != nTokenPos ) 106 { 107 String aLine = aText.GetToken( 0, '\n', nTokenPos ); 108 while ( aLine.Len() ) 109 { 110 String sTmpText; 111 sal_Bool bField = sal_False; 112 113 sal_uInt16 nPos = aLine.Search( '<' ); 114 if ( nPos ) 115 { 116 sTmpText = aLine.Copy( 0, nPos ); 117 aLine.Erase( 0, nPos ); 118 // sTmpText = aLine.Cut( 0, nPos ); 119 } 120 else 121 { 122 nPos = aLine.Search( '>' ); 123 if ( nPos == STRING_NOTFOUND ) 124 { 125 sTmpText = aLine; 126 aLine.Erase(); 127 // sTmpText = aLine.Cut(); 128 } 129 else 130 { 131 sTmpText = aLine.Copy( 0, nPos + 1); 132 aLine.Erase( 0, nPos + 1); 133 // sTmpText = aLine.Cut( 0, nPos + 1 ); 134 135 // Datenbankfelder muesen mind. 3 Punkte beinhalten! 136 String sDBName( sTmpText.Copy( 1, sTmpText.Len() - 2)); 137 sal_uInt16 nCnt = sDBName.GetTokenCount('.'); 138 if (nCnt >= 3) 139 { 140 ::ReplacePoint(sDBName, sal_True); 141 SwInsertFld_Data aData(TYP_DBFLD, 0, sDBName, aEmptyStr, 0, &rSh ); 142 rFldMgr.InsertFld( aData ); 143 sRet = sDBName; 144 bField = sal_True; 145 } 146 } 147 } 148 if ( !bField ) 149 rSh.Insert( sTmpText ); 150 } 151 rSh.InsertLineBreak(); 152 } 153 rSh.DelLeft(); // Letzten Linebreak wieder l???schen 154 155 return sRet; 156 } 157 158 // ---------------------------------------------------------------------------- 159 160 161 void lcl_CopyCollAttr(SwWrtShell* pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId) 162 { 163 sal_uInt16 nCollCnt = pOldSh->GetTxtFmtCollCount(); 164 SwTxtFmtColl* pColl; 165 for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt ) 166 if(nCollId == (pColl = &pOldSh->GetTxtFmtColl(nCnt))->GetPoolFmtId()) 167 pNewSh->GetTxtCollFromPool(nCollId)->SetFmtAttr(pColl->GetAttrSet()); 168 } 169 170 // ---------------------------------------------------------------------------- 171 172 173 void SwModule::InsertEnv( SfxRequest& rReq ) 174 { 175 static sal_uInt16 nTitleNo = 0; 176 177 SwDocShell *pMyDocSh; 178 SfxViewFrame *pFrame; 179 SwView *pNewView; 180 SwWrtShell *pOldSh, 181 *pSh; 182 183 //aktuelle Shell besorgen 184 pMyDocSh = (SwDocShell*) SfxObjectShell::Current(); 185 pOldSh = pMyDocSh ? pMyDocSh->GetWrtShell() : 0; 186 187 // Neues Dokument erzeugen (kein Show!) 188 SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_STANDARD ) ); 189 xDocSh->DoInitNew( 0 ); 190 pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 ); 191 pNewView = (SwView*) pFrame->GetViewShell(); 192 pNewView->AttrChangedNotify( &pNewView->GetWrtShell() );//Damit SelectShell gerufen wird. 193 pSh = pNewView->GetWrtShellPtr(); 194 195 String aTmp( SW_RES(STR_ENV_TITLE) ); 196 aTmp += String::CreateFromInt32( ++nTitleNo ); 197 xDocSh->SetTitle( aTmp ); 198 199 // Ggf. alte Collections "Absender" und "Empfaenger" in neues 200 // Dokument kopieren 201 if ( pOldSh ) 202 { 203 ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS); 204 ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS); 205 } 206 207 // SwEnvItem aus Config lesen 208 SwEnvCfgItem aEnvCfg; 209 210 //Haben wir schon einen Briefumschlag. 211 sal_Bool bEnvChange = sal_False; 212 213 SfxItemSet aSet(GetPool(), FN_ENVELOP, FN_ENVELOP, 0); 214 aSet.Put(aEnvCfg.GetItem()); 215 216 SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess()->getPrinter( true ); 217 if(pOldSh ) 218 { 219 const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc()); 220 String sJacket; 221 SwStyleNameMapper::FillUIName( RES_POOLPAGE_JAKET, sJacket ); 222 bEnvChange = rCurPageDesc.GetName() == sJacket; 223 224 IDocumentDeviceAccess* pIDDA_old = pOldSh->getIDocumentDeviceAccess(); 225 if( pIDDA_old->getPrinter( false ) ) 226 { 227 IDocumentDeviceAccess* pIDDA = pSh->getIDocumentDeviceAccess(); 228 pIDDA->setJobsetup( *pIDDA_old->getJobsetup() ); 229 //#69563# if it isn't the same printer then the pointer has been invalidated! 230 pTempPrinter = pIDDA->getPrinter( true ); 231 } 232 pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue()); 233 234 } 235 236 Window *pParent = pOldSh ? pOldSh->GetWin() : 0; 237 SfxAbstractTabDialog * pDlg=NULL; 238 short nMode = ENV_INSERT; 239 240 SFX_REQUEST_ARG( rReq, pItem, SwEnvItem, FN_ENVELOP, sal_False ); 241 if ( !pItem ) 242 { 243 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); 244 DBG_ASSERT(pFact, "SwAbstractDialogFactory fail!"); 245 246 pDlg = pFact->CreateSwEnvDlg( pParent, aSet, pOldSh, pTempPrinter, !bEnvChange, DLG_ENV ); 247 DBG_ASSERT(pDlg, "Dialogdiet fail!"); 248 nMode = pDlg->Execute(); 249 } 250 else 251 { 252 SFX_REQUEST_ARG( rReq, pBoolItem, SfxBoolItem, FN_PARAM_1, sal_False ); 253 if ( pBoolItem && pBoolItem->GetValue() ) 254 nMode = ENV_NEWDOC; 255 } 256 257 if (nMode == ENV_NEWDOC || nMode == ENV_INSERT) 258 { 259 SwWait aWait( (SwDocShell&)*xDocSh, sal_True ); 260 261 // Dialog auslesen, Item in Config speichern 262 const SwEnvItem& rItem = pItem ? *pItem : (const SwEnvItem&) pDlg->GetOutputItemSet()->Get(FN_ENVELOP); 263 aEnvCfg.GetItem() = rItem; 264 aEnvCfg.Commit(); 265 266 //Wenn wir Drucken uebernehmen wir den eingestellten Jobsetup aus 267 //dem Dialog. Die Informationen muessen hier vor dem evtl. zerstoeren 268 //der neuen Shell gesetzt werden, weil deren Drucker an den Dialog 269 //gereicht wurde. 270 if ( nMode != ENV_NEWDOC ) 271 { 272 ASSERT(pOldSh, "Kein Dokument - war 'Einfuegen' nicht disabled???"); 273 SvxPaperBinItem aItem( RES_PAPER_BIN ); 274 aItem.SetValue((sal_uInt8)pSh->getIDocumentDeviceAccess()->getPrinter(true)->GetPaperBin()); 275 pOldSh->GetPageDescFromPool(RES_POOLPAGE_JAKET)->GetMaster().SetFmtAttr(aItem); 276 } 277 278 SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh; 279 const SwPageDesc* pFollow = 0; 280 SwTxtFmtColl *pSend = pTmp->GetTxtCollFromPool( RES_POOLCOLL_SENDADRESS ), 281 *pAddr = pTmp->GetTxtCollFromPool( RES_POOLCOLL_JAKETADRESS); 282 const String &rSendMark = pSend->GetName(); 283 const String &rAddrMark = pAddr->GetName(); 284 285 if (nMode == ENV_INSERT) 286 { 287 288 SetView(&pOldSh->GetView()); // Pointer auf oberste View restaurieren 289 290 //Neues Dok wieder loeschen 291 xDocSh->DoClose(); 292 pSh = pOldSh; 293 //#i4251# selected text or objects in the document should 294 //not be deleted on inserting envelopes 295 pSh->EnterStdMode(); 296 // Los geht's (Einfuegen) 297 pSh->StartUndo(UNDO_UI_INSERT_ENVELOPE, NULL); 298 pSh->StartAllAction(); 299 pSh->SttEndDoc(sal_True); 300 301 if (bEnvChange) 302 { 303 // Folgevorlage: Seite 2 304 pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow(); 305 306 // Text der ersten Seite loeschen 307 if ( !pSh->SttNxtPg(sal_True) ) 308 pSh->EndPg(sal_True); 309 pSh->DelRight(); 310 // Rahmen der ersten Seite loeschen 311 if( pSh->GotoFly( rSendMark ) ) 312 { 313 pSh->EnterSelFrmMode(); 314 pSh->DelRight(); 315 } 316 if ( pSh->GotoFly( rAddrMark ) ) 317 { 318 pSh->EnterSelFrmMode(); 319 pSh->DelRight(); 320 } 321 pSh->SttEndDoc(sal_True); 322 } 323 else 324 // Folgevorlage: Seite 1 325 pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc()); 326 327 // Seitenumbruch einfuegen 328 if ( pSh->IsCrsrInTbl() ) 329 { 330 pSh->SplitNode(); 331 pSh->Right( CRSR_SKIP_CHARS, sal_False, 1, sal_False ); 332 SfxItemSet aBreakSet( pSh->GetAttrPool(), RES_BREAK, RES_BREAK, 0 ); 333 aBreakSet.Put( SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) ); 334 pSh->SetTblAttr( aBreakSet ); 335 } 336 else 337 pSh->InsertPageBreak(0, sal_False); 338 pSh->SttEndDoc(sal_True); 339 } 340 else 341 { 342 pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc()); 343 // Los geht's (Drucken) 344 pSh->StartAllAction(); 345 pSh->DoUndo(sal_False); 346 347 // Neue Collections "Absender" und "Empfaenger" wieder in neues 348 // Dokument kopieren 349 if ( pOldSh ) 350 { 351 ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS); 352 ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS); 353 } 354 } 355 356 SET_CURR_SHELL(pSh); 357 pSh->SetNewDoc(); // Performanceprobleme vermeiden 358 359 // Flys dieser Seite merken 360 SvPtrarr aFlyArr(0, 5); 361 if( ENV_NEWDOC != nMode && !bEnvChange ) 362 pSh->GetPageObjs( aFlyArr ); 363 364 // Page-Desc ermitteln 365 SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_JAKET); 366 SwFrmFmt& rFmt = pDesc->GetMaster(); 367 368 Printer *pPrt = pSh->getIDocumentDeviceAccess()->getPrinter( true ); 369 370 // Raender (setzen sich zusammen aus Shift-Offset und 371 // Ausrichtung) 372 Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(), 373 MAP_TWIP); 374 if ( !aPaperSize.Width() && !aPaperSize.Height() ) 375 aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4); 376 if ( aPaperSize.Width() > aPaperSize.Height() ) 377 Swap( aPaperSize ); 378 379 long lLeft = rItem.lShiftRight, 380 lUpper = rItem.lShiftDown; 381 382 sal_uInt16 nPageW = (sal_uInt16) Max(rItem.lWidth, rItem.lHeight), 383 nPageH = (sal_uInt16) Min(rItem.lWidth, rItem.lHeight); 384 385 switch (rItem.eAlign) 386 { 387 case ENV_HOR_LEFT: break; 388 case ENV_HOR_CNTR: lLeft += Max(0L, long(aPaperSize.Width() - nPageW)) / 2; 389 break; 390 case ENV_HOR_RGHT: lLeft += Max(0L, long(aPaperSize.Width() - nPageW)); 391 break; 392 case ENV_VER_LEFT: lUpper += Max(0L, long(aPaperSize.Width() - nPageH)); 393 break; 394 case ENV_VER_CNTR: lUpper += Max(0L, long(aPaperSize.Width() - nPageH)) / 2; 395 break; 396 case ENV_VER_RGHT: break; 397 } 398 SvxLRSpaceItem aLRMargin( RES_LR_SPACE ); 399 SvxULSpaceItem aULMargin( RES_UL_SPACE ); 400 aLRMargin.SetLeft ((sal_uInt16) lLeft ); 401 aULMargin.SetUpper((sal_uInt16) lUpper); 402 aLRMargin.SetRight(0); 403 aULMargin.SetLower(0); 404 rFmt.SetFmtAttr(aLRMargin); 405 rFmt.SetFmtAttr(aULMargin); 406 407 // Kopf-, Fusszeilen 408 rFmt.SetFmtAttr(SwFmtHeader(sal_Bool(sal_False))); 409 pDesc->ChgHeaderShare(sal_False); 410 rFmt.SetFmtAttr(SwFmtFooter(sal_Bool(sal_False))); 411 pDesc->ChgFooterShare(sal_False); 412 413 // Seitennumerierung 414 pDesc->SetUseOn(nsUseOnPage::PD_ALL); 415 416 // Einstellen der Seitengroesse 417 rFmt.SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE, 418 nPageW + lLeft, nPageH + lUpper)); 419 420 // Einstellen der Numerierungsart der Seite 421 SvxNumberType aType; 422 aType.SetNumberingType(SVX_NUM_NUMBER_NONE); 423 pDesc->SetNumType(aType); 424 425 // Folgevorlage 426 if (pFollow) 427 pDesc->SetFollow(pFollow); 428 429 // Landscape 430 pDesc->SetLandscape( rItem.eAlign >= ENV_VER_LEFT && 431 rItem.eAlign <= ENV_VER_RGHT); 432 433 // Page-Desc anwenden 434 435 sal_uInt16 nPos; 436 pSh->FindPageDescByName( pDesc->GetName(), 437 sal_False, 438 &nPos ); 439 440 441 pSh->ChgPageDesc( nPos, *pDesc); 442 pSh->ChgCurPageDesc(*pDesc); 443 444 // Rahmen einfuegen 445 SwFlyFrmAttrMgr aMgr(sal_False, pSh, FRMMGR_TYPE_ENVELP); 446 SwFldMgr aFldMgr; 447 aMgr.SetHeightSizeType(ATT_VAR_SIZE); 448 449 //Defaults ueberschreiben! 450 aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) ); 451 aMgr.SetULSpace( 0L, 0L ); 452 aMgr.SetLRSpace( 0L, 0L ); 453 454 // Absender 455 if (rItem.bSend) 456 { 457 pSh->SttEndDoc(sal_True); 458 aMgr.InsertFlyFrm(FLY_AT_PAGE, 459 Point(rItem.lSendFromLeft + lLeft, rItem.lSendFromTop + lUpper), 460 Size (rItem.lAddrFromLeft - rItem.lSendFromLeft, 0)); 461 462 pSh->EnterSelFrmMode(); 463 pSh->SetFlyName( rSendMark ); 464 pSh->UnSelectFrm(); 465 pSh->LeaveSelFrmMode(); 466 pSh->SetTxtFmtColl( pSend ); 467 InsertLabEnvText( *pSh, aFldMgr, rItem.aSendText ); 468 aMgr.UpdateAttrMgr(); 469 } 470 471 // Empfaenger 472 pSh->SttEndDoc(sal_True); 473 474 aMgr.InsertFlyFrm(FLY_AT_PAGE, 475 Point(rItem.lAddrFromLeft + lLeft, rItem.lAddrFromTop + lUpper), 476 Size (nPageW - rItem.lAddrFromLeft - 566, 0)); 477 pSh->EnterSelFrmMode(); 478 pSh->SetFlyName( rAddrMark ); 479 pSh->UnSelectFrm(); 480 pSh->LeaveSelFrmMode(); 481 pSh->SetTxtFmtColl( pAddr ); 482 InsertLabEnvText(*pSh, aFldMgr, rItem.aAddrText); 483 484 // Flys auf die "alten" Seiten verschieben 485 if (aFlyArr.Count()) 486 pSh->SetPageObjsNewPage(aFlyArr, 1); 487 488 // Fertig 489 pSh->SttEndDoc(sal_True); 490 491 pSh->EndAllAction(); 492 493 if (nMode == ENV_NEWDOC) 494 pSh->DoUndo(sal_True); 495 else 496 pSh->EndUndo(UNDO_UI_INSERT_ENVELOPE); 497 498 if (nMode == ENV_NEWDOC) 499 { 500 pFrame->GetFrame().Appear(); 501 502 if ( rItem.aAddrText.indexOf('<') >= 0 ) 503 { 504 static sal_uInt16 __READONLY_DATA aInva[] = 505 { 506 SID_SBA_BRW_UPDATE, 507 SID_SBA_BRW_INSERT, 508 SID_SBA_BRW_MERGE, 509 0 510 }; 511 pFrame->GetBindings().Invalidate( aInva ); 512 513 // Datenbankbeamer oeffnen 514 ShowDBObj(*pNewView, pSh->GetDBData()); 515 } 516 } 517 518 if ( !pItem ) 519 { 520 rReq.AppendItem( rItem ); 521 if ( nMode == ENV_NEWDOC ) 522 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, sal_True ) ); 523 } 524 525 rReq.Done(); 526 } 527 else //Abbruch 528 { 529 rReq.Ignore(); 530 531 xDocSh->DoClose(); 532 --nTitleNo; 533 534 // Pointer auf oberste View restaurieren 535 if (pOldSh) 536 SetView(&pOldSh->GetView()); 537 } 538 delete pDlg; 539 } 540 541 542