Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 : #include <svl/macitem.hxx>
22 : #include <sfx2/frame.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <svl/urihelper.hxx>
25 : #include <svl/eitem.hxx>
26 : #include <svl/stritem.hxx>
27 : #include <sfx2/docfile.hxx>
28 : #include <sfx2/fcontnr.hxx>
29 : #include <sfx2/dispatch.hxx>
30 : #include <sfx2/linkmgr.hxx>
31 : #include <fmtinfmt.hxx>
32 : #include <frmatr.hxx>
33 : #include <swtypes.hxx>
34 : #include <wrtsh.hxx>
35 : #include <docsh.hxx>
36 : #include <fldbas.hxx>
37 : #include <expfld.hxx>
38 : #include <ddefld.hxx>
39 : #include <docufld.hxx>
40 : #include <reffld.hxx>
41 : #include <swundo.hxx>
42 : #include <doc.hxx>
43 : #include <IDocumentUndoRedo.hxx>
44 : #include <viewopt.hxx>
45 : #include <frmfmt.hxx>
46 : #include <swtable.hxx>
47 : #include <mdiexp.hxx>
48 : #include <view.hxx>
49 : #include <swevent.hxx>
50 : #include <poolfmt.hxx>
51 : #include <section.hxx>
52 : #include <navicont.hxx>
53 : #include <navipi.hxx>
54 : #include <crsskip.hxx>
55 : #include <txtinet.hxx>
56 : #include <cmdid.h>
57 : #include <wrtsh.hrc>
58 : #include "swabstdlg.hxx"
59 : #include "fldui.hrc"
60 : #include <SwRewriter.hxx>
61 :
62 : #include <com/sun/star/document/XDocumentProperties.hpp>
63 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
64 :
65 : #include <xmloff/odffields.hxx>
66 :
67 0 : void SwWrtShell::Insert(SwField &rFld)
68 : {
69 0 : ResetCursorStack();
70 0 : if(!CanInsert())
71 0 : return;
72 0 : StartAllAction();
73 :
74 0 : SwRewriter aRewriter;
75 0 : aRewriter.AddRule(UndoArg1, rFld.GetDescription());
76 :
77 0 : StartUndo(UNDO_INSERT, &aRewriter);
78 :
79 0 : bool bDeleted = false;
80 0 : const SwPaM* pAnnotationTextRange = NULL;
81 0 : if ( HasSelection() )
82 : {
83 0 : if ( rFld.GetTyp()->Which() == RES_POSTITFLD )
84 : {
85 : // for annotation fields:
86 : // - keep the current selection in order to create a corresponding annotation mark
87 : // - collapse cursor to its end
88 0 : if ( IsTableMode() )
89 : {
90 0 : GetTblCrs()->Normalize( false );
91 0 : const SwPosition rStartPos( *(GetTblCrs()->GetMark()->nNode.GetNode().GetCntntNode()), 0 );
92 0 : KillPams();
93 0 : EndPara();
94 0 : const SwPosition rEndPos( *GetCurrentShellCursor().GetPoint() );
95 0 : pAnnotationTextRange = new SwPaM( rStartPos, rEndPos );
96 : }
97 : else
98 : {
99 0 : NormalizePam( sal_False );
100 0 : const SwPaM& rCurrPaM = GetCurrentShellCursor();
101 0 : pAnnotationTextRange = new SwPaM( *rCurrPaM.GetPoint(), *rCurrPaM.GetMark() );
102 0 : ClearMark();
103 : }
104 : }
105 : else
106 : {
107 0 : bDeleted = DelRight() != 0;
108 : }
109 : }
110 :
111 0 : SwEditShell::Insert2(rFld, bDeleted);
112 :
113 0 : if ( pAnnotationTextRange != NULL )
114 : {
115 0 : if ( GetDoc() != NULL )
116 : {
117 0 : IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess();
118 0 : pMarksAccess->makeAnnotationMark( *pAnnotationTextRange, ::rtl::OUString() );
119 : }
120 0 : delete pAnnotationTextRange;
121 : }
122 :
123 0 : EndUndo();
124 0 : EndAllAction();
125 : }
126 :
127 : // Start the field update
128 :
129 0 : void SwWrtShell::UpdateInputFlds( SwInputFieldList* pLst )
130 : {
131 : // Go through the list of fields and updating
132 0 : SwInputFieldList* pTmp = pLst;
133 0 : if( !pTmp )
134 0 : pTmp = new SwInputFieldList( this );
135 :
136 0 : const sal_uInt16 nCnt = pTmp->Count();
137 0 : if(nCnt)
138 : {
139 0 : pTmp->PushCrsr();
140 :
141 0 : sal_Bool bCancel = sal_False;
142 0 : OString aDlgPos;
143 0 : for( sal_uInt16 i = 0; i < nCnt && !bCancel; ++i )
144 : {
145 0 : pTmp->GotoFieldPos( i );
146 0 : SwField* pField = pTmp->GetField( i );
147 0 : if(pField->GetTyp()->Which() == RES_DROPDOWN)
148 0 : bCancel = StartDropDownFldDlg( pField, sal_True, &aDlgPos );
149 : else
150 0 : bCancel = StartInputFldDlg( pField, sal_True, 0, &aDlgPos);
151 :
152 0 : if (!bCancel)
153 : {
154 : // Otherwise update error at multi-selection:
155 0 : pTmp->GetField( i )->GetTyp()->UpdateFlds();
156 : }
157 : }
158 0 : pTmp->PopCrsr();
159 : }
160 :
161 0 : if( !pLst )
162 0 : delete pTmp;
163 0 : }
164 :
165 : // Listener class: will close InputField dialog if input field(s)
166 : // is(are) deleted (for instance, by an extension) after the dialog shows up.
167 : // Otherwise, the for loop in SwWrtShell::UpdateInputFlds will crash when doing:
168 : // 'pTmp->GetField( i )->GetTyp()->UpdateFlds();'
169 : // on a deleted field.
170 0 : class FieldDeletionModify : public SwModify
171 : {
172 : public:
173 0 : FieldDeletionModify(AbstractFldInputDlg* pInputFieldDlg) : mpInputFieldDlg(pInputFieldDlg) {}
174 :
175 0 : void Modify( const SfxPoolItem* pOld, const SfxPoolItem *) SAL_OVERRIDE
176 : {
177 : // Input fields have been deleted: better to close the dialog
178 0 : if (pOld->Which() == RES_FIELD_DELETED)
179 : {
180 0 : mpInputFieldDlg->EndDialog(RET_CANCEL);
181 : }
182 0 : }
183 : private:
184 : AbstractFldInputDlg* mpInputFieldDlg;
185 : };
186 :
187 : // Start input dialog for a specific field
188 :
189 0 : sal_Bool SwWrtShell::StartInputFldDlg( SwField* pFld, sal_Bool bNextButton,
190 : Window* pParentWin, OString* pWindowState )
191 : {
192 :
193 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
194 : OSL_ENSURE(pFact, "Dialogdiet fail!");
195 0 : AbstractFldInputDlg* pDlg = pFact->CreateFldInputDlg(pParentWin, *this, pFld, bNextButton);
196 : OSL_ENSURE(pDlg, "Dialogdiet fail!");
197 0 : if(pWindowState && !pWindowState->isEmpty())
198 0 : pDlg->SetWindowState(*pWindowState);
199 :
200 : // Register for possible input field deletion while dialog is open
201 0 : FieldDeletionModify aModify(pDlg);
202 0 : GetDoc()->GetUnoCallBack()->Add(&aModify);
203 :
204 0 : sal_Bool bRet = RET_CANCEL == pDlg->Execute();
205 :
206 : // Dialog closed, remove modification listener
207 0 : GetDoc()->GetUnoCallBack()->Remove(&aModify);
208 :
209 0 : if(pWindowState)
210 0 : *pWindowState = pDlg->GetWindowState();
211 :
212 0 : delete pDlg;
213 0 : GetWin()->Update();
214 0 : return bRet;
215 : }
216 :
217 0 : sal_Bool SwWrtShell::StartDropDownFldDlg(SwField* pFld, sal_Bool bNextButton, OString* pWindowState)
218 : {
219 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
220 : OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
221 :
222 0 : AbstractDropDownFieldDialog* pDlg = pFact->CreateDropDownFieldDialog(NULL, *this, pFld, bNextButton);
223 : OSL_ENSURE(pDlg, "Dialogdiet fail!");
224 0 : if(pWindowState && !pWindowState->isEmpty())
225 0 : pDlg->SetWindowState(*pWindowState);
226 0 : sal_uInt16 nRet = pDlg->Execute();
227 0 : if(pWindowState)
228 0 : *pWindowState = pDlg->GetWindowState();
229 0 : delete pDlg;
230 0 : sal_Bool bRet = RET_CANCEL == nRet;
231 0 : GetWin()->Update();
232 0 : if(RET_YES == nRet)
233 : {
234 0 : GetView().GetViewFrame()->GetDispatcher()->Execute(FN_EDIT_FIELD, SFX_CALLMODE_SYNCHRON);
235 : }
236 0 : return bRet;
237 : }
238 :
239 : // Insert directory - remove selection
240 :
241 0 : void SwWrtShell::InsertTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet)
242 : {
243 0 : if(!CanInsert())
244 0 : return;
245 :
246 0 : if(HasSelection())
247 0 : DelRight();
248 :
249 0 : SwEditShell::InsertTableOf(rTOX, pSet);
250 : }
251 :
252 : // Update directory - remove selection
253 :
254 0 : sal_Bool SwWrtShell::UpdateTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet)
255 : {
256 0 : sal_Bool bResult = sal_False;
257 :
258 0 : if(CanInsert())
259 : {
260 0 : bResult = SwEditShell::UpdateTableOf(rTOX, pSet);
261 :
262 0 : if (pSet == NULL)
263 : {
264 0 : SwDoc *const pDoc_ = GetDoc();
265 0 : if (pDoc_)
266 : {
267 0 : pDoc_->GetIDocumentUndoRedo().DelAllUndoObj();
268 : }
269 : }
270 : }
271 :
272 0 : return bResult;
273 : }
274 :
275 : // handler for click on the field given as parameter.
276 : // the cursor is positioned on the field.
277 :
278 0 : void SwWrtShell::ClickToField( const SwField& rFld )
279 : {
280 : // cross reference field must not be selected because it moves the cursor
281 0 : if (RES_GETREFFLD != rFld.GetTyp()->Which())
282 : {
283 0 : StartAllAction();
284 0 : Right( CRSR_SKIP_CHARS, true, 1, false ); // Select the field.
285 0 : NormalizePam();
286 0 : EndAllAction();
287 : }
288 :
289 0 : bIsInClickToEdit = true;
290 0 : switch( rFld.GetTyp()->Which() )
291 : {
292 : case RES_JUMPEDITFLD:
293 : {
294 0 : sal_uInt16 nSlotId = 0;
295 0 : switch( rFld.GetFormat() )
296 : {
297 : case JE_FMT_TABLE:
298 0 : nSlotId = FN_INSERT_TABLE;
299 0 : break;
300 :
301 : case JE_FMT_FRAME:
302 0 : nSlotId = FN_INSERT_FRAME;
303 0 : break;
304 :
305 0 : case JE_FMT_GRAPHIC: nSlotId = SID_INSERT_GRAPHIC; break;
306 0 : case JE_FMT_OLE: nSlotId = SID_INSERT_OBJECT; break;
307 :
308 : }
309 :
310 0 : if( nSlotId )
311 : {
312 0 : StartUndo( UNDO_START );
313 : //#97295# immediately select the right shell
314 0 : GetView().StopShellTimer();
315 0 : GetView().GetViewFrame()->GetDispatcher()->Execute( nSlotId,
316 0 : SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD );
317 0 : EndUndo( UNDO_END );
318 : }
319 : }
320 0 : break;
321 :
322 : case RES_MACROFLD:
323 : {
324 0 : const SwMacroField *pFld = (const SwMacroField*)&rFld;
325 0 : const OUString sText( rFld.GetPar2() );
326 0 : OUString sRet( sText );
327 0 : ExecMacro( pFld->GetSvxMacro(), &sRet );
328 :
329 : // return value changed?
330 0 : if( sRet != sText )
331 : {
332 0 : StartAllAction();
333 0 : ((SwField&)rFld).SetPar2( sRet );
334 0 : ((SwField&)rFld).GetTyp()->UpdateFlds();
335 0 : EndAllAction();
336 0 : }
337 : }
338 0 : break;
339 :
340 : case RES_GETREFFLD:
341 0 : StartAllAction();
342 : SwCrsrShell::GotoRefMark( ((SwGetRefField&)rFld).GetSetRefName(),
343 0 : ((SwGetRefField&)rFld).GetSubType(),
344 0 : ((SwGetRefField&)rFld).GetSeqNo() );
345 0 : EndAllAction();
346 0 : break;
347 :
348 : case RES_INPUTFLD:
349 : {
350 0 : const SwInputField* pInputField = dynamic_cast<const SwInputField*>(&rFld);
351 0 : if ( pInputField == NULL )
352 : {
353 0 : StartInputFldDlg( (SwField*)&rFld, sal_False );
354 : }
355 : }
356 0 : break;
357 :
358 : case RES_SETEXPFLD:
359 0 : if( ((SwSetExpField&)rFld).GetInputFlag() )
360 0 : StartInputFldDlg( (SwField*)&rFld, sal_False );
361 0 : break;
362 : case RES_DROPDOWN :
363 0 : StartDropDownFldDlg( (SwField*)&rFld, sal_False );
364 0 : break;
365 : default:
366 : SAL_WARN_IF(rFld.IsClickable(), "sw", "unhandled clickable field!");
367 : }
368 :
369 0 : bIsInClickToEdit = false;
370 0 : }
371 :
372 0 : void SwWrtShell::ClickToINetAttr( const SwFmtINetFmt& rItem, sal_uInt16 nFilter )
373 : {
374 0 : if( rItem.GetValue().isEmpty() )
375 0 : return ;
376 :
377 0 : bIsInClickToEdit = true;
378 :
379 : // At first run the possibly set ObjectSelect Macro
380 0 : const SvxMacro* pMac = rItem.GetMacro( SFX_EVENT_MOUSECLICK_OBJECT );
381 0 : if( pMac )
382 : {
383 0 : SwCallMouseEvent aCallEvent;
384 0 : aCallEvent.Set( &rItem );
385 0 : GetDoc()->CallEvent( SFX_EVENT_MOUSECLICK_OBJECT, aCallEvent, false );
386 : }
387 :
388 : // So that the implementation of templates is displayed immediately
389 0 : ::LoadURL( *this, rItem.GetValue(), nFilter, rItem.GetTargetFrame() );
390 0 : const SwTxtINetFmt* pTxtAttr = rItem.GetTxtINetFmt();
391 0 : if( pTxtAttr )
392 : {
393 0 : const_cast<SwTxtINetFmt*>(pTxtAttr)->SetVisited( true );
394 0 : const_cast<SwTxtINetFmt*>(pTxtAttr)->SetVisitedValid( true );
395 : }
396 :
397 0 : bIsInClickToEdit = false;
398 : }
399 :
400 0 : bool SwWrtShell::ClickToINetGrf( const Point& rDocPt, sal_uInt16 nFilter )
401 : {
402 0 : bool bRet = false;
403 0 : OUString sURL;
404 0 : OUString sTargetFrameName;
405 0 : const SwFrmFmt* pFnd = IsURLGrfAtPos( rDocPt, &sURL, &sTargetFrameName );
406 0 : if( pFnd && !sURL.isEmpty() )
407 : {
408 0 : bRet = true;
409 : // At first run the possibly set ObjectSelect Macro
410 0 : const SvxMacro* pMac = &pFnd->GetMacro().GetMacro( SFX_EVENT_MOUSECLICK_OBJECT );
411 0 : if( pMac )
412 : {
413 0 : SwCallMouseEvent aCallEvent;
414 0 : aCallEvent.Set( EVENT_OBJECT_URLITEM, pFnd );
415 0 : GetDoc()->CallEvent( SFX_EVENT_MOUSECLICK_OBJECT, aCallEvent, false );
416 : }
417 :
418 0 : ::LoadURL(*this, sURL, nFilter, sTargetFrameName);
419 : }
420 0 : return bRet;
421 : }
422 :
423 0 : void LoadURL( SwViewShell& rVSh, const OUString& rURL, sal_uInt16 nFilter,
424 : const OUString& rTargetFrameName )
425 : {
426 : OSL_ENSURE( !rURL.isEmpty(), "what should be loaded here?" );
427 0 : if( rURL.isEmpty() )
428 0 : return ;
429 :
430 : // The shell could be 0 also!!!!!
431 0 : if ( !rVSh.ISA(SwCrsrShell) )
432 0 : return;
433 :
434 : //A CrsrShell is always a WrtShell
435 0 : SwWrtShell &rSh = (SwWrtShell&)rVSh;
436 :
437 0 : SwDocShell* pDShell = rSh.GetView().GetDocShell();
438 : OSL_ENSURE( pDShell, "No DocShell?!");
439 0 : OUString sTargetFrame(rTargetFrameName);
440 0 : if (sTargetFrame.isEmpty() && pDShell)
441 : {
442 : using namespace ::com::sun::star;
443 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
444 0 : pDShell->GetModel(), uno::UNO_QUERY_THROW);
445 : uno::Reference<document::XDocumentProperties> xDocProps
446 0 : = xDPS->getDocumentProperties();
447 0 : sTargetFrame = xDocProps->getDefaultTarget();
448 : }
449 :
450 0 : OUString sReferer;
451 0 : if( pDShell && pDShell->GetMedium() )
452 0 : sReferer = pDShell->GetMedium()->GetName();
453 0 : SfxViewFrame* pViewFrm = rSh.GetView().GetViewFrame();
454 0 : SfxFrameItem aView( SID_DOCFRAME, pViewFrm );
455 0 : SfxStringItem aName( SID_FILE_NAME, rURL );
456 0 : SfxStringItem aTargetFrameName( SID_TARGETNAME, sTargetFrame );
457 0 : SfxStringItem aReferer( SID_REFERER, sReferer );
458 :
459 0 : SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, false );
460 : //#39076# Silent can be removed accordingly to SFX.
461 0 : SfxBoolItem aBrowse( SID_BROWSE, true );
462 :
463 0 : if( nFilter & URLLOAD_NEWVIEW )
464 0 : aTargetFrameName.SetValue( OUString("_blank") );
465 :
466 : const SfxPoolItem* aArr[] = {
467 : &aName,
468 : &aNewView, /*&aSilent,*/
469 : &aReferer,
470 : &aView, &aTargetFrameName,
471 : &aBrowse,
472 : 0L
473 0 : };
474 :
475 : pViewFrm->GetDispatcher()->GetBindings()->Execute( SID_OPENDOC, aArr,
476 0 : SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD );
477 : }
478 :
479 0 : void SwWrtShell::NavigatorPaste( const NaviContentBookmark& rBkmk,
480 : const sal_uInt16 nAction )
481 : {
482 0 : if( EXCHG_IN_ACTION_COPY == nAction )
483 : {
484 : // Insert
485 0 : OUString sURL = rBkmk.GetURL();
486 : // Is this is a jump within the current Doc?
487 0 : const SwDocShell* pDocShell = GetView().GetDocShell();
488 0 : if(pDocShell->HasName())
489 : {
490 0 : const OUString rName = pDocShell->GetMedium()->GetURLObject().GetURLNoMark();
491 :
492 0 : if (sURL.startsWith(rName))
493 : {
494 0 : if (sURL.getLength()>rName.getLength())
495 : {
496 0 : sURL = sURL.copy(rName.getLength());
497 : }
498 : else
499 : {
500 0 : sURL = OUString();
501 : }
502 0 : }
503 : }
504 0 : SwFmtINetFmt aFmt( sURL, OUString() );
505 0 : InsertURL( aFmt, rBkmk.GetDescription() );
506 : }
507 : else
508 : {
509 0 : SwSectionData aSection( FILE_LINK_SECTION, GetUniqueSectionName() );
510 0 : OUString aLinkFile( rBkmk.GetURL().getToken(0, '#') );
511 0 : aLinkFile += OUString(sfx2::cTokenSeparator);
512 0 : aLinkFile += OUString(sfx2::cTokenSeparator);
513 0 : aLinkFile += rBkmk.GetURL().getToken(1, '#');
514 0 : aSection.SetLinkFileName( aLinkFile );
515 0 : aSection.SetProtectFlag( true );
516 0 : const SwSection* pIns = InsertSection( aSection );
517 0 : if( EXCHG_IN_ACTION_MOVE == nAction && pIns )
518 : {
519 0 : aSection = SwSectionData(*pIns);
520 0 : aSection.SetLinkFileName( OUString() );
521 0 : aSection.SetType( CONTENT_SECTION );
522 0 : aSection.SetProtectFlag( false );
523 :
524 : // the update of content from linked section at time delete
525 : // the undostack. Then the change of the section dont create
526 : // any undoobject. - BUG 69145
527 0 : sal_Bool bDoesUndo = DoesUndo();
528 0 : SwUndoId nLastUndoId(UNDO_EMPTY);
529 0 : if (GetLastUndoInfo(0, & nLastUndoId))
530 : {
531 0 : if (UNDO_INSSECTION != nLastUndoId)
532 : {
533 0 : DoUndo(false);
534 : }
535 : }
536 0 : UpdateSection( GetSectionFmtPos( *pIns->GetFmt() ), aSection );
537 0 : DoUndo( bDoesUndo );
538 0 : }
539 : }
540 0 : }
541 :
542 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|